Aller au contenu
couillerot

Quick App - Prévisions Météo WeatherBit v1.2

Recommended Posts

Autre point, puisqu'il n'y a plus besoin d'écrire dans la variable "lat" de l'onglet du QA, et que la variable "lat" n'est pas utilisée dans le reste du code, au risque de faire une bêtise je viens de remplacer ça :

	lat = api.get("/settings/location").latitude
	lati = tostring(lat)

 

 

par ça :

	lati = tostring(api.get("/settings/location").latitude)

 

:D

Modifié par Fredmas

Partager ce message


Lien à poster
Partager sur d’autres sites

Parfait !

 

Le QA est loin d'être optimisé car il s'agissait du deuxième ou troisième QA/VD que je codais donc débutant inside... :)

 

Stef

Partager ce message


Lien à poster
Partager sur d’autres sites

T'inquiètes, je serais bien mal placé pour critiquer vu mon niveau  ;)

Et je te remercie encore beaucoup pour ton travail et ces QA très utiles.

 

Grâce à tes 2 QA météo (état et prévision), j'ai gagné beaucoup de temps, notamment dans la construction du "http:request", du "response.data", et du json en général que je ne connais pas.

Là je pense avoir à peu près pas trop mal compris :P, et je me suis fait une version dans un seul QA qui fait le tout : état de la journée (réutilisable par la box et d'autres QA) et prévisions (réutilisable par d'autres QA).

Maintenant je joue avec et je modifie au fur et à mesure mais surtout afin de comprendre pour la maintenance à venir :D

Partager ce message


Lien à poster
Partager sur d’autres sites

Mais du coup plus je joue, plus je crois apprendre, et plus j'ai des questions :2:

Partager ce message


Lien à poster
Partager sur d’autres sites

ça c'est normal, plus on apprend, plus on se rend compte du chemin qui reste à parcourir pour maitriser le sujet :D

 

Pas valable que pour le LUA bien sûr...

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Sitting in a long meeting and being a bit bored I did some hacking on your code... I guess it's a matter of taste but there are no globals anymore :-)

Your original version may make more sense to you, so just see it as an example of alternative way of coding.

function QuickApp:onInit()
  local key_id = self:getVariable("key_id")
  local lati = tostring(api.get("/settings/location").latitude)
  self:setVariable("latitude", string.format("%.2f", lati))
  local long = tostring(api.get("/settings/location").longitude)
  self:setVariable("longitude", string.format("%.2f", long))
  self.url = "https://api.weatherbit.io/v2.0/forecast/daily?lat="..lati.."&lon="..long.."&days=5&lang=fr&key="..key_id
  
  self.icons = {}
  for i=1,11 do
    self.icons[i]=tonumber(self:getVariable("id_icon"..i))
  end
  
  self:loop()
