Bonjour,
comme beaucoup, j’avais installé l’excellent script du blog Domotic and stupid geek stuff utilisant l’API de https://www.wunderground.com/.
Seul défaut à mon goût, script en bash à lancer via un crontab et aucune remontée de fonctionnement dans les logs de domoticz.
En revisitant les données délivrées par cette api, je me suis rendu compte qu’il y avait plein d’autres données, et notamment les probabilités de neige.
Et voila une occasion de réécrire ce script en lua, en ajoutant les probabilités de neige, en facilitant le choix des heures de probabilité, la possibilité d’etre notifié au delà d’un certain seuil de probabilité et … j’aime bien le lua.
--[[ name : script_time_probabilite_pluie.lua auteur : papoo date de création : 04/02/2018 Date de mise à jour : 26/12/2017 Principe : Ce script a pour but d'interroger l'API du site https://www.wunderground.com/ toutes les heures afin de récuperer les calculs de probabilités de pluie et de neige sur 36 heures pour une ville donnée. Cette API utilise une clé gratuite pour 500 requêtes par heure Il faut donc s'inscrire sur weatherunderground pour avoir accès à cette API avant l'utilisation de ce script, pensez à créer une variable utilisateur de type chaine pour y stocker votre clé API pour créer/modifier une variable utilisateur : domoticz => Réglages => Plus d'options => Variables utilisateur /probabilite-de-pluie-et-de-neige-en-lua/ http://easydomoticz.com/forum/viewtopic.php?f=17&t=2301#p20893 https://github.com/papo-o/domoticz_scripts/blob/master/Lua/script_time_probabilite_pluie.lua Ce script utilise Lua-Simple-XML-Parser https://github.com/Cluain/Lua-Simple-XML-Parser ]]-- -------------------------------------------- ------------ Variables à éditer ------------ -------------------------------------------- local nom_script = 'Probabilite Pluie' local version = '1.17' local debugging = true -- true pour voir les logs dans la console log Dz ou false pour ne pas les voir local pays='FRANCE' -- Votre pays, nécessaire pour l'API local api_wu = 'api_weather_underground' -- Nom de la variable utilisateur contenant l'API Weather Underground de 16 caractères préalablement créé (variable de type chaine) local ville='Limoges' -- Votre ville ou commune -- L'api fournie 36 probabilités de pluie, 1 par heure. local proba_pluie_h = {} -- Ajoutez, modifiez ou supprimez les variables proba_pluie_h[] -- en changeant le N° entre [] correspondant à l'heure souhaitée pour l'associer au device concerné dans dz proba_pluie_h[1]=504 -- renseigner l'idx du device % probabilité pluie à 1 heure associé, nil si non utilisé proba_pluie_h[2]=505 -- renseigner l'idx du device % probabilité pluie à 2 heures associé, nil si non utilisé proba_pluie_h[4]=639 -- renseigner l'idx du device % probabilité pluie à 4 heures associé, nil si non utilisé proba_pluie_h[6]=506 -- renseigner l'idx du device % probabilité pluie à 6 heures associé, nil si non utilisé proba_pluie_h[12]=507 -- renseigner l'idx du device % probabilité pluie à 12 heures associé, nil si non utilisé proba_pluie_h[24]=508 -- renseigner l'idx du device % probabilité pluie à 24 heures associé, nil si non utilisé -- L'api fournie 36 probabilités de neige, 1 par heure. local proba_neige_h={} -- comme pour la pluie Ajoutez, modifiez ou supprimez les variables proba_neige_h[] -- en changeant le N° entre [] correspondant à l'heure souhaitée pour l'associer au device concerné dans dz proba_neige_h[1]=771 -- renseigner l'idx du device % probabilité neige à 1 heure associé, nil si non utilisé proba_neige_h[3]=772 -- renseigner l'idx du device % probabilité neige à 2 heures associé, nil si non utilisé proba_neige_h[6]=773 -- renseigner l'idx du device % probabilité neige à 4 heures associé, nil si non utilisé proba_neige_h[12]=774 -- renseigner l'idx du device % probabilité neige à 6 heures associé, nil si non utilisé proba_neige_h[24]=738 -- renseigner l'idx du device % probabilité neige à 12 heures associé, nil si non utilisé proba_neige_h[36]=775 -- renseigner l'idx du device % probabilité neige à 24 heures associé, nil si non utilisé local seuil_notification= nil -- pourcentage au delà duquel vous souhaitez être notifié, nil si non utilisé -------------------------------------------- ----------- Fin variables à éditer --------- -------------------------------------------- local pluie local neige -------------------------------------------- ---------------- Fonctions ----------------- -------------------------------------------- function voir_les_logs (s,debugging) if (debugging) then if s ~= nil then print (" ".. s .." ") else print ("aucune valeur affichable") end end end --------------------------------------------------------------------------------- -- Lua-Simple-XML-Parser --------------------------------------------------------------------------------- XmlParser = {}; self = {}; function XmlParser:ToXmlString(value) value = string.gsub(value, "&", "&"); -- '&' -> "&" value = string.gsub(value, "<", "<"); -- '<' -> "<" value = string.gsub(value, ">", ">"); -- '>' -> ">" value = string.gsub(value, "\"", """); -- '"' -> """ value = string.gsub(value, "([^%w%&%;%p%\t% ])", function(c) return string.format("%X;", string.byte(c)) end); return value; end function XmlParser:FromXmlString(value) value = string.gsub(value, "([%x]+)%;", function(h) return string.char(tonumber(h, 16)) end); value = string.gsub(value, "([0-9]+)%;", function(h) return string.char(tonumber(h, 10)) end); value = string.gsub(value, """, "\""); value = string.gsub(value, "'", "'"); value = string.gsub(value, ">", ">"); value = string.gsub(value, "<", "<"); value = string.gsub(value, "&", "&"); return value; end function XmlParser:ParseArgs(node, s) string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a) node:addProperty(w, self:FromXmlString(a)) end) end function XmlParser:ParseXmlText(xmlText) local stack = {} local top = newNode() table.insert(stack, top) local ni, c, label, xarg, empty local i, j = 1, 1 while true do ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i) if not ni then break end local text = string.sub(xmlText, i, ni - 1); if not string.find(text, "^%s*$") then local lVal = (top:value() or "") .. self:FromXmlString(text) stack[#stack]:setValue(lVal) end if empty == "/" then -- empty element tag local lNode = newNode(label) self:ParseArgs(lNode, xarg) top:addChild(lNode) elseif c == "" then -- start tag local lNode = newNode(label) self:ParseArgs(lNode, xarg) table.insert(stack, lNode) top = lNode else -- end tag local toclose = table.remove(stack) -- remove top top = stack[#stack] if #stack < 1 then error("XmlParser: nothing to close with " .. label) end if toclose:name() ~= label then error("XmlParser: trying to close " .. toclose.name .. " with " .. label) end top:addChild(toclose) end i = j + 1 end local text = string.sub(xmlText, i); if #stack > 1 then error("XmlParser: unclosed " .. stack[#stack]:name()) end return top end function XmlParser:loadFile(xmlFilename, base) if not base then base = system.ResourceDirectory end local path = system.pathForFile(xmlFilename, base) local hFile, err = io.open(path, "r"); if hFile and not err then local xmlText = hFile:read("*a"); -- read file content io.close(hFile); return self:ParseXmlText(xmlText), nil; else print(err) return nil end end function newNode(name) local node = {} node.___value = nil node.___name = name node.___children = {} node.___props = {} function node:value() return self.___value end function node:setValue(val) self.___value = val end function node:name() return self.___name end function node:setName(name) self.___name = name end function node:children() return self.___children end function node:numChildren() return #self.___children end function node:addChild(child) if self[child:name()] ~= nil then if type(self[child:name()].name) == "function" then local tempTable = {} table.insert(tempTable, self[child:name()]) self[child:name()] = tempTable end table.insert(self[child:name()], child) else self[child:name()] = child end table.insert(self.___children, child) end function node:properties() return self.___props end function node:numProperties() return #self.___props end function node:addProperty(name, value) local lName = "@" .. name if self[lName] ~= nil then if type(self[lName]) == "string" then local tempTable = {} table.insert(tempTable, self[lName]) self[lName] = tempTable end table.insert(self[lName], value) else self[lName] = value end table.insert(self.___props, { name = name, value = self[name] }) end return node end -------------------------------------------- -------------- Fin Fonctions --------------- -------------------------------------------- commandArray = {} time=os.date("*t") --if time.min % 2 == 0 then -- exécution du script toutes les X minute(s) if ((time.min-1) % 60) == 0 then -- exécution du script toutes les heures à xx:01 voir_les_logs("=========== ".. nom_script .." (v".. version ..") ===========",debugging) local APIKEY = uservariables[api_wu] local rid = assert(io.popen("/usr/bin/curl -m8 http://api.wunderground.com/api/"..APIKEY.."/hourly/lang:FR/q/"..pays.."/"..ville..".xml")) voir_les_logs("--- --- --- http://api.wunderground.com/api/"..APIKEY.."/hourly/lang:FR/q/"..pays.."/"..ville..".xml",debugging) local testXml = rid:read('*all') rid:close() local parsedXml = XmlParser:ParseXmlText(testXml) if (parsedXml) then local abr = parsedXml.response.hourly_forecast for i in pairs(abr:children()) do if proba_pluie_h[i] ~= nil then pluie = tonumber(abr:children()[i]:children()[19]:value()) voir_les_logs("--- --- --- Probabilite de pluie a ".. i .."h => " .. pluie,debugging) commandArray[#commandArray+1] = {['UpdateDevice'] = proba_pluie_h[i]..'|0|'.. pluie} if seuil_notification ~= nil and pluie > seuil_notification then commandArray[#commandArray+1] = {['SendNotification'] = 'Alerte : '.. pluie ..' % de probabilité de pluie dans '.. i ..'heure(s)'} end end if proba_neige_h[i] ~=nil then neige = tonumber(abr:children()[i]:children()[18]:children()[2]:value()) voir_les_logs("--- --- --- probabilite de neige a ".. i .."h => " .. neige,debugging) commandArray[#commandArray+1] = {['UpdateDevice'] = proba_neige_h[i]..'|0|'.. neige} if seuil_notification ~= nil and neige > seuil_notification then commandArray[#commandArray+1] = {['SendNotification'] = 'Alerte : '.. neige ..' % de probabilité de neige dans '.. i ..'heure(s)'} end --print(abr:children()[i]:children()[4]:value()) end end end voir_les_logs("========= Fin ".. nom_script .." (v".. version ..") =========",debugging) end -- if time return commandArray
si des fois cela peut vous servir
Bonjour Titof
As tu bien créé une variable utilisateur contenant l’api et renseigné son nom ?
bonjour
j’ai un message d’erreur dans domoticz quand je regarde les log.
le voila
2017-05-10 21:09:00.015 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_probabilite_pluie.lua: …i/domoticz/scripts/lua/script_time_probabilite_pluie.lua:70: ‘)’ expected near ‘ »); — ‘ »
Pouvez vous me dire d’ou ça vient
merci d’avance
la ligne 69 fait partie d’une fonction qui agit sur le contenu du fichier téléchargé
sans fichier téléchargé dans le répertoire /tmp/ elle ne peut pas s’exécuter
Il faudrait vérifier les droits du fichiers, au minimum chmod 644
bonsoir
ma cle API est bien la bonne car elle fonctionne sous domoticz pour récupérer les infos météo de ma ville
accès extérieur: je ne passe pas car d’autre scripts fonctionnent
et j’ai bien mis Limoges comme ville sans espace
c’est surtout que dans les log j’ai l’erreur suivante qui remonte , comme s’il y avait un caractère manquant :
Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_probabilite_pluie.lua: …i/domoticz/scripts/lua/script_time_probabilite_pluie.lua:69: ‘)’ expected near ‘ »); — ‘ »‘
c’est donc que la requête wget n’a pas aboutie
plusieurs causes possible :
clé API incorrecte, vous etes vous inscrit sur Weather Underground pour avoir votre propre clé API (les chiffres donnés dans le script ne sont qu’un exemple)
accès extérieur bloqué (par feu?)
erreur dans l’adresse Weather Underground
espace dans la variable ville
non il n’y a aucun fichier « limoge.out » dans le repertoire /tmp/
bonsoir
dans le répertoire /tmp/
il y a t’il un fichier nommé limoges.out ? si oui est il vide ou contient il quelque chose?
bonsoir et merci pour votre intérêt
local debbuging était déjà en true et le message d’erreur est celui que j’ai cite hier
la clé est la bonne
et j’ai essaye avec limoges toujours la même erreur
visiblement il, j’avais pas exactement les même lignes donc j’ai recopie le code et commenter la ligne 221
idem : Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_probabilite_pluie.lua: …i/domoticz/scripts/lua/script_time_probabilite_pluie.lua:69: ‘)’ expected near ‘ »); — ‘ »‘
je ne comprends pas
merci
Bonsoir,
en mettant local debugging = true
avez vous des informations dans les logs concernant le fonctionnement du script?
votre clé API weatherunderground est elle correctement renseignée?
la déclaration de votre ville est elle correcte et connue de weatherunderground (faire un essai avec Limoges qui fonctionne)
décommentez la ligne 220 et commentez la ligne 221 comme ceci
local fname ="/tmp/weather"..ville..".out"
--local fname ="/media/Freebox/Trend/weather"..ville..".out"
bonsoir
j’ai tenter de faire fonctionner votre script, or domoticz me remonte une erreur, je ne comprend pas :
EventSystem: in /home/pi/domoticz/scripts/lua/script_time_probabilite_pluie.lua: …i/domoticz/scripts/lua/script_time_probabilite_pluie.lua:69: ‘)’ expected near ‘ »); — ‘ »‘
voici ce que j’ai a la ligne 69 :
value = string.gsub(value, « \ » », « » »); — ‘ »‘ -> « » »
sauriez vous d’ou vient le problème
Merci d’avance pour votre aide
cordialement