[LUA] Quantité de précipitation avec OpenWeatherMap
Publié : 17 janv. 2021, 18:40
Bonjour à tous et bonne année.
J'ouvre ce topic suite à la remarque de Keros (sur ce topic: viewtopic.php?f=17&t=9892) afin de mieux mettre en avant et détailler ce tutoriel.
Avant toute chose, sachez que je débute en Lua et avec Domoticz. Je suis loin d'être un expert et je reste bien évidemment à l'écoute de toutes remarques et conseils.
Passons aux choses sérieuse!
Comment récupérer des données cumulées de précipitations annoncées sur 2h, 4h, 6h, 12h (et d'autres, si l'on veut) ?
Prérequis:
Je suis partie du script de joebuz (viewtopic.php?p=82679#p82679) pour réaliser cette partie de script. Je vous conseil d'y jeter un œil attentif avant toute chose.
Naturellement, vous n’êtes pas obligé d'utiliser ce même code. Si vous avez déjà implémenté OPW dans votre Domoticz, vous ne voudriez pas tout perdre. Ne vous inquiétez pas, je vous préciserai, durant ce tuto, quelle partie il faudra ajouter et où. Le seul réel prérequis est d'avoir ces lignes (ou équivalentes) permettant d'obtenir un JSON des prévisions:
C'est pourquoi, avant de vous attaquer à cette partie je ne peux que vous conseiller de bien suivre le tuto de Keros (rappel: viewtopic.php?f=17&t=9892) et de bien comprendre les différentes parties. Je pars du principe que ces notions sont acquises, je ne m'attarderai pas dessus.
Objectif:
L'objectif de notre projet est donc de récupérer les quantités de précipitions cumulées sur différents intervalles de temps. Puis, stocker ces données dans des Device de précipitation.
Problématique:
En discutant ici, je me suis rendu compte que plusieurs personnes désiraient avoir ces informations mais ne savaient pas comment faire. Effectivement, l'un des problèmes est que ces informations ne sont pas dans le JSON (en tout cas pas directement comme l'avoir avec d'autres informations comme le pourcentage d'humidité).
Réalisation:
Nous voilà à la partie la plus importante. La solution.
Mais avant d'aller directement à la solution, je vais vous expliquer comment en arriver là. Cela vous permettra de bien/mieux comprendre mon code. Avouez que c'est plus intéressant de comprendre ce que l'on fait, non?
Partie JSON:
Tout d'abord, regardons le JSON car une partie de la solution se trouve dedans. Vous pouvez voir qu'il existe des menus déroulants (des nœuds) qui se nomment "current", "minutely" et... "hourly". Oui, "hourly", c'est à des prévisions par heure.
Voilà c'est bon, le tuto est fini
Non, évidemment que le tuto n'est pas fini. Mais presque. On voit que le noeud contient lui même d'autres nœuds nommé 0, 1, 2, 3...
Déroulons ces noeuds (ici le 40): Ainsi, ici, on retrouve les différentes infos correspondant aux prévisions dans 40h. C'est la dernière ligne qui nous intéresse. Elle nous donne la quantité de pluie prévue pour cette heure (j'ai choisi ce noeud car je n'avais pas de pluie annoncée avant
). Attention, c'est bien la quantité de pluie prévue pour l'heure 40 seule, pas une quantité cumulée (voir: https://openweathermap.org/api/one-call-api).
Super... mais on fait quoi maintenant ?
Je m'en fiche qu'il pleuve 0.12 mm dans 40h !
Et moi aussi
.
Revenons à notre problématique: Une quantité de pluie cumulé en 2h (ou en autant de temps que vous voulez). Et comment on obtient ça ? Et bien, en additionnant les quantité de pluie pour ces 2 premières heures (dans ce cas).
C'est là où l'on va mettre les mains dans le cambouis. Allez! Passons à la partie sur le LUA!
Partie LUA:
Vous savez comment récupérer un JSON avec LUA (et donc Domoticz), comment l'ouvrir, le lire... On ne va pas revenir là-dessus.
J'ai besoin d'avoir, au maximum, le cumulé des précipitations prévues pour les 12 prochaines heures.
Il me faut donc parcourir les 12 prochaines prévisions horaires. C'est ce que je fais là:
Je déclare une somme (somme des quantités de précipitations) égale à 0 au début. A chaque itération de ma boucle for, on regarde si une précipitation est prévue. Si oui, alors on additionne cette quantité à la somme.
Dans cette boucle, vous pouvez voir un bloc "if". Son but est de vérifier où l'on est. Par exemple, if (i == 2) then , cela signifie que l'on en est à la prévision pour la prochaine 2eme heure. A ce moment là, on a donc additionné les précipitations prévues pour la prochaine heure et cette seconde heure. On affecte donc sa valeur à la variable représentant la quantité pour les deux prochaines heures.
Je récupère les précipitations avec jsonValeur.hourly.rain["1h"]. Comprenez par là que la variable i, qui s’incrémenter à chaque parcours de la boucle (de 1 à 12), permet de récupérer les données correspondantes à cette heure. Ensuite, j'ai dû écrire ["1h"] pour pouvoir récupérer les données de précipitations seule.
Partie Domoticz:
Si l'on veut stocker ces valeurs dans des Devices, il faut les créer. J'ai utilisé des Devices Précipitaitons. Créez-en autant que besoin(4 dans le cas décrit dans ce tuto). Notez leur Idx.
Ensuite, dans le script LUA on déclare nos devices (enfin leur Idx plus précisement).
Maintenant mettons à jour nos Devices (cette partie se place après la boucle for de la somme):
Et voilà.
Le code en entier:
N'oubliez pas que cela reste un tutoriel. Libre à vous d'adapter ce que j'ai fais selon vos besoins. Si vous voulez plus de données, moins de données, un intervalle de temps plus grand... Faites. Sachez simplement que les prévisions sont limité à 48h avec OWM dans sa version gratuite.
Dans mon cas, j'ai considéré comme précipitation neige et pluie indifféremment. Vous pouvez faire le distinguo si tel est votre envie/besoin.
Cette version est une version "beta". Je ne l'ai pas encore testé en long, en large et en travers. Si vous rencontrez des problèmes avec n'hesitez pas à me faire remonter ça. N'hésitez pas non plus, si vous avez des questions.
Je pense ajouter à ce script les probabilités de précipitation. Si cela vous intéresse, je vous partagerai ça.
J'ouvre ce topic suite à la remarque de Keros (sur ce topic: viewtopic.php?f=17&t=9892) afin de mieux mettre en avant et détailler ce tutoriel.
Avant toute chose, sachez que je débute en Lua et avec Domoticz. Je suis loin d'être un expert et je reste bien évidemment à l'écoute de toutes remarques et conseils.
Passons aux choses sérieuse!
Comment récupérer des données cumulées de précipitations annoncées sur 2h, 4h, 6h, 12h (et d'autres, si l'on veut) ?
Prérequis:
Je suis partie du script de joebuz (viewtopic.php?p=82679#p82679) pour réaliser cette partie de script. Je vous conseil d'y jeter un œil attentif avant toute chose.
Naturellement, vous n’êtes pas obligé d'utiliser ce même code. Si vous avez déjà implémenté OPW dans votre Domoticz, vous ne voudriez pas tout perdre. Ne vous inquiétez pas, je vous préciserai, durant ce tuto, quelle partie il faudra ajouter et où. Le seul réel prérequis est d'avoir ces lignes (ou équivalentes) permettant d'obtenir un JSON des prévisions:
Code : Tout sélectionner
--json = (loadfile "/home/votrenomutilisé/domoticz/scripts/lua/JSON.lua")() -- For Linux
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")() -- for PI
--json = (loadfile "/volume1/@appstore/domoticz/var/scripts/lua/JSON.lua")() -- For SynoCode : Tout sélectionner
config=assert(io.popen('/usr/bin/curl "https://api.openweathermap.org/data/2.5/onecall?lat='..lat..'&lon='..long..'&appid='..api..'&lang=fr&units=metric"'))
blocjson = config:read('*all')
config:close()
jsonValeur = json:decode(blocjson)Objectif:
L'objectif de notre projet est donc de récupérer les quantités de précipitions cumulées sur différents intervalles de temps. Puis, stocker ces données dans des Device de précipitation.
Problématique:
En discutant ici, je me suis rendu compte que plusieurs personnes désiraient avoir ces informations mais ne savaient pas comment faire. Effectivement, l'un des problèmes est que ces informations ne sont pas dans le JSON (en tout cas pas directement comme l'avoir avec d'autres informations comme le pourcentage d'humidité).
Réalisation:
Nous voilà à la partie la plus importante. La solution.
Mais avant d'aller directement à la solution, je vais vous expliquer comment en arriver là. Cela vous permettra de bien/mieux comprendre mon code. Avouez que c'est plus intéressant de comprendre ce que l'on fait, non?
Partie JSON:
Tout d'abord, regardons le JSON car une partie de la solution se trouve dedans. Vous pouvez voir qu'il existe des menus déroulants (des nœuds) qui se nomment "current", "minutely" et... "hourly". Oui, "hourly", c'est à des prévisions par heure.
Voilà c'est bon, le tuto est fini
Non, évidemment que le tuto n'est pas fini. Mais presque. On voit que le noeud contient lui même d'autres nœuds nommé 0, 1, 2, 3...
Déroulons ces noeuds (ici le 40): Ainsi, ici, on retrouve les différentes infos correspondant aux prévisions dans 40h. C'est la dernière ligne qui nous intéresse. Elle nous donne la quantité de pluie prévue pour cette heure (j'ai choisi ce noeud car je n'avais pas de pluie annoncée avant
Super... mais on fait quoi maintenant ?
Revenons à notre problématique: Une quantité de pluie cumulé en 2h (ou en autant de temps que vous voulez). Et comment on obtient ça ? Et bien, en additionnant les quantité de pluie pour ces 2 premières heures (dans ce cas).
C'est là où l'on va mettre les mains dans le cambouis. Allez! Passons à la partie sur le LUA!
Partie LUA:
Vous savez comment récupérer un JSON avec LUA (et donc Domoticz), comment l'ouvrir, le lire... On ne va pas revenir là-dessus.
J'ai besoin d'avoir, au maximum, le cumulé des précipitations prévues pour les 12 prochaines heures.
Il me faut donc parcourir les 12 prochaines prévisions horaires. C'est ce que je fais là:
Code : Tout sélectionner
local somme = 0 -- Somme des quantité. Peut être placée en en-tête.
for i=1, 12 do --On parcourt les 12 prochaines heures.
if (jsonValeur.hourly[i].rain) then --Pluie prévue ?
somme = somme + jsonValeur.hourly[i].rain["1h"] --Si oui, on additionne la quantité annoncée à cette heure à la somme des quantités. Sinon, on ne fait rien.
end
if (jsonValeur.hourly[i].snow) then --Neige prévue ?
somme = somme + jsonValeur.hourly[i].snow["1h"] --Même principe.
end
if (i == 2) then
quantiteDeuxHeures = somme
elseif (i == 4) then
quantiteQuatresHeures = somme
elseif (i == 6) then
quantiteSixHeures = somme
elseif (i == 12) then
quantiteDouzeHeures = somme
end
endDans cette boucle, vous pouvez voir un bloc "if". Son but est de vérifier où l'on est. Par exemple, if (i == 2) then , cela signifie que l'on en est à la prévision pour la prochaine 2eme heure. A ce moment là, on a donc additionné les précipitations prévues pour la prochaine heure et cette seconde heure. On affecte donc sa valeur à la variable représentant la quantité pour les deux prochaines heures.
Je récupère les précipitations avec jsonValeur.hourly.rain["1h"]. Comprenez par là que la variable i, qui s’incrémenter à chaque parcours de la boucle (de 1 à 12), permet de récupérer les données correspondantes à cette heure. Ensuite, j'ai dû écrire ["1h"] pour pouvoir récupérer les données de précipitations seule.
Partie Domoticz:
Si l'on veut stocker ces valeurs dans des Devices, il faut les créer. J'ai utilisé des Devices Précipitaitons. Créez-en autant que besoin(4 dans le cas décrit dans ce tuto). Notez leur Idx.
Ensuite, dans le script LUA on déclare nos devices (enfin leur Idx plus précisement).
Code : Tout sélectionner
local deuxHeuresDeviceIdx = 25
local quatreHeuresDeviceIdx = 26
local sixHeuresDeviceIdx = 27
local douzeHeuresDeviceIdx = 28
Code : Tout sélectionner
commandArray[deuxHeuresDeviceIdx] = { ['UpdateDevice'] = deuxHeuresDeviceIdx..'|1|0;'..quantiteDeuxHeures }
commandArray[quatreHeuresDeviceIdx] = { ['UpdateDevice'] = quatreHeuresDeviceIdx..'|1|0;'..quantiteQuatresHeures }
commandArray[sixHeuresDeviceIdx] = { ['UpdateDevice'] = sixHeuresDeviceIdx..'|1|0;'..quantiteSixHeures }
commandArray[douzeHeuresDeviceIdx] = { ['UpdateDevice'] = douzeHeuresDeviceIdx..'|1|0;'..quantiteDouzeHeures }Le code en entier:
Code : Tout sélectionner
local time = os.date("*t") -- Si vous souhaitez exécuté ce script toutes les X min
local start_hour = '06:00' -- Si vous souhaitez exécuté ce script tous les jours à 6h
local actual_hour = os.date("%H:%M")
local deuxHeuresDeviceIdx = 25
local quatreHeuresDeviceIdx = 26
local sixHeuresDeviceIdx = 27
local douzeHeuresDeviceIdx = 28
--------------------------------------------
----------- Variables à éditer -------------
--------------------------------------------
local api = 'myapikey' -- Remplacer par votre clé API
local lat = 'mylat' -- Remplacer par ici votre latittude
local long = 'mylong' -- Remplacer par votre longitude
--Sélectionner le chemin vers votre fichier JSON.lua en décommentant la ligne pour votre système d'exploitation
--json = (loadfile "/home/votrenomutilisé/domoticz/scripts/lua/JSON.lua")() -- For Linux
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")() -- for PI
--json = (loadfile "/volume1/@appstore/domoticz/var/scripts/lua/JSON.lua")() -- For Syno
--------------------------------------------
---------- Fin variables à éditer ----------
--------------------------------------------
commandArray = {}
log(scriptName.." "..scriptVersion.." - "..actual_hour)
log("heure: " ..time.hour)
-- Les script_time sont exécutés toute les 1 minute par Domoticz
-- Limite de l'API : 1000 appels/jour, il y a 1440 minutes/jour
-- A modifier si vous souhaitez toutes les 5, 10, 30, ... minutes (ici 20 minutes)
if (time.min % 20)==0 then -- pour exécuter le script toutes les X min
--if actual_hour==start_hour then -- pour exécuter le script à heure fixe
-- L'appel et l'enregistrement des prévisions dans la variable jsonValeur
config=assert(io.popen('/usr/bin/curl "https://api.openweathermap.org/data/2.5/onecall?lat='..lat..'&lon='..long..'&appid='..api..'&lang=fr&units=metric"'))
blocjson = config:read('*all')
config:close()
jsonValeur = json:decode(blocjson)
--------------------------------------------
---- Code à modifier selon vos besoins -----
--------------------------------------------
local somme = 0 -- Somme des quantité. Peut être placée en en-tête.
for i=1, 12 do --On parcourt les 12 prochaines heures.
if (jsonValeur.hourly[i].rain) then --Pluie prévue ?
somme = somme + jsonValeur.hourly[i].rain["1h"] --Si oui, on additionne la quantité annoncée à cette heure à la somme des quantités. Sinon, on ne fait rien.
end
if (jsonValeur.hourly[i].snow) then --Neige prévue ?
somme = somme + jsonValeur.hourly[i].snow["1h"] --Même principe.
end
if (i == 2) then
quantiteDeuxHeures = somme
elseif (i == 4) then
quantiteQuatresHeures = somme
elseif (i == 6) then
quantiteSixHeures = somme
elseif (i == 12) then
quantiteDouzeHeures = somme
end
end
commandArray[deuxHeuresDeviceIdx] = { ['UpdateDevice'] = deuxHeuresDeviceIdx..'|1|0;'..quantiteDeuxHeures }
commandArray[quatreHeuresDeviceIdx] = { ['UpdateDevice'] = quatreHeuresDeviceIdx..'|1|0;'..quantiteQuatresHeures }
commandArray[sixHeuresDeviceIdx] = { ['UpdateDevice'] = sixHeuresDeviceIdx..'|1|0;'..quantiteSixHeures }
commandArray[douzeHeuresDeviceIdx] = { ['UpdateDevice'] = douzeHeuresDeviceIdx..'|1|0;'..quantiteDouzeHeures }
--------------------------------------------
--------- Fin code à modifier -------------
--------------------------------------------
end
return commandArrayN'oubliez pas que cela reste un tutoriel. Libre à vous d'adapter ce que j'ai fais selon vos besoins. Si vous voulez plus de données, moins de données, un intervalle de temps plus grand... Faites. Sachez simplement que les prévisions sont limité à 48h avec OWM dans sa version gratuite.
Dans mon cas, j'ai considéré comme précipitation neige et pluie indifféremment. Vous pouvez faire le distinguo si tel est votre envie/besoin.
Cette version est une version "beta". Je ne l'ai pas encore testé en long, en large et en travers. Si vous rencontrez des problèmes avec n'hesitez pas à me faire remonter ça. N'hésitez pas non plus, si vous avez des questions.
Je pense ajouter à ce script les probabilités de précipitation. Si cela vous intéresse, je vous partagerai ça.