end
-----
function QuickApp:loop()
  local http = net.HTTPClient()
  http:request(self.url, {
      options = {
        method = 'GET'
      },
      success = function(response)
        if response.status == 200 then
          if response.data and response.data ~= "" then
            local jsonTable = json.decode(response.data)
            local gfx = jsonTable.data[1].weather.code
            local city = jsonTable.city_name
            local citycode = jsonTable.country_code
------------------------------------------------------------------------------
----------------------------- CHOIX DE L'ICON --------------------------------
------------------------------------------------------------------------------
            local codeicon,icon = tonumber(gfx),1
            if codeicon == 610 then                     icon=1 end
            if codeicon >= 803 and codeicon <= 804 then icon=2 end
            if codeicon >= 700 and codeicon <= 751 then icon=3 end
            if codeicon >= 500 and codeicon <= 522 then icon=4 end
            if codeicon >= 601 and codeicon <= 623 then icon=5 end
            if codeicon == 600 then                     icon=6 end
            if codeicon == 800 then                     icon=7 end
            if codeicon >= 801 and codeicon <= 802 then icon=8 end
            if codeicon >= 300 and codeicon <= 302 then icon=9 end
            if codeicon >= 230 and codeicon <= 233 then icon=10 end
            if codeicon >= 200 and codeicon <= 202 then icon=11 end
            self:updateProperty("deviceIcon", self.icons[icon])

            local Var_Heure = os.date("%d.%m.%Y à %Hh%M")

------------------------------------------------------------------------------              
-------------------------- CONSTRUCTION DES TABLES ---------------------------
------------------------------------------------------------------------------
            local week = {[0] = "DIMANCHE", [1] = "LUNDI", [2] = "MARDI", [3] = "MERCREDI", [4] = "JEUDI", [5] = "VENDREDI", [6] = "SAMEDI"}
            local month = {"JANVIER", "FEVRIER", "MARS", "AVRIL", "MAI", "JUIN", "JUILLET", "AOUT", "SEPTEMBRE", "OCTOBRE", "NOVEMBRE", "DECEMBRE"}

            local day = os.date("%w")-1
            local data = {}
------------------
----- JOUR -----
------------------
            for i=1,5 do
              data[i]={}
              local m = data[i]
              m.precipday = jsonTable.data[i].precip
              m.dayweather = jsonTable.data[i].weather.description
              m.snowday = jsonTable.data[i].snow
              m.lowtempday = jsonTable.data[i].low_temp
              m.maxtempday = jsonTable.data[i].max_temp
              m.windspeed = jsonTable.data[i].wind_spd
              m.winddir = jsonTable.data[i].wind_cdir
              m.m,m.j = jsonTable.data[i].datetime:match("%d+%-(%d+)%-(%d+)")
              m.j,m.m = tonumber(m.j),tonumber(m.m)
              m.day = (tonumber(day)+i) % 7
            end

------------------------------------------------------------------------------
--------------------------- CONSTRUCTION DES LABELS --------------------------
------------------------------------------------------------------------------
            local function setView(elm,fmt,...) self:updateView(elm,"text",string.format(fmt,...)) end
            for i=1,5 do
              local m = data[i]
              setView(
                "labelday"..i, "%s %s %s\r%s\rT° mini : %s °c - T° maxi : %s°c\r%.1f mm de pluie | %.1f mm de neige\rVent  %.1f km/h (%s)",
                week[m.day],m.j,month[m.m],m.dayweather,m.lowtempday,m.maxtempday,m.precipday,m.snowday,m.windspeed* 3.6,m.winddir
              )

            end
            setView("labelMAJ", "Station de %s (%s) - MAJ le %s",city,citycode,Var_Heure)
-----------------------------
            local precipitation_arrosage = string.format("%.2f", data[1].precipday + data[2].precipday)
            fibaro.setGlobalVariable("prevision_pluie", tostring(precipitation_arrosage))
----------
          else
            self:error("empty response data")
          end
        else
          self:error("status=" .. tostring(response.status))
        end
      end,
      error = function(err)
        self:error(err)
      end
    })    
  fibaro.setTimeout(1000 * 60 * 60 * 2, function()
      self:loop()
    end)
end

 

Modifié par jang
  • Like 2

Partager ce message


Lien à poster
Partager sur d’autres sites

...and the reason it's pretty quick to run your original QA, step through it, understand what it's doing and then modifying it, is that it runs very well in my new little offline emulator

Révélation

local _=loadfile and loadfile("TQAE.lua"){
  user="admin", 
  pwd="admin", 
  host="192.168.1.57",
  verbose=false,
  modPath = "TQAEmodules/",
  temp = "temp/",
--  startTime="12/24/2024-07:00", 
  terminate = false,
--  logLevel=5
}

-- luacheck: globals ignore QuickApp json api fibaro net

--%%name="WeatherBit"
--%%quickVars={key_id="1c28cbe9096646faa789fcc5824f6f76"} -- I changed 4 digits...
--%%u1={label="labelday1", text=""}
--%%u2={label="labelday2", text=""}
--%%u3={label="labelday3", text=""}
--%%u4={label="labelday4", text=""}
--%%u5={label="labelday5", text=""}
--%%u6={label="labelMAJ", text=""}

------------------ Code ------------------------

function QuickApp:onInit()
  local key_id = self:getVariable("key_id")
  local lati = tostring(api.get("/settings/location").latitude)
  self:setVariable("latitude", string.format("%.2f", lati))
  local long = tostring(api.get("/settings/location").longitude)
  self:setVariable("longitude", string.format("%.2f", long))
  self.url = "https://api.weatherbit.io/v2.0/forecast/daily?lat="..lati.."&lon="..long.."&days=5&lang=fr&key="..key_id

  self.icons = {}
  for i=1,11 do
    self.icons=tonumber(self:getVariable("id_icon"..i))
  end

  self:loop()
end
-----
function QuickApp:loop()
  local http = net.HTTPClient()
  http:request(self.url, {
      options = {
        method = 'GET'
      },
      success = function(response)
        if response.status == 200 then
          if response.data and response.data ~= "" then
            local jsonTable = json.decode(response.data)
            local gfx = jsonTable.data[1].weather.code
            local city = jsonTable.city_name
            local citycode = jsonTable.country_code
------------------------------------------------------------------------------
----------------------------- CHOIX DE L'ICON --------------------------------
------------------------------------------------------------------------------
            local codeicon,icon = tonumber(gfx),1
            if codeicon == 610 then                     icon=1 end
            if codeicon >= 803 and codeicon <= 804 then icon=2 end
            if codeicon >= 700 and codeicon <= 751 then icon=3 end
            if codeicon >= 500 and codeicon <= 522 then icon=4 end
            if codeicon >= 601 and codeicon <= 623 then icon=5 end
            if codeicon == 600 then                     icon=6 end
            if codeicon == 800 then                     icon=7 end
            if codeicon >= 801 and codeicon <= 802 then icon=8 end
            if codeicon >= 300 and codeicon <= 302 then icon=9 end
            if codeicon >= 230 and codeicon <= 233 then icon=10 end
            if codeicon >= 200 and codeicon <= 202 then icon=11 end
            self:updateProperty("deviceIcon", self.icons[icon])

            local Var_Heure = os.date("%d.%m.%Y à %Hh%M")

------------------------------------------------------------------------------              
-------------------------- CONSTRUCTION DES TABLES ---------------------------
------------------------------------------------------------------------------
            local week = {[0] = "DIMANCHE", [1] = "LUNDI", [2] = "MARDI", [3] = "MERCREDI", [4] = "JEUDI", [5] = "VENDREDI", [6] = "SAMEDI"}
            local month = {"JANVIER", "FEVRIER", "MARS", "AVRIL", "MAI", "JUIN", "JUILLET", "AOUT", "SEPTEMBRE", "OCTOBRE", "NOVEMBRE", "DECEMBRE"}

            local day = os.date("%w")-1
            local data = {}
------------------
----- JOUR -----
------------------
            for i=1,5 do
              data={}
              local m = data
              m.precipday = jsonTable.data.precip
              m.dayweather = jsonTable.data.weather.description
              m.snowday = jsonTable.data.snow
              m.lowtempday = jsonTable.data.low_temp
              m.maxtempday = jsonTable.data.max_temp
              m.windspeed = jsonTable.data.wind_spd
              m.winddir = jsonTable.data.wind_cdir
              m.m,m.j = jsonTable.data.datetime:match("%d+%-(%d+)%-(%d+)")
              m.j,m.m = tonumber(m.j),tonumber(m.m)
              m.day = (tonumber(day)+i) % 7
            end

------------------------------------------------------------------------------
--------------------------- CONSTRUCTION DES LABELS --------------------------
------------------------------------------------------------------------------
            local function setView(elm,fmt,...) self:updateView(elm,"text",string.format(fmt,...)) end
            for i=1,5 do
              local m = data
              setView(
                "labelday"..i, "%s %s %s\r\rT° mini : °c - T° maxi : %s°c\r%.1f mm de pluie | %.1f mm de neige\rVent  %.1f km/h (%s)",
                week[m.day],m.j,month[m.m],m.dayweather,m.lowtempday,m.maxtempday,m.precipday,m.snowday,m.windspeed* 3.6,m.winddir
              )
            end
            setView("labelMAJ", "Station de %s (%s) - MAJ le %s",city,citycode,Var_Heure)
-----------------------------
            local precipitation_arrosage = string.format("%.2f", data[1].precipday + data[2].precipday)
            fibaro.setGlobalVariable("prevision_pluie", tostring(precipitation_arrosage))
----------
          else
            self:error("empty response data")
          end
        else
          self:error("status=" .. tostring(response.status))
        end
      end,
      error = function(err)
        self:error(err)
      end
    })    
  fibaro.setTimeout(1000 * 60 * 60 * 2, function()
      self:loop()
    end)
end

 

Partager ce message


Lien à poster
Partager sur d’autres sites

thanks jang for your alternative code !

it's really interesting :74:

 

Stef

Partager ce message


Lien à poster
Partager sur d’autres sites

Thank you for your alternative proposal @jang

As usual, I remember discussions about intervalRunner, you give us some « food » for the opportunity to think, learn and improve.

At least for newbie like me in QA and LUA :D

Partager ce message


Lien à poster
Partager sur d’autres sites

There was some missing fields in the setView call, fixed.

What's missing is to check the user provided quickAppVariables that they are valid and warn if not.

Partager ce message


Lien à poster
Partager sur d’autres sites
Il y a 23 heures, jang a dit :

local function setView(elm,fmt,...)
  	self:updateView(elm,"text",string.format(fmt,...))
end
for i=1,5 do
	local m = data[i]
	setView(
    	"labelday"..i, "%s %s %s\r%s\rT° mini : %s °c - T° maxi : %s°c\r%.1f mm de pluie | %.1f mm de neige\rVent  %.1f km/h (%s)",
    	week[m.day],m.j,month[m.m],m.dayweather,m.lowtempday,m.maxtempday,m.precipday,m.snowday,m.windspeed* 3.6,m.winddir
    )
end
setView("labelMAJ", "Station de %s (%s) - MAJ le %s",city,citycode,Var_Heure)

 

 

Grâce à ces lignes de codes., je découvre le fonctionnement de 2 nouveaux trucs :D :

 

#1

Citation

- des "..." en paramètre de la fonction

Je pense que ça veut dire autant de paramètres et d'arguments à suivre dans l'appel de la fonction.

 

 

#2

Citation

- des "%s" dans l'appel de la fonction

Je pense que ça remplace le "%s" par les paramètres à suivre et dans l'ordre. Par exemple string.format("%s %q", "Hello", "Lua User !")  ==>  Hello "Lua user!"

Mais du coup je ne comprends pas pourquoi il manque les 3 "%s" correspondant à "m.precipday, m.snowday ,m.windspeed* 3.6". Ca a l'air d'être comme si le %.1f du format suffisait à la place du %s ???

 

Je viens de chercher dans plusieurs doc pour "apprendre" à m'en servir, mais je ne trouve pas tout :lol:

Ai-je bien compris le fonctionnement ? :P

Partager ce message


Lien à poster
Partager sur d’autres sites

Bonjour,

 

Le %s c'est pour le type string. Le %.1f, c'est pour le type float avec une précision de 1 chiffre après la virgule.

Dans "%s %d %.1f", "Toto", 25, 0.55 tu aurais "Toto 25 0.5" dans ta chaîne.

 

Partager ce message


Lien à poster
Partager sur d’autres sites

 

Il y a 18 heures, Fredmas a dit :

But suddenly I don't understand why the 3 "% s" corresponding to "m.precipday, m.snowday, m.windspeed * 3.6" are missing. Seems to be like the% .1f of the format suffices instead of the% s ???

 

In the first version I missed some % directives. It should be fixed in the last edit of the post.

Il y a 18 heures, Fredmas a dit :

Did I understand the operation correctly? : P

Yes :P

Partager ce message


Lien à poster
Partager sur d’autres sites

@Kana-chan @jang Thank you for your answers both ;)

 

One question: if we want to keep a "%" as a string printed in the text, how can we do?

The best is a clear example :D How to modify the code below to have this result "Humidity is 50%" in the label?

local function setView(elm,fmt,...) self:updateView(elm,"text",string.format(fmt,...)) end
for i=1,5 do
	local m = data[i]
	setView(
    	"labelday"..i, "Humidity is %s",
        m.humidity
	)
 end

Is there a special caracter to write before the % I want to print in the label?

Partager ce message


Lien à poster
Partager sur d’autres sites

I have a solution, but not so nice from my point of view...

local function setView(elm,fmt,...) self:updateView(elm,"text",string.format(fmt,...)) end
for i=1,5 do
	local m = data[i]
	setView(
    	"labelday"..i, "Humidity is %s%s",
        m.humidity,"%"
	)
 end

 

Partager ce message


Lien à poster
Partager sur d’autres sites

setView("Humidity is %s%%",50)

%% -> %

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Bonjour,

 

En général, lorsque dans une chaîne de caractères un caractère ne s'affiche pas comme voulu ou provoque une erreur, il suffit de le doubler pour avoir le caractère qui s'affiche comme on veut.

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci, c'est noté. Je ne savais pas  :60:

Partager ce message


Lien à poster
Partager sur d’autres sites
Le 01/09/2021 à 17:08, Fredmas a dit :

Je vais tester dans les prochains jours, et je ne manquerai pas de te faire signe en cas de problème :2:

 

D'ailleurs, sans vouloir ouvrir de longs débats, comme la fiabilité des précisions météo a toujours été discutée depuis des années peu importe les supports et usages, pourquoi as-tu choisi WeatherBit et pas un autre fournisseur ?

Je demande principalement par curiosité vu que je vais bientôt l'utiliser également grâce à ton QA :P

Le 01/09/2021 à 17:22, couillerot a dit :

Pourquoi Weatherbit ?

 

tout simplement, parce que j'avais le VD sous la HC2... après je n'ai pas approfondi plus le truc sur la précision des prévisions, ni effectué par exemple un comparo avec les autres fournisseurs. Une prévision reste une prévision c'est-à-dire une tendance. Je me sers de ce QA principalement pour mon arrosage auto et je n'ai pas eu de grosses surprises jusque là ;)

 

Stef

 

Bon, histoire de jouer un peu, j'en ai essayé d'autres :

 

Meteo-Concept (cocorico) pas mal mais manque d'info. J'ai abandonné.

 

OpenWeather pas mal avec autant d'infos que WeatherBit, par contre j'ai régulièrement mon QA qui crash.

Pour isoler le problème, j'ai tout supprimé et gardé uniquement le response.data sans aucune action derrière histoire de simplement récolter la réponse de leur API. Et j'ai toujours le QA qui crash de temps en temps dont les 2 messages les plus réguliers sont :

[12.10.2021] [09:00:21] [ERROR] [QUICKAPP82]: QuickApp crashed
[12.10.2021] [09:00:21] [ERROR] [QUICKAPP82]: /usr/share/lua/5.3/json/decode/util.lua:35: unexpected character @ character: 3531 0:3531 ["] line:

et

[12.10.2021] [10:00:32] [ERROR] [QUICKAPP79]: QuickApp crashed
[12.10.2021] [10:00:32] [ERROR] [QUICKAPP79]: /usr/share/lua/5.3/json/decode.lua:91: Unclosed elements present

 

Je n'y connais rien en json. Ces messages parlent à quelqu'un ?

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

×