Aller au contenu

Rechercher dans la communauté

Affichage des résultats pour les étiquettes 'tuto hc2'.



Plus d’options de recherche

  • Rechercher par étiquettes

    Saisir les étiquettes en les séparant par une virgule.
  • Rechercher par auteur

Type du contenu


Forums

  • Bienvenue
    • Annonces et suggestions
    • Nouveau ? Présentez-vous
    • Le bistrot
    • Mon installation domotique
    • Autres Solutions Domotiques
  • La HC2 et ses périphériques
    • La Home Center pour les nuls
    • Home Center 2 & Lite
    • Modules Fibaro
    • Modules Z-wave
    • Périphériques et matériels autres
    • Plugins
    • Alarme & Vidéo-surveillance
    • Multimédia
    • Chauffage et Energie
    • Actionneurs & Ouvrants (Portail, volets...)
    • Eclairage
    • Applications Smartphones et Tablettes
    • English Section
  • Les objets connectés
    • Les Assistants Vocaux
  • Fibaro's Awards
    • Membre du mois
    • Jeux concours & Cadeaux
  • Les bonnes affaires
    • Sites internet
    • Petites annonces

Rechercher les résultats dans…

Rechercher les résultats qui…


Date de création

  • Début

    Fin


Dernière mise à jour

  • Début

    Fin


Filtrer par nombre de…

Inscription

  • Début

    Fin


Groupe


Jabber


Skype


Ville :


Intéret :


Version

133 résultats trouvés

  1. razowski

    Module Virtuel "hc2 - Diagnostics"

    Hello, Voici un petit module virtuel qui va interroger la HC2 et qui permet quand on est pas à la maison, de garder un oeil sur la mémoire utilisée par notre HC2, la charge CPU et l'espace disponible pour le système respectivement le recovery. Voici mon icône, si cela peut vous intéresser...: Voici le module virtuel : HC2_Diagnostics.vfib Pour que ça marche, importer le Virtual Device et c'est prêt. Bonne découverte. @+ Razowski
  2. Watchdog Version 1.3 Voici une scène permettant de surveiller le fonctionnement des Scènes et Main Loop de Modules Virtuels sur Home Center 2 en version 4.x. Pour ce faire, les messages de la fenêtre de Debug sont analysés. De plus, pour les scènes uniquement, le nombre d'instances est compté. En cas de problème détecté, la scène ou le virtual device considéré est automatiquement redémarré, et une notification peut être envoyée. Copier/coller le script LUA suivant dans une nouvelle scène : --[[ %% autostart %% properties %% globals --]] -------------------------------------------------- -- Scene : Watchdog -- Author : Lazer -- Version : 1.3 -- Date : June 2017 -------------------------------------------------- -- User variables local intervalle = 60 local delay = 15*60 local watchdog = { } local userID = {} -- Email local smartphoneID = {} -- Push local sms = { ["VD_ID"] = 0, -- Virtual Device ID ["VD_Button"] = "1", -- Virtual Device Button ["VG_Name"] = "SMS" -- Global Variable Name } local debug = false -- -- Message function -- function Message(color, message) if color and color ~= "" then fibaro:debug('<span style="color:'..color..';">'..(message or '<nil>')..'</span>') else fibaro:debug(message or '<nil>') end end -- -- Notification function -- function Notification(message, param) local message = message or "<vide>" Message("yellow", "Notification : "..message) if param then for _, notif in ipairs(param) do if debug then Message("grey", notif) end -- Envoi Push if notif == "push" and smartphoneID then for _, id in ipairs(smartphoneID) do if debug then Message("grey", "Send Push smartphone ID : "..id) end fibaro:call(id, "sendPush", message) end -- Envoi Email elseif notif == "email" and userID then for _, id in ipairs(userID) do if debug then Message("grey", "Send Email user ID : "..id) end fibaro:call(id, "sendEmail", "HC2 Watchdog", message) end -- Envoi SMS elseif notif == "sms" and sms then if debug then Message("grey", "Send SMS : VD_ID="..(sms["VD_ID"] or 0).." VD_Button="..(sms["VD_Button"] or "0").." VG_Name="..(sms["VG_Name"] or "")) end fibaro:setGlobal(sms["VG_Name"], message) if sms["VD_ID"] and tonumber(sms["VD_ID"])>0 and sms["VD_Button"] and tonumber(sms["VD_Button"])>0 then fibaro:call(sms["VD_ID"], "pressButton", sms["VD_Button"]) end end end else Message("orange", "Warning : no notification options given") end end -- -- Restart function -- function Restart(type, id, restart, notification, reason) Message("blue", 'Restart '..type..'('..id..')') -- Prepare API URL local getURL = "" local putURL = "" if type:lower() == "scene" then getURL = 'http://127.0.0.1:11111/api/scenes/'..id putURL = 'http://127.0.0.1:11111/api/scenes/'..id elseif type:lower() == "vd" then getURL = 'http://127.0.0.1:11111/api/virtualDevices/'..id putURL = 'http://127.0.0.1:11111/api/virtualDevices/'..id end -- Load VD/Scene local httpClient = net.HTTPClient() httpClient:request(getURL, { success = function(response) if response.status == 200 then local jsonTable = json.decode(response.data) local name = jsonTable.name or "" if restart and restart == true then -- Add new line at end of scene lua code if type:lower() == "scene" and jsonTable.lua then jsonTable.lua = jsonTable.lua .. "\n" response.data = json.encode(jsonTable) end -- Save VD/Scene httpClient:request(putURL, { success = function(response) if response.status == 200 then Message("green", type.."("..id..") successfully restarted") Notification('Watchdog : '..type..' « '..(name or "")..' » ('..id..") a été redémarré : "..(reason or "???"), notification) else Message("red", type.."("..id..") Error : status="..tostring(response.status)) Notification('Watchdog : '..type..' « '..(name or "")..' » ('..id..") n'a pas pu être redémarré : "..(reason or "???"), notification) end end, error = function(err) Message("red", type.."("..id..") Error : "..err) Notification('Watchdog : '..type..' « '..(name or "")..' » ('..id..") n'a pas pu être redémarré : "..(reason or "???"), notification) end, options = { method = 'PUT', -- headers = { -- ["content-type"] = 'application/x-www-form-urlencoded;' -- }, data = response.data } }) else Notification('Watchdog : '..type..' « '..(name or "")..' » ('..id..") doit être redémarré manuellement : "..(reason or "???"), notification) end else Message("red", type.."("..id..") Error : status="..tostring(response.status)) Notification('Watchdog : '..type..' ('..id..") n'a pas pu être redémarré : "..(reason or "???"), notification) end end, error = function(err) Message("red", type.."("..id..") Error : "..err) Notification('Watchdog : '..type..' ('..id..") n'a pas pu être redémarré : "..(reason or "???"), notification) end, options = { method = 'GET' } }) end -- function -- -- Check function -- function Check(interval) Message(nil, "Check") -- Browse VD/Scene list local httpClient = net.HTTPClient() local elements = #watchdog for i = 1, elements do -- Initialization local countscene_found = false if debug then Message(nil, "Check : type="..watchdog[i].type.." id="..watchdog[i].id) end -- Check number of running scene instances if watchdog[i].type:lower() == "scene" and watchdog[i].count and watchdog[i].count > 0 then local countScenes = fibaro:countScenes(watchdog[i].id) if countScenes < watchdog[i].count then Message("orange", watchdog[i].type..'('..watchdog[i].id..') '..countScenes..' running instance') countscene_found = true Restart(watchdog[i].type, watchdog[i].id, watchdog[i].restart, watchdog[i].notification, countScenes..' instance') elseif debug then Message("green", watchdog[i].type..'('..watchdog[i].id..') '..countScenes.." running instance") end end if countscene_found == false then -- Do not enter this loop if scene has already been restarted -- Prepare API URL local getURL = "" if watchdog[i].type:lower() == "scene" then getURL = "http://127.0.0.1:11111/api/scenes/"..watchdog[i].id.."/debugMessages" elseif watchdog[i].type:lower() == "vd" then getURL = "http://127.0.0.1:11111/api/virtualDevices/"..watchdog[i].id.."/debugMessages/0" else Message("red", "Error : unknown type value") end if getURL ~= "" then if debug then Message("grey", getURL) end -- Load VD/Scene debug messages httpClient:request(getURL, { success = function(response) if response.status == 200 then if response.data and response.data ~= "" then local jsonTable = json.decode(response.data) local current_timestamp = os.time() local oldest_timestamp = current_timestamp local match_found = false local no_match_found = false local reason = "" -- Reverse browsing of debug messages for j = #jsonTable, 1, -1 do oldest_timestamp = jsonTable[j].timestamp -- Check if debug message match lookup string within allowed interval if watchdog[i].match.text and watchdog[i].match.text ~= "" and watchdog[i].match.interval > 0 and jsonTable[j].txt:match(watchdog[i].match.text) then if jsonTable[j].timestamp > current_timestamp - watchdog[i].match.interval then if debug then Message("green", watchdog[i].type..'('..watchdog[i].id..') Found string "'..watchdog[i].match.text..'"') end match_found = true end end -- Check if debug message match forbidden string if watchdog[i].no_match.text and watchdog[i].no_match.text ~= "" and jsonTable[j].txt:match(watchdog[i].no_match.text) then Message("orange", watchdog[i].type..'('..watchdog[i].id..') Found string "'..watchdog[i].no_match.text..'"') no_match_found = true reason = os.date('%H:%M:%S', (jsonTable[j].timestamp or 0)) .. " " .. jsonTable[j].type .. " : " .. jsonTable[j].txt break end if watchdog[i].no_match.type and watchdog[i].no_match.type ~= "" and jsonTable[j].type == watchdog[i].no_match.type then Message("orange", watchdog[i].type..'('..watchdog[i].id..') Found type "'..watchdog[i].no_match.type..'"') no_match_found = true reason = os.date('%H:%M:%S', (jsonTable[j].timestamp or 0)) .. " " .. jsonTable[j].type .. " : " .. jsonTable[j].txt break end end -- for if debug and oldest_timestamp > current_timestamp - watchdog[i].match.interval then Message("grey", watchdog[i].type..'('..watchdog[i].id..') oldest debug timestamp more recent than interval') end -- Restart VD/Scene if watchdog[i].match.text and watchdog[i].match.text ~= "" and watchdog[i].match.interval > 0 and match_found == false and oldest_timestamp < current_timestamp - watchdog[i].match.interval then Message("orange", watchdog[i].type..'('..watchdog[i].id..') String "'..watchdog[i].match.text..'" not found') reason = 'Chaine « ' .. watchdog[i].match.text .. ' » non trouvée' if #jsonTable > 0 then reason = reason .. ', dernier message : ' .. os.date('%H:%M:%S', (jsonTable[#jsonTable].timestamp or 0)) .. ' « ' .. (jsonTable[#jsonTable].txt or "<nil>") .. ' »' end Restart(watchdog[i].type, watchdog[i].id, watchdog[i].restart, watchdog[i].notification, reason) --if watchdog[i].no_match.text and watchdog[i].no_match.text ~= "" and no_match_found == true then elseif no_match_found == true then Restart(watchdog[i].type, watchdog[i].id, watchdog[i].restart, watchdog[i].notification, reason) end else Message("red", "Error : empty response") end else Message("red", "Error : status=" .. tostring(response.status)) end end, error = function(err) Message("red", 'Error : ' .. err) end, options = { method = 'GET' } }) end end end -- for -- Wait if interval and interval > 0 then setTimeout(function() Check(interval) end, interval*1000) end end -- function -- -- Main loop -- local trigger = fibaro:getSourceTrigger() if trigger["type"] == "autostart" then Message(nil, "Watchdog instance autostart") -- Check function call delayed to prevent killing all other scenes not already started right after HC2 boot setTimeout(function() Check(intervalle) end, delay*1000) else Message(nil, "Watchdog instance manual launch") -- Call Check function Check(nil) end . Le paramétrage du script s'effectue dans les quelques lignes situées sous le commentaire "User variables" : intervalle : durée entre 2 vérifications delay : délai avant la première vérification. En effet, cette scène ayant la propriété autostart afin de démarrer automatiquement au boot de la box, le risque est de démarrer avant les autres Scène/VD, et de forcer un redémarrage de ceux-ci alors qu'ils n'ont pas encore effectivement démarré. Ce délai laisse donc aux autres Scène/VD le temps de démarrer et de s'initialiser proprement. watchdog : tableau dont chaque ligne représente une Scène ou un Virtual Device à monitorer : type : "Scene" ou "VD" id : valeur numérique représentant l'ID de la Scène ou VD à monitorer match : texte qui doit être trouvé pendant un certain laps de temps afin de confirmer le bon fonctionnement du VD/Scène. Cela correspond typiquement à un message affiché cycliquement à intervalle régulier. Les 2 champs suivants doivent être renseignés pour que la condition soit prise en compte (condition ET) : text : chaine de caractères à trouver interval : durée en secondes no_match : texte qui ne doit pas être trouvé, sous peine de considérer le VD/Scène comme planté. Cela correspond typiquement à un message d'erreur LUA qui entraine le plantage du script. A noter que la condition no_match à priorité sur la condition match, c'est à dire que si le texte recherché par no_match est détecté, le VD/Scène sera redémarrer même si le texte recherché par match a été détecté. L'un ou l'autre des 2 champs suivants peuvent être renseignés pour que la condition soit prise en compte (condition OU) : text : chaine de caractères à trouver type : "ERROR" correspond aux messages affichés en rouge dans la fenêtre de Debug de l'interface HC2. A noter que jusqu'en v4.056, dans une scène une erreur LUA affichait le message en rouge avec le type "ERROR", tandis que depuis les Beta v4.057 et v4.058, cette même erreur s'affiche en blanc sans le type ERROR, par conséquent ce test ne fonctionne plus. En revanche, aucun changement de mode de fonctionnement concernant les Virtual Devices. count : valeur valable pour les scènes uniquement, et indiquant le nombre minimal d'instances qui doivent fonctionner pour confirmer le bon fonctionnement de la scène. Cela correspond typiquement à l'instance de type boucle infinie lancée en autostart. restart : true ou false afin de redémarrer le VD/Scène concerné, ou seulement envoyer une notification signalant qu'il faut le redémarrer manuellement. notification : liste séparée par des virgules des moyens de notifications à employer. userID : liste séparée par des virgules des ID des utilisateurs qui doivent recevoir des notifications par email (le mail est celui configuré pour chaque utilisateur dans le panneau de contrôle d'accès) smartphoneID : liste séparée par des virgules des ID des smartphones qui doivent recevoir des notifications push (à récupérer dans le toolkit de Krikroff ou via l'API : /api/iosDevices) sms : si vous avez une passerelle SMS sous Android avec SMS Gateway (ou équivalent) pilotée par un module virtuel, il faut renseigner ici les informations nécessaires : VD_ID : ID du module virtuel VD_Button : ID du bouton du module virtuel VG_Name : nom de la variable globale debug : true ou false afin d'activer l'affichage étendu dans la fenêtre de débugage de la scène. Exemple de paramètres : -- User variables local intervalle = 60 local delay = 15*60 local watchdog = { {type = "Scene", id = 1, match = {text="", interval=0}, no_match = {text=""}, count=1, restart=true, notification = {"push", "email", "sms"}}, -- Présence Lazer {type = "Scene", id = 2, match = {text="Last run", interval=2*60}, no_match = {text=""}, count=1, restart=true, notification = {"push", "email", "sms"}}, -- DomoCharts {type = "Scene", id = 3, match = {text="Durée des traitements", interval=11*60}, no_match = {text=""}, count=1, restart=true, notification = {"push", "email", "sms"}}, -- GEA {type = "VD", id = 1, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- Surveillance Station {type = "VD", id = 2, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- Clock Sync {type = "VD", id = 3, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- My Batteries {type = "VD", id = 4, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- Evénements {type = "VD", id = 5, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- Network Monitor {type = "VD", id = 6, match = {text="", interval=0}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- GEA Alarm {type = "VD", id = 7, match = {text=" ", interval=30}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}}, -- Sonos Player (Tk.isTraceEnabled = true) {type = "VD", id = 8, match = {text="Start main process", interval=31*60}, no_match = {text="", type="ERROR"}, restart=true, notification = {"push", "email", "sms"}} -- Freebox Serveur } local userID = {1} -- Email local smartphoneID = {1, 2} -- Push local sms = { ["VD_ID"] = 99, -- Virtual Device ID ["VD_Button"] = "1", -- Virtual Device Button ["VG_Name"] = "SMS" -- Global Variable Name } local debug = false
  3. Nikko

    Backup Via Scene Lua

    Bonjour, Voici un résumé sur la réalisation/suppression de backups via des scènes en Lua. La création/suppression de backup s'effectue en temps normal sur l'interface du HomeCenter à la page Diagnostiques/Sauvegarde et restauration. Le code donné dons les 2 scènes n'est pas des plus optimisé; cela constitue juste une base. EDIT (03/12/2016): Mise à jour avec l'api pour les versions >=4.101; voir plus loin: (https://www.domotique-fibaro.fr/topic/8641-backup-via-scene-lua/?do=findComment&comment=146362) Les Commandes de l'API La récupération au format JSON de la liste des backups se fait à l'addresse http://HC2/api/settings/backups Pour Créer un Backup on utilise l'addresse http://HC2/api/settings/backups avec une requète de type en POST avec les paramètres action et description. Pour Supprimer un Backup, on utilise l'addresse http://HC2/api/settings/backups?id=xx (où xx est le numéro de backup). La requète est de type DELETE avec comme paramètre id=xx => Comme les urls de l'api vont être appelées depuis des scènes lua, l'ip de la box utilisée sera 127.0.0.1 (port 11111) => En cas d'appel sur l'ip LAN de la box (Ex: http://192.168.0.100/api/settings/backups) , il faudra en plus transmettre l'authentification dans la requète. Attention: Lors de la création de Backup, "tout le reste" est suspendu; de même après que le backup soit effectué, le moteur Z-Wave et d'autres services redémarrent. Donc en cas de planification , privilégier la nuit, là ou l'activité ZWave, scénarios, est faible/inexistante. Scène de création d'un backup Exemple de Scène de création d'un Backup, avec notification vers portable: --[[ %% properties %% events %% globals --]] -- ID des mobiles,tablettes pour notification local portable = { 385,378 } -- Message Descriptif du Backup local descriptif = 'Backup du '..os.date("%d/%m/%y - %HH%M") function sendPush(message) if #portable > 0 then for _,v in ipairs(portable) do fibaro:call(v,'sendPush', message) end end end local url = 'http://127.0.0.1:11111/api/settings/backups' local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 201 then print("Backup Created at " .. os.date()) sendPush(descriptif .. ' effectué') else print("Error " .. response.status) sendPush('Erreur lors de la création du Backup') end end, error = function(err) print('error = ' .. err) end, options = { method = 'POST', headers = { ["content-type"] = 'application/x-www-form-urlencoded;' }, data = 'action=create&description='..descriptif } }); Depuis la page des backups, on peut vérifier que la scène fonctionne: Pour les utilisateurs de GEA, on peut déclencher cette sauvegarde le 1er samedi de chaque mois par exemple: -- Fonction déterminant si nous sommes le 1er samedi du mois function isFirstSaturday() local t = os.date('*t') return ( t['day'] < 8 and t['wday'] == 7 ) end -- Backup le 1er samedi du mois GEA.add({"Function",function() return isFirstSaturday() end} , 30 , "Backup Mensuel du HC2" , {{"Time","01:00","01:01"},{"Scenario", 12}}) . Scène de suppression d'un backup Exemple de Scene Lua pour réaliser la suppression du backup le plus ancien: --[[ %% properties %% events %% globals --]] -- Flag dryrun; Si true, la requete sur api pour effacer le backup n'est pas effectuée local dryrun = true -- Récupération de la list des backups local backups = api.get('/settings/backups') -- Vérification de présence Backup if (backups and type(backups == 'table') and #backups > 0) then if #backups > 1 then print(#backups .. ' Backups présents') else print('1 Backup présent') end for i in ipairs(backups) do fibaro:debug('ID: '..backups[i]['id']..' | TIMESTAMP: '..backups[i]['timestamp']..' | DESCRIPTION: '..backups[i]['description']) end else print('Pas de backup ou erreur lors de la récupération de la liste') fibaro:abort() end -- Pour chaque Backup on stock le timestamp de la date de réalisation dans une table -- On classe ensuite les timestamps par ordre croissant local timestamp = {} for i in ipairs(backups) do table.insert(timestamp, backups[i]['timestamp']) end table.sort(timestamp) -- Le 1er timestamp de la table est le plus petit donc le plus ancien en epochtime -- Dans la table de backup on recherche le backup ayant ce timestamp local id = false for i in ipairs(backups) do if (tonumber(backups[i]['timestamp']) == tonumber(timestamp[1])) then id = backups[i]['id'] end end if id then print("ID du backup le plus ancien: "..id) else print("Erreur lors de la récupération de l'ID") fibaro:abort() end -- Requete via API pour effacer le backup le plus ancien if not dryrun then local url = 'http://127.0.0.1:11111/api/settings/backups?id='..id local httpClient = net.HTTPClient() httpClient:request(url , { success = function(response) if tonumber(response.status) == 200 then print("Backup deleted at " .. os.date()) else print("Error " .. response.status) end end, error = function(err) print('error = ' .. err) end, options = { method = 'DELETE', headers = { ["content-type"] = 'application/x-www-form-urlencoded;' }, data = 'id='..id } }); end . Cette Scène produit le debug suivant: Nicolas
  4. Steven

    Evénements

    Evénements Module virtuel pour afficher les derniers événements Lorsque l'on fait des tests, il est parfois pratique d'avoir la liste des derniers événements ayant eu lieu sur notre HC2. Voici donc mon dernier module virtuel avant les vacances :-) Comme vous pouvez le voir, ce module affiche les 10 événements en oubliant volontairement les modules de températures. Si vous voulez voir plus d'événements, il vous faudra rajouter vous-même des labels en faisant juste attention que leur ID suivent la numérotation Label11, Label12, Label13, ... et modifier la position du bouton rafraîchir dans le Main Loop. J'ai volontairement ajouté la pièce pour certaine personne qui se reconnaîtrons Ce dernier affiche donc : Le nom du module concerné La pièce dans laquelle il se trouve Son ancienne valeur Sa nouvelle valeur L'heure de l'événement Ce module se rafraîchi automatiquement toutes les 3 secondes . . . Installation Il vous suffit juste d'importer le module virtuel ci-joint puis de modifier votre pseudonyme et mot de passe qui se trouve dans le bouton Rafraichir local user = "admin" local pwd = "password" HC2 = Net.FHttp("127.0.0.1",80) HC2:setBasicAuthentication(user, pwd) ... Cordialement Evenements.vfib
  5. sebcbien

    Detection De Présence

    Bonjour, Suite à une conversation en MP avec un de nos admin chéri ;-), voici ma solution pour détecter la présence via smartphone. L'idée est de savoir quand ma femme ou moi même sommes à la maison afin de pouvoir lancer des scénarios ou en bloquer l’exécution. J'ai fait ça il y a longtemps, et bien sur je n'ai pas tout fait tout seul. Je me souviens avoir fait quelques modifications pour que ça tourne comme je le voulais, mais je ne sais plus lesquelles. Bref, voici le package complet, pour certains scripts, comme pour le ping par exemple la base est de Krikroff et j'ai laissé le copyright. J'ai mis le Virtual Device en attach et le code du bouton ci-dessous . IP Smartphone Presence Check V1.0.vfib !!! voir post plus loin dans le fil pour les V1.1 V1.2 V1.3 V2.0 et suivantes !!! V2.1 ici: https://www.domotique-fibaro.fr/topic/2613-detection-de-prã©sence/?do=findComment&comment=121355 V1.3 ici: http://www.domotique-fibaro.fr/index.php/topic/2613-detection-de-pr%C3%A9sence/page-3#entry35219 - il faut créer une variable globale (non prédéfinie) par device à surveiller (moi j'utilise "Phone_GG_Present" pour le tel de ma femme) et la déclarer en début de script du bouton. - il faut encoder l'adresse IP du téléphone dans les paramètres du Virtual device (pensez à déterminer une ip Wifi fixe pour votre smartphone) - il faut encoder le port ouvert sur votre téléphone dans les paramètres du Virtual device (3500 ou 3401) - Sur Androà¯d, il n'y a pas de port ouvert par défaut pour accepter le ping, le moyen le plus simple est d'installer l'application Sonos et a lancer, c'est tout (pas besoin d'avoir du matos sonos pour que ça fonctionne) - Sur iPhone idem, mais je n'ai pas testé personellement - si vous ne voulez pas utiliser le mainloop comme "scheduler" , créez simplement une scène qui va cliquer sur le bouton de demande de présence toutes les minutes... ou avec l'excellent GEA, avec la ligne ci-dessous (à adapter): -- Mise à jour des Présences par détection d'adresses IP toutes les minutes GEA.add(true , 1*60, "",{{"VirtualDevice", id["VD_PRESENCE_SEB"], "1"},{"VirtualDevice", id["VD_PRESENCE_GG"], "1"},{"Repeat"}}) Notification de présence en utilisant GEA, entre 8h et 21h: N'oubliez pas de mettre les VG dans l'entête. Ces exemple sont repris dans le post GEA de ma signature --------------DETECTION PRESENCE-------------- -- Signale GG at Home GEA peux se déclencher sur un changement de valeur d'une variable global GEA.add({"Global", "Phone_GG_Present", "1"}, -1, "Presence GG est maintenant à #value#", {{"Portable", 53}, {"Time", "08:00", "21:00"}}) GEA.add({"Global", "Phone_GG_Present", "0"}, -1, "Presence GG est maintenant à #value#", {{"Portable", 53}, {"Time", "08:00", "21:00"}}) Code bouton VD détect presence V1.0 (ancien code): -- IP Smartphone Presence Check V1.0 -- Copyright © 2014 Sébastien Jauquet. -- http://www.domotique-fibaro.fr/index.php/topic/2613-detection-de-pr%C3%A9sence/ --Using code from: -- Ping v 1.0.1 [05-2013] -- Copyright © 2013 Jean-christophe Vermandé -- http://www.domotique-fibaro.fr/index.php/topic/109-ping-dun-%C3%A9quipement-r%C3%A9seau/page-2 fibaro:log("Starting process"); local _deviceIp = "192.168.10.112"; local variable_globale_phone = "Phone_GG_Present"; local _devicePort = 3500; local _maxRetryProcess = 20; local time = tonumber(os.time()); local maxtime = 56; -- fibaro:setGlobal("Lock_Away","Unlocked") function SecondsToClock(sSeconds) local nSeconds = tonumber(sSeconds) if nSeconds == 0 then return "00:00:00"; else nHours = string.format("%02.f", math.floor(nSeconds/3600)); nMins = string.format("%02.f", math.floor(nSeconds/60 - (nHours*60))); nSecs = string.format("%02.f", math.floor(nSeconds - nHours*3600 - nMins *60)); return nHours..":"..nMins..":"..nSecs end end -- recursive function to ping device local function _ping(retry) retry = retry or 0; -- notify state local elapsed = os.difftime(os.time(), tonumber(time)); local msg = "Loop #".. retry .." since "..SecondsToClock(elapsed); fibaro:log(msg); -- check for no more than 30 seconds if elapsed > maxtime then return false; end --open the socket local tcpSocket = Net.FTcpSocket(_deviceIp, _devicePort); --set the read timeout tcpSocket:setReadTimeout(250); --send packet local bytes, errorCode = tcpSocket:write("test"); --check for error if errorCode == 0 then return true; else if retry < _maxRetryProcess then --fibaro:log("Retry process, please wait..."); fibaro:sleep(1*750); return _ping(retry + 1); end return false; end end --ping device, secure with pcall to catch errors. local f, result = pcall(_ping); local Lock_Away = fibaro:getGlobal("Lock_Away") if (f) then if (result == true) and (Lock_Away == "Unlocked") then fibaro:log("Device has been found."); fibaro:setGlobal(variable_globale_phone,"1") -- fibaro:setGlobal("Present_Phones",os.time()) else fibaro:log("Device was not found!"); fibaro:setGlobal(variable_globale_phone,"0") end else fibaro:log("Error: " .. f); end Code main loop du VD local thismodule = fibaro:getSelfId(); local status = fibaro:getGlobal("Phone_GG_Present") -- fibaro:debug(thismodule); if status == "0" then fibaro:call(thismodule, "setProperty", "currentIcon", 1037) end if status == "1" then fibaro:call(thismodule, "setProperty", "currentIcon", 1036) end fibaro:sleep(1000); Ce n'est certainement pas le code le plus "léché" mais je pense que ça en aidera quand même certains... et puis c'est "tout fait" ;-) Le script va détecter quasi instantanément lorsque le smartphone apparaît sur le réseau, mais pourra mettra jusqu'à une minute pour valider son absence Enjoy !
  6. Ce module permet de piloter l'arrêt, la petite et la grande vitesse à l'aide d'un FGS-221. La VMC n'est pas prévue pour être à l'arrêt initialement mais je trouve ridicule de la faire tourner les jours rouges (je suis en Tempo) qui sont généralement les plus froids. Une conso électrique pour en plus mettre de la chaleur dehors, plus jamais même si les radiateurs à chaleur douce sont en appoint d'un insert. La salle de bain à l'étage est en pignon et assez éloignée de la trémie de l'escalier donc pas réellement chauffée par l'insert. . Voici le schéma sur lequel je suis partit. Ayant un doute sur la possibilité de ma VMC à lui raccorder la grande vitesse en même temps que la petite, j'ai préféré ajouter un relais inverseur pour suivre le même câblage que le va-et-vient d'origine. L'astuce est de faire le pont entre la phase et O1 (marche-arrêt) puis d'alimenter le contact inverseur du relais en In et enfin sortir de O2 pour alimenter la bobine du relais (PV-GV). J'ai choisi des poussoirs à voyant Mosaïc pour les commandes et pour l'état un voyant vert pour la marche en petite vitesse et un voyant rouge sur le second poussoir pour la grande vitesse. Il me manquait des fils entre la VMC et une boîte à l'étage (au dessus du plan de travail). Je vous précise cela car ça ne voulait pas passer et j'ai été obligé de débrancher les fils existants dans la gaîne (circuit PC + circuit 20A + alim. d'un éclairage + 3 fils VMC), d'y accrocher une aiguille et ressortir les 7 mètres pour y ajouter mon neutre + d'autres en réserve pour ensuite les repasser tous ensemble (c'était chaud mais pas impossible). Pour les commandes des boutons, rien de compliqué La main loop pour le retour des 3 états. Un grand MERCI à Steven qui, une fois de plus à répondu présent pour me dépatouiller de Lua. --[[ %% properties %% globals --]] local id_vmc_lent = 236 local id_vmc_rapide = 238 local id_module_virtuel = fibaro:getSelfId() local lentAllumer = tonumber(fibaro:getValue(id_vmc_lent, "value")) == 1 local rapideAllumer = tonumber(fibaro:getValue(id_vmc_rapide, "value")) == 1 local icon = fibaro:getValue(id_module_virtuel, "currentIcon") if (lentAllumer and rapideAllumer) then -- icone rapide icon = 1097 elseif (lentAllumer) then -- icone lent icon = 1096 else -- icone éteint icon = 1091 end fibaro:call(235, "setProperty", "currentIcon", icon) Et enfin, les icônes au cas où vous ne les auriez pas déjà trouver dans le topic de Steh (Banque Icônes Hc2 & Hcl). Bien sûr, je n'ai pas fait ce module juste pour pouvoir m'amuser avec la VMC de la tablette mais je compte bien la faire taire complètement les jours rouges et peut-être aussi lui faire forcer la grande vitesse quand le taux d'humidité dans la gaîne de la salle de bain sera trop élevé mais encore faudrait-il trouver une sonde adéquate.
  7. Bonjour, Le but de ce tuto sera de faire une passerelle pour les données de la netatmo vers emoncms. J'en ai profité pour améliorer le script php classique d'interface entre la netatmo et la HC2 les versions disponibles ot du mal à gérer les installations netatmo avec plusieurs modules. Ici j'ai cherché à améliorer les choses et ça fonctionne même lorsque l'on a plusieurs master device et plusieurs stations additionnelles. En effet, savoir l'ordre des modules renvoyé par netatmo dans ces conditions est un peur hard. J'ai ajouté plusieures pages de résultats au script PHP: une avec un json viewer intégré et un qui retourne le json complet. J'ai aussi optimisé pour minimiser le nombre de requêtes faites à netatmo, histoire de ne pas se faire "jeter" voici déjà la présentation de la plateforme emon CMS très puissante que j'utilise depuis plus d'un an: http://emoncms.org/site/home http://emoncms.org/site/docs/visualisations Personellement je l'utilise pour remonter mes graphiques de valeurs diverses de ma HC2 - températures - consommations eau, gaz, elec - paramètres de ma VMC (T° Vitesse, rendement etc.) J'ai partagé mon script avec un ami et comme il était enchanté, je fais l'effort de le mettre ici aussi ;-) En effet, il suffit de configurer les variables dans le VD, créer un répertoire /netatmo dans www ou web ou html, y mettre le PHP et le répertoire jsoneditor et c'est parti, les données seront remontées automatiquement à emonCMS ! Voici déjà le script côté HC2: Je l'ai mis derrière un bouton, car dans un main loop, une corruption json quelquepart et c'est tout qui plante. Ce bouton dont être cliqué via GEA ou autre scheduler toutes les 10 minutes. Voici le Virtual Device tout fait: Grosse mise à jour à ce post: http://www.domotique-fibaro.fr/index.php/topic/3929-yagda-yet-another-graphic-data-analyser-netatmo-vmc-emoncms-json-viewer/#entry63238 Netatmo_V2.vfib Attention, dans ce post ne figure que les scripts de la première version, voir plus loin dans le fil pour les versions suivantes ! ----------------------------------------------------------------------------------------- -- YAGDA - yet another graphic data analyser V2.01 -- Retreive Netatmo values for more than 2 modules, compute CO2 and push to EmonCMS -- Sebastien Jauquet -- Février 2015 -- Thanks to cedriclocqueneux, krikroff, i-magin and all contibutors to the netatmo code ----------------------------------------------------------------------------------------- -- Instructions: -- Create an free emoncms.org account -- Retrieve your Write API Key from it -- Create a Global variable (undefined) -> CO2_Max_Value to store the max value of CO2 of the house - if you dont need this, set CO2 to false (default: 0) -- Install my netatmo.php in your webserver and write his address in the ip Address of this module -- for each value you want to be pushed to emoncms, modify the section -- Push To EMONCMS -- below -- Create a block scene or use gea to click this button each 10 minutes (to avoid rejection from the api of Netatmo) local EmonCMS_Prefix = "NETATMO_" -- prefix of the id of the inpus to be created in emoncms (convenient for testing to not alter current feeds) local PushToEmonCMS = true -- true = push to emoncms - false = do not push local selfId = fibaro:getSelfId(); local thismodule=fibaro:getSelfId() local domaine = fibaro:get(selfId, 'IPAddress') local PushItem local CO2_Max_Value_Local = 0 -- if you dont need this, set CO2 to false (default: 0) local emoncms = Net.FHttp("emoncms.org",80) local emoncms_api_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" -- your EMONCMS WRITE api Key EmonCMS = {}; if (temperature_exterieure==nil) then temperature_exterieure = ""; end if (humidite_exterieure==nil) then humidite_exterieure = ""; end if (temperature_interieure==nil) then temperature_interieure = ""; end if (humidite_interieure==nil) then humidite_interieure = ""; end if (co2==nil) then co2 = ""; end if (pression==nil) then pression = ""; end if (bruit==nil) then bruit = ""; end if (temperature_int_mod2==nil) then temperature_int_mod2 = ""; end if (humidite_int_mod2==nil) then humidite_int_mod2 = ""; end if (co2_mod2==nil) then co2_mod2 = ""; end if (temperature_int_mod3==nil) then temperature_int_mod3 = ""; end if (humidite_int_mod3==nil) then humidite_int_mod3 = ""; end if (co2_mod3==nil) then co2_mod3 = ""; end if (temperature_int_mod4==nil) then temperature_int_mod4 = ""; end if (humidite_int_mod4==nil) then humidite_int_mod4 = ""; end if (co2_mod4==nil) then co2_mod4 = ""; end if(refreshUI==nil) then -- Loads in memory only the first occurence function refreshUI(ext, bruit, titre, tempmod, co2mod, humidmod, lastupdate, laststatus) fibaro:call(selfId,"setProperty","ui.ext.value",ext); fibaro:call(selfId,"setProperty","ui.bruit.value",bruit); fibaro:call(selfId,"setProperty","ui.titre.value",titre); fibaro:call(selfId,"setProperty","ui.tempmod.value",tempmod); fibaro:call(selfId,"setProperty","ui.co2mod.value",co2mod); fibaro:call(selfId,"setProperty","ui.humidmod.value",humidmod); fibaro:call(selfId,"setProperty","ui.lastupdate.value",lastupdate); fibaro:call(selfId,"setProperty","ui.laststatus.value",laststatus); end; end if(getExt==nil) then -- Loads in memory only the first occurence function getExt(retry) retry = retry or 0 -- Setting up the connection data local FHTE = Net.FHttp(domaine, 80); -- Netatmo extérieur local response = FHTE:GET("/netatmo/netatmo.php?parameter=ext"); -- decoding json string to table if (response~= nil) then local result = nil; result = json.decode(response); if (result ~= nil) then -- prevent: attempt to index field 'body' (a nil value) if (result.body ~= nil) then temperature_exterieure = result.body[1].value[1][1] or "n.c"; humidite_exterieure =result.body[1].value[1][2] or "n.c"; -- variable globale pour info sms local msg = "Température extérieure : "..temperature_exterieure.."°C"; fibaro:setGlobal("tempext", msg); return true; else fibaro:debug("Netatmo EXT: erreur le " .. os.date()); if (result.error ~= nil) then fibaro:debug("error code: "..result.error.code..", message: "..result.error.message); end end else fibaro:debug("Netatmo EXT: erreur decodage json le " .. os.date()); end else fibaro:debug("Netatmo EXT:la reponse est null !"); end if ((retry or 5)< 5) then fibaro:debug("Retry #"..retry.."process, please wait..."); fibaro:sleep(5000); return getInt(tonumber(retry+1)); else return false; end end; end if(getInt==nil) then -- Loads in memory only the first occurence function getInt(retry) retry = retry or 0; -- Setting up the connection data local FHTE = Net.FHttp(domaine, 80); -- Netatmo intérieur local response = FHTE:GET("/netatmo/netatmo.php?parameter=int"); -- decoding json string to table if (response~= nil) then local result = nil; result = json.decode(response); if (result ~= nil) then -- prevent: attempt to index field 'body' (a nil value) if (result.body ~= nil) then temperature_interieure = result.body[1].value[1][1] or "n.c"; humidite_interieure = result.body[1].value[1][3] or "n.c"; co2 = result.body[1].value[1][2] or "n.c"; pression = result.body[1].value[1][4] or "n.c"; bruit = result.body[1].value[1][5] or "n.c"; -- variable globale pour info sms fibaro:setGlobal("tempint", "Température intérieure : "..temperature_interieure.."°C"); return true; else fibaro:debug("Netatmo INT: erreur le " .. os.date()); if (result.error ~= nil) then fibaro:debug("error code: "..result.error.code..", message: "..result.error.message); end end else fibaro:debug("Netatmo INT: erreur decodage json le " .. os.date()); end else fibaro:debug("Netatmo INT:la reponse est null !"); end if ((retry or 5)< 5) then fibaro:debug("Retry #"..retry.."process, please wait..."); fibaro:sleep(5000); return getExt(tonumber(retry+1)); else return false; end end; end if(getMod2==nil) then -- Loads in memory only the first occurence function getMod2(retry) retry = retry or 0; -- Setting up the connection data local FHTE = Net.FHttp(domaine, 80); -- Netatmo intérieur local response = FHTE:GET("/netatmo/netatmo.php?parameter=mod2"); -- decoding json string to table if (response~= nil) then local result = nil; result = json.decode(response); if (result ~= nil) then -- prevent: attempt to index field 'body' (a nil value) if (result.body ~= nil) then temperature_int_mod2 = result.body[1].value[1][1] or "n.c"; humidite_int_mod2 = result.body[1].value[1][2] or "n.c"; co2_mod2 = result.body[1].value[1][3] or "n.c"; -- variable globale pour info sms -- fibaro:setGlobal("tempint", "Température intérieure : "..temperature_interieure.."°C"); return true; else fibaro:debug("Netatmo INT_mod2: erreur le " .. os.date()); if (result.error ~= nil) then fibaro:debug("error code: "..result.error.code..", message: "..result.error.message); end end else fibaro:debug("Netatmo INT_mod2: erreur decodage json le " .. os.date()); end else fibaro:debug("Netatmo INT_mod2:la reponse est null !"); end if ((retry or 5)< 5) then fibaro:debug("Retry #"..retry.."process, please wait..."); fibaro:sleep(5000); return getExt(tonumber(retry+1)); else return false; end end; end if(getMod3==nil) then -- Loads in memory only the first occurence function getMod3(retry) retry = retry or 0; -- Setting up the connection data local FHTE = Net.FHttp(domaine, 80); -- Netatmo intérieur local response = FHTE:GET("/netatmo/netatmo.php?parameter=mod3"); -- decoding json string to table if (response~= nil) then local result = nil; result = json.decode(response); if (result ~= nil) then -- prevent: attempt to index field 'body' (a nil value) if (result.body ~= nil) then temperature_int_mod3 = result.body[1].value[1][1] or "n.c"; humidite_int_mod3 = result.body[1].value[1][2] or "n.c"; co2_mod3 = result.body[1].value[1][3] or "n.c"; -- variable globale pour info sms -- fibaro:setGlobal("tempint", "Température intérieure : "..temperature_interieure.."°C"); return true; else fibaro:debug("Netatmo INT_mod3: erreur le " .. os.date()); if (result.error ~= nil) then fibaro:debug("error code: "..result.error.code..", message: "..result.error.message); end end else fibaro:debug("Netatmo INT_mod3: erreur decodage json le " .. os.date()); end else fibaro:debug("Netatmo INT_mod3:la reponse est null !"); end if ((retry or 5)< 5) then fibaro:debug("Retry #"..retry.."process, please wait..."); fibaro:sleep(5000); return getExt(tonumber(retry+1)); else return false; end end; end if(getMod4==nil) then -- Loads in memory only the first occurence function getMod4(retry) retry = retry or 0; -- Setting up the connection data local FHTE = Net.FHttp(domaine, 80); -- Netatmo intérieur local response = FHTE:GET("/netatmo/netatmo.php?parameter=mod4"); -- decoding json string to table if (response~= nil) then local result = nil; result = json.decode(response); if (result ~= nil) then -- prevent: attempt to index field 'body' (a nil value) if (result.body ~= nil) then temperature_int_mod4 = result.body[1].value[1][1] or "n.c"; humidite_int_mod4 = result.body[1].value[1][2] or "n.c"; co2_mod4 = result.body[1].value[1][3] or "n.c"; -- variable globale pour info sms -- fibaro:setGlobal("tempint", "Température intérieure : "..temperature_interieure.."°C"); return true; else fibaro:debug("Netatmo INT_mod4: erreur le " .. os.date()); if (result.error ~= nil) then fibaro:debug("error code: "..result.error.code..", message: "..result.error.message); end end else fibaro:debug("Netatmo INT_mod4: erreur decodage json le " .. os.date()); end else fibaro:debug("Netatmo INT_mod4:la reponse est null !"); end if ((retry or 5)< 5) then fibaro:debug("Retry #"..retry.."process, please wait..."); fibaro:sleep(5000); return getExt(tonumber(retry+1)); else return false; end end; end function EmonCMS:Push(payloademon) payloademon = "/input/post.json?json={" .. EmonCMS_Prefix .. payloademon .. "}&apikey=" .. emoncms_api_key response, status, errorCode = emoncms:GET(payloademon); fibaro:debug("Payload: " .. payloademon) ; fibaro:debug("response: " .. response .. " Status: " .. status .. " errorcode: " .. errorCode) ; fibaro:sleep(500); end local function main() -- retrieve values from netatmo.php local resInt, resExt, resMod2, resMod3, resMod4 = false, false, false, false, false; local status, err = pcall(function () resInt = getInt(); end); fibaro:debug("Récupération des données intérieures: " .. tostring(resInt)); if (status == false) then fibaro:debug("err: "..tostring(err or 'n.c')); end local status, err = pcall(function () resExt = getExt(); end); fibaro:debug("Récupération des données extérieures : " .. tostring(resExt)); if (status == false) then fibaro:debug("err: "..tostring(err or 'n.c')); end local status, err = pcall(function () resMod2 = getMod2(); end); fibaro:debug("Récupération des données intérieures Mod2: " .. tostring(resMod2)); if (status == false) then fibaro:debug("err: "..tostring(err or 'n.c')); end local status, err = pcall(function () resMod3 = getMod3(); end); fibaro:debug("Récupération des données intérieures Mod3: " .. tostring(resMod3)); if (status == false) then fibaro:debug("err: "..tostring(err or 'n.c')); end local status, err = pcall(function () resMod4 = getMod4(); end); fibaro:debug("Récupération des données intérieures Mod4: " .. tostring(resMod4)); if (status == false) then fibaro:debug("err: "..tostring(err or 'n.c')); end refreshUI( "Ext: "..temperature_exterieure.." °C - "..humidite_exterieure.." % - "..pression.." mbar", "Bruit Rez: "..bruit.." dB", "Rez - Emilien - Thomas - Parents", temperature_interieure.." - "..temperature_int_mod2.." - "..temperature_int_mod3.." - "..temperature_int_mod4.." °C ", co2.." - "..co2_mod2.." - "..co2_mod3.." - "..co2_mod4.." ppm", humidite_interieure.." - "..humidite_int_mod2.." - "..humidite_int_mod3.." - "..humidite_int_mod4.." % ", os.date("%H:%M"), tostring(resInt).." "..tostring(resExt).." "..tostring(resMod2).." "..tostring(resMod3).." "..tostring(resMod4) ); -- Push To EMONCMS -- if PushToEmonCMS == true then payloademon = "temperature_exterieure:"..temperature_exterieure EmonCMS:Push(payloademon); payloademon = "humidite_exterieure:".. humidite_exterieure EmonCMS:Push(payloademon); payloademon = "pression:".. pression EmonCMS:Push(payloademon); payloademon = "bruit:".. bruit EmonCMS:Push(payloademon); payloademon = "temperature_interieure_Rez:".. temperature_interieure EmonCMS:Push(payloademon); payloademon = "temperature_int_mod2_Emilien:".. temperature_int_mod2 EmonCMS:Push(payloademon); payloademon = "temperature_int_mod3_Thomas:".. temperature_int_mod3 EmonCMS:Push(payloademon); payloademon = "temperature_int_mod4_Parents:".. temperature_int_mod4 EmonCMS:Push(payloademon); payloademon = "humidite_interieure_Rez:".. humidite_interieure EmonCMS:Push(payloademon); payloademon = "humidite_int_mod2_Emilien:".. humidite_int_mod2 EmonCMS:Push(payloademon); payloademon = "humidite_int_mod3_Thomas:".. humidite_int_mod3 EmonCMS:Push(payloademon); payloademon = "humidite_int_mod4_Parents:".. humidite_int_mod4 EmonCMS:Push(payloademon); payloademon = "co2_Rez:".. co2 EmonCMS:Push(payloademon); payloademon = "co2_mod2_Emilien:".. co2_mod2 EmonCMS:Push(payloademon); payloademon = "co2_mod3_Thomas:".. co2_mod3 EmonCMS:Push(payloademon); payloademon = "co2_mod4_Parents:".. co2_mod4 EmonCMS:Push(payloademon); end -- Compute Value MAX CO2 Maison (For VMC Speed VD) if CO2_Max_Value_Local == false then fibaro:debug("not calculating nor storing CO2 Max Value") else CO2_Max_Value_Local = co2 if CO2_Max_Value_Local < co2_mod2 then CO2_Max_Value_Local = co2_mod2 end if CO2_Max_Value_Local < co2_mod3 then CO2_Max_Value_Local = co2_mod3 end if CO2_Max_Value_Local < co2_mod4 then CO2_Max_Value_Local = co2_mod4 end fibaro:setGlobal("CO2_Max_Value", CO2_Max_Value_Local ) fibaro:debug("CO2_Max_Value: ".. CO2_Max_Value_Local ) end end main();
  8. Je voulais partager avec vous la solution que j'ai mis en place pour suivre ma consommation d'eau. Alors j'ai choisi d'un installer un compteur d'eau "Débitmètre avec sortie d'impulsion Compteur d'eau Générateur de débit d'eau 1 Imp./L Qn 1,5m³/h" J'ai connecté l'impulsion sur un détecteur domotique universel FGBS-0001 entre la pin IN2 et GND. Coté HC2, le capteur est vu comme un capteur de présence, dans mon cas j'ai choisi un capteur de porte. Je coche la case qui permet d'exclure ce capteur des alarmes. Je désactive les alarmes (paramètre 13) en mode broadcast disable. Enfin, j'active dans les options avancées du capteur , le mode scène (paramètre 14 positionné sur ON). Je sauvegarde ce paramètre. Ensuite, j'utilise le service ThingSpeak.com pour pouvoir grapher les résultats. Ce service à l'avantage d'être très simple à mettre en place. Il suffit de créé un "Channel" et je nomme le "field1" -> 'Consommation d'eau'. Dans l'onglet "API Keys" du site ThingSpeak, je sauve la valeur de la clé pour le mode écriture ("Write API Key"). Sur le graphique de ce channel, je choisi le mode "SUM 60 minutes en mode ligne" pour avoir un affichage cumulé des consommations sur une période de 1 heure. Je créé un Virtual Device que je nomme "Graph Eau" avec un bouton que je nomme "grapheau". Et J'utilise le code LUA suivant : fibaro:log('Actualisation consommation eau') thingspeak = Net.FHttp('api.thingspeak.com') payload = 'key=VOTREWRITEAPIKEY&field1=1' response, status, errorCode = thingspeak:POST('/update', payload) Je vais dans le menu Scène et je créé une nouvelle scène que je nomme "Graphique Eau", je créé la scène avec le mode utilisant les blocs pour plus de simplicité. Le paramètre 14 du capteur de présence indique que sur l'entrée IN2, un front montant (OFF -> ON) déclenche un code scène 20. Donc j'indique que "SI le capteur du compteur d'eau == "scène activation" 20 alors j’exécute le bouton "grapheau" du virtual device "Graph Eau". Et voilà ! Cela nous donne un graphique heure par heure de la consommation d'eau. Il est à noter que j'ai choisi un compteur qui me donne 1 impulsion par litre rendant l'interprétation des résultats plus facile. J'espère que cela vous sera utile, je trouve la solution assez élégante et facile à mettre en place.
  9. EDIT : VD disponibles dans les pages suivantes Ce tuto est un projet qui démarre, il n'y a encore rien à partager... Mais vu la saison, j'ai la pression. Le but du virtal device est de simplifier la gestion de la piscine, en commençant par la filtration. Pour le moment je débute en LUA et VD et je m'attaque à la logique avant de l'enrober dans un VD ou plugin. La partie logique ne devrait pas trop poser de problème mais l'absence de fonctions partagées sur la HC2 rends les codes peu digeste à priori un peu de théorie: Vous trouverez plein de sites qui traitent de la filtration piscine allant du simple 'température / 2' à des notions plus complexes. Je me base sur la notion de 'durée de cycle' pour régler le temps de marche de la pompe. En effet dans l'absolu le temps n'est pas un bon critère car tout dépend du dimensionnement de la filtration versus le volume de la piscine. Une règle de base répandue sur le net donne Eau > 25 °C : on conseille 3 cycles complets de filtration, au minimum 12 h. 20 °C < eau < 24 °C : compter environ 1 à 2 cycles de filtration soit de 10 à 11 h. 15 °C < eau < 20 °C : 1 cycle complet suffit. 10 °C < eau < 14 °C : ½ voire même ¼ de cycle dans ce cas, ce qui dure approximativement entre 1 et 2 h. Eau < 10 °C : dans ce cas la filtration quotidienne est facultative. Avec un peu de lissage on obtient une courbe température / cycles (donc durée) de la forme Cette courbe n'est pas linéaire mais sans entrer dans les détails elle reste un cas général à adapter à chaque bassin (type désinfection, fréquentation moyenne, environnement....) Je propose de ne pas trop discuter la forme/hauteur de la courbe sur ce forum... De toute façon le VD permettra de fixer votre courbe de référence allant de la simple droite à une forme ultra 'optimisée'. des choix à faire: Vous trouverez de tout comme stratégie pour économiser/optimiser perso je suis plutôt contre la filtration de nuit en HC... - bon et au final + cher filtrer X minutes par heure pour atteindre la durée totale me parait moyen aussi pour mon algo (à créer) je pars sur - 1 à 3 périodes de filtration par jour - filtrer plus en fin de journée pour compenser la fréquentation et assurer un bon nettoyage avant le repos nocturne - j'ai des HC entre 12h et 13h30 autant filtrer (il n'y a pas de petites économies). De plus avoir une filtration fixe vers midi permettra de prendre une température de référence cohérente de jour en jour en plus de la gestion automatique le VD doit permettre de superposer des périodes de 'filtration choc' ; départ immédiat et non-stop pour 12, 24, 48h d'appliquer une correction à la courbe 0 à 400% par exemple pour s'adapter aux périodes de sur-fréquentation ou vent ou.... de proposer un bouton 'baignade' qui permettrait de mettre en marche une heure histoire d’être certain d'avoir la circulation d'eau pour masser le dos :-). de reprendre la planification après un reboot HC2 quelques pistes pour l'affichage dans le VD affichage température de référence utilisée pour le calcul + durée totale de filtration du mode auto affichage température courante affichage état pompe bouton baignade bouton "CHOC +12" + affichage progression choc totale/restante bouton "annuler choc" ajustement 0 à 400% Je vais arrêter la, car c fait déjà pas mal de cas à gérer sans tomber dans une usine à gaz. voila une maquette de VD
  10. Déshumidificateur avec planification automatique Préambule : Après quelques recherches pour configurer un panneau d'humidité et l'avoir lié à un détecteur d'humidité branché sur un wallplug, j'ai eu la désillusion de constater que le panneau d'humidité de nos HCL/HC2 ne permet pas de gérer la déshumidification mais l'humidification d'une pièce merci à @Nico pour la précision. Qu'à cela ne tienne, je me suis lancer dans la création de la fonctionnalité de déshumidification en maintenant l'utilisation d'un panneau humidité (mais sans le lier). Pour cela, je me suis inspiré du VD de @Steven permettant de gérer son chauffage en utilisant un panneau de chauffage. Le principe est quasi le même, mais avec un fonctionnement inversé. Le Projet : Le but du projet consiste à déshumidifier un pièce en fonction du taux humidité relevé par un capteur humidité (dans mon cas un module NetAtmo). L'objectif étant : de limiter le taux humidité tout est minimisant la consommation électrique de ce type d'appareil (qui sont très gourmands). de pouvoir gérer des périodes de fonctionnement selon les jours de la semaine et des tranches horaires (exemple : période d'absence dans la pièce, cf. bruit de l'appareil) de pouvoir automatiser son fonctionnement selon 3 modes : automatique selon les consignes du panneau d'humidité selon les jours et les tranches horaires vacance durant lequel le fonctionnement est constant selon une consigne d'humidité maximum définit arrêt à la demande manuel via la fonction disponible au niveau du panneau d'humidité, pour une consigne (taux d'humidité et durée de fonctionnement) d'intercepter les moments ou le reservoir du déshumidificateur est plein d'éviter de faire tourner le déshumidificateur si une porte ou un fenêtre est ouverte. synchroniser le VD avec le panneau d'humidité (mode vacance et mode manuel) Usages : Toutes pièce humide (pièce exposée au nord, salle de bains, cave à vin, ...) Pré-requis : 1) Configurer un panneau d'humidité 2) Disposer d'un détecteur d'humidité dans la pièce à réguler 3) Disposer d'un WallPlug pour démarrer/arrêter le déshumidificateur et mesurer la consommation électrique 4) Disposer de détecteurs d'ouverture (fenêtre, porte) si utilisation de la fonction qui permet d'éviter de faire tourner le déshumidificateur si une porte ou un fenêtre est ouverte. Installation : Importer le VD ci-dessous : Charger les icônes ci-dessous Configurer les variables du bouton Raffraichissement Configurer un panneau d'humidité Configuration : Un ensemble de variables sont disponibles pour l'utilisateur, -- User variables local modetrace = true -- permet de voir le résultat du traitement local modedebug = true -- permet de suivre les différente étapes lors de l'exécution du traitement Humidity.IdDoorWindows = {85, 102} -- permet d'éviter de faire tourner le déshumidificateur si une porte ou un fenêtre est ouverte (il est possible de renseigner plusieurs portes et fenêtres) à compléter ... Evolution à venir : Notification (Mail, SMS, Message Vocal, ..) lorsque le bac est plein Vos idées/suggestions d'évolutions sont les bienvenues Versions : V1.0 : du 02/11/2017 -> Première version V1.1 : du 05/11/2017 -> Amélioration de la gestion des icônes V1.2 : du 11/11/2017 -> Nouvelles icônes (amélioration du graphisme), simplification du code, amélioration des labels avec des icônes V1.3 : du 12/11/2017 -> Ajout d'une fonction qui permet d'éviter de faire tourner le déshumidificateur si une porte ou un fenêtre est ouverte. Ajout de l'icône correspondante. V1.4 : du 12/11/2017 -> Synchronisation bidirectionnelle du VD avec le panneau d'humidité (mode vacance et mode manuel) Ajout du mode manuel via la fonction disponible au niveau du panneau d'humidité, pour une consigne (taux d'humidité et durée de fonctionnement) Ajout d'une icône pour le bouton rafraichir. Attention les boutons Auto et Stop contiennent du nouveau code Sources : Virtual Device : Déshumidificateur V.1.4.vfib.json Code Lua du bouton "Rafraichir" : Déshumidificateur V1.4.lua Icônes : Déshumidificateur V1.3.lua
  11. jojo

    Images Clé Usb

    Bonjour, Il y a de plus en plus de demandes des fichiers images de la clé recovery de la HC2. Alors j'ai mis cela en public sur mon Google Drive Il contient un un gros fichier ZIP (2,4 GB) "USB RECOVERY HC2" : qui contient une image complète de la clé USB recovery. Complète = la FAT32 et les autres partitions nécessaires. L'image est celle de la 4.056 Le sous-dossier le l'image contient un répertoire /backups avec quelques vieux backups à moi, qui vous seront d'aucune utilité => vous pouvez détruire le contenu de ce répertoire (PAS le répertoire). Voir le tuto de @mprinfo pour son utilisation. Il contient actuellement 4 folders "Recovery Image 3.xxx" : le dossier system qui contient l'image (v3.x) utilisée par le HC2 lors qu'un recovery. Ce dossier se trouve dans la FAT32 de la clé USB "Recovery Image 4.031" : le dossier system qui contient l'image (v4.031) utilisée par le HC2 lors qu'un recovery. Ce dossier se trouve dans la FAT32 de la clé USB "Recovery Image 4.056" : le dossier system qui contient l'image (v4.056) utilisée par le HC2 lors qu'un recovery. Ce dossier se trouve dans la FAT32 de la clé USB "USB RECOVERY HC2" : un gros fichier ZIP (2,4 GB) qui contient une image complète de la clé USB recovery. Complète = la FAT32 et les autres partitions nécessaires. Voir le tuto de mprinfo pour son utilisation. et 1 fichier avec un exemple de doc que je maintiens pour pouvoir repartir de zéro (>60 pages ...)
  12. sebcbien

    Topic Unique S. A. R. A. H.

    Voilà , pas trop de temps pour le moment, mais je vais voir ce que je peux pondre comme tuto pour S.A.R.A.H. Comme je l'ai déjà dit, en général l'installation va toute seule mais parfois ça merde et là 'fo du Barbu costO !... En gros: Windows 10 Installé sur un petit laptop c'est top, pas de place, silencieux, économe en énergie... Télécharger SARAH V4 dans c:/sarah Ajouter le plugin sonos Utiliser mon VD Sarah Say it Pour plus de détails, voir le post suivant. Ancien posts: ------------------- Voici un aperçu Pour la qualité, l'enregistrement n'est pas top mais le volume est au minimum car les enfants dorment Pour la vitesse de conversion en TTS, je pense que ça vous donne une idée... Et l'interruption de la musique est impec et reprends juste après. ----------------- et la photo de mon serveur Jeedom/S.A.R.A.H. Le serveur fermé, c'est beau: Ouvert: Comme vous pouvez le voir c'est un vieux laptop récupéré car l'écran est fichu, tombé de haut et utilisable uniquement en remote ou avec un autre écran.. C'est installé avec Windows 10 et je prends en remote avec TeamViewer. J'ai mon Jeedom qui tourne dans VirtualBox et S.A.R.A.H. sur le windows Consommation en charge avec JD et SARAH: 12W à 15W incluant un UPS avec shutdown automatique svp... (la batterie est encore bonne) J'ai presque envie de relancer ma VM xpenology pour transcoder, là il y a plus de hummph que avec mon DS 412+... C'est tout nouveau, je suis très content de ma solution... avant Jeedom tournait sur mon pc principal qui bouffait entre 70 et 90W en permanence...
  13. Tout est dans le titre. Il s'agit d'un simple device virtuel permettant de rebooter ou arreter un serveur synology. L'idée est inspirée de la solution de Labomatik pour QNAP La solution est tres tres largement inspirée du module virtuel de lazer permettant de piloter la surveillance station ... effectivement, je n'ai pas inventé grand chose. Toute la mécanique d'authentification est issue du dev de Lazer (que je remercie au passage). Les fonctions que l'on exploite ici ne sont pas officiellement mise à dispo par l'API Synology, mais un peu de reverse engeneering permet de retrouver ce qui est fait par l'interface web du synology. La configuration est tres simple : - Paramétrer l'adresse IP et le port du device virtuel avec l'adresse ip et le port du synology ==> Il doit s'agir d'un port HTTP. La solution ne supporte pas l'HTTPS. Dans chaque bouton, remplacer les variables par un login / password existant sur votre synology. Attention : Il doit s'agir d'un utilisateur ayant des droits admin Ajouté au virtuel device de Lazer, nous voilà aussi bien équipé que les utilisateurs QNAP. Plus de jaloux! Une remarque pour ceux qui souhaitent égallement redémarrer leur synology via la HC2 : Tous les synology ne supportent pas le Wake On Lan. Plus d'info : https://www.synology.com/fr-fr/knowledgebase/faq/437 Synology.vfib Icone pour le device virtuel :
  14. Pour faire face au problème récurrent de désynchronisation de l'horloge du HC2 voici un vd très largement inspiré par le support Fibaro cf. internal clock Homecenter is slow Il fonctionne a merveille sur mon HC2 qui n'est plus a la traine maintenant La synchronisation avec le serveur NTP sera faite une fois par jour en automatique par le VD mais il est aussi possible de faire une demande en manuel en cliquant sur le bouton Clock Sync dans le détail du VD ou sur le bouton du VD sur la home du HC2. Voici la miniature pour le vd: Pour la configuration du vd c'est très simple: après l'importation dans le HC2 et renseigné l'adresse IP et le port du HC2 dans l'onglet avancé il faut éditer le code du main loop et de modifier la variable synchroTime avec l'heure de mise à jour. Puis editer le code du bouton btnSync et de modifier les variables username et password avec votre userid et votre password admin de votre HC2 afin de pousser la modification sur votre HC2 par l' API Settings.... Le fichier vfib a importer sur le HC2: Clock_Sync.vfib PS: Si l'importation ne marche pas depuis le HC2, veuillez utiliser le Toolkit pour importer le vd Cette solution est du bidouillage mais cela marche très bien donc pour le moment cela me convient ! Amusez-vous bien...
  15. cboubou

    Module Virtuel "smartvmc"

    Bonjour la communauté, Je vous propose aujourd'hui mon module virtuel "SmartVMC". Ce dernier me permet de piloter de manière automatique ma VMC en fonction de la qualité de l'air de ma maison : On allume la VMC si le taux moyen d'humidité relative est supérieur à 60% OU si la concentration moyenne de CO2 est supérieure à 1000 ppm. Le traitement s'arrêtera si le taux moyen d'humidité relative est inférieur ou égal à 55% ET si la concentration moyenne de CO2 est inférieure ou égale à 900 ppm. Le but étant de ne pas allumer/éteindre la VMC dès que l'on atteint la limite de 60% ou de 1000 ppm. Les données sur la qualité de l'air (humidité relative et concentration de CO2) sont extraites de ma Netatmo par le biais du plugin idoine disponible dans la V4. Ma configuration matérielle est la suivante : VMC simple flux, hygroréglable, Aldès, MicroWatt. Home Center 2 en version v4.033. WallPlug Fibaro pour piloter la VMC. Station Netatmo avec modules additionnels. Le module virtuel se présente de la sorte : Un visuel des moyennes d'humidité relative et de concentration de CO2. Un bouton permettant d'analyser à l'instant "t" l'air de la maison. Un visuel de l'état actuel de la VMC. Un bouton de marche forcée de la VMC. Un bouton d'arrêt complet de la VMC. Un bouton pour basculer la VMC en mode automatique. La date de la dernière analyse de l'air. Les 4 états différents de la VMC sont les suivants : Marche Forcée Arrêt Complet Auto (En cours...) Auto (Pause) Il est nécessaire de créer 2 variables globales : Une première variable globale "VMC" est utilisée afin de savoir si la VMC est : en marche automatique, en pause, en marche forcée ou arrêtée (Auto, Pause, Forcée, Arrêtée). Une seconde variable globale "RecyclAir" est utilisée afin de savoir si la VMC est déjà en train d'assainir l'air, par le biais de ce traitement (Oui, Non). J'ai commenté le code afin d'en faciliter la compréhension. NB : Il peut être envisageable pour les personnes possédant une VMC à 2 vitesses que le mode "Auto (En cours...)" corresponde à la grande vitesse et que le mode "Auto (Pause)" corresponde à la petite vitesse. Voici les icônes (2 variantes) : Orange => Marche Forcée Rouge => Arrêt Complet Vert => Auto (En cours...) Bleu => Auto (Pause) Les originaux qui m'ont servi de base sont ici : http://www.domotique...zibase/?p=25155 Vous trouverez également de magnifiques icônes pour la Netatmo ici (merci Stef). ChangeLog => v1.0 : Création du module. v1.1 : Ajout du push lors du passage "En cours" <=> "Pause". Modification des conditions du passage au mode "Auto". Ajout d'un contrôle sur l'état du plugin Netatmo pour mode "Auto". SmartVMC.vfib
  16. Bonjour, Voilà , le code est enfin correct, je le partage donc. Je n'ai pas beaucoup de temps ce soir, mais voici 2-3 points: - Ce VD crée automagiquement 3 Variables globales (si demandé dans les options) - Ce VD est multilingue - Ce VD fait des push de la météo à deux moments de la journée - CE VD s'adapte aux mobiles et à l'interface web - Ce VD télécharge automagiquement les icônes - Ce VD a besoin d'une clef APi de Wunderground, - La partie mobile du VD n'est pas encore complètement terminée. Merci à Jompa68 de forum.fibaro.com pour le code de base Pour l'installer: - Téléchargez le vfib attaché et importez le dans la HC2 - Changer l'icône du slider avec l'icône attachée: - Utilisez le dernier code disponible sur github: https://github.com/sjauquet/YAMSWU Qui ajoute la création de VG qui contiendront la météo prononçable par une synthèse vocale comme S.A.R.A.H.: http://www.domotique-fibaro.fr/index.php/topic/6446-yams-wu-yet-another-meteo-station-wunderground-version/page-4#entry132933 et placez-le dans le main loop du VFIB (V3.9) attaché à ce message - Changez l'api key. Pour cela, créez un compte wunderground et allez la récupérer ici: http://www.wunderground.com/weather/api/ WU.APIkey = "xxxxxxxxxxxxxxx" - Ensuite définissez les variables suivantes: WU.PWS = "IGVLEBOR5" -- The PWS location to get data from (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data from (City location) WU.station = "PWS" -- Choose your prefered method to retrieve from: PWS or LOCID Personnellement je préfère utiliser les infos d'une pws près de chez moi. Pour trouver ces variables: @bono2007 écrivait: Pour trouver, j'ai eu la station PWS en cliquant dans "Search locations" sur Wunderground, on te propose "search nearest station", et il a proposé une station météo proche. Sinon en entrant ta ville, tu peux cliquer sur "change Station" et tu verras une carte avec d'autres stations météo. Exemple : j'ai entré "Boussois" et j'ai comme station météo "Cit du Grand Bois, Récquignies ( IRECQUIG2) J'ai modifié WU.PWS = "IRECQUIG2" Et tout devrait fonctionner :-) Virtual device avec code V3.7 (ancien à remplacer !!! ) YAMS_WU.vfib Virtual device avec code V3.9 YAMS_WU V3.9.vfib Voici les dernières captures d'écran pour avoir une idée: à gauche en mode Browser Web, à droite en mode Mobile (les icônes ne sont pas téléchargeables) Attention, ancien code ci-dessous ! ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- WU WeatherData - Fetch weather data from wunderground.com. Multilanguage support! -- Original Code by Jonny Larsson 2015 http://forum.fibaro.com/index.php?/topic/19810-wu-weatherdata-version-202-2015-10-25/ -- forked by Sébastien Jauquet 11/2015 -- Inspired by GEA(steven), stevenvd, Krikroff and many other users. -- Source - forum.fibaro.com, domotique-fibaro.fr and worldwideweb -- -- Version 3.7 -- -- PWS = Personal Weather Station -- LOCID = Public station -- -- 2014-03-22 - Permissions granted from Krikroff -- 2014-03-23 - Added rain and forecast, Added FR language. -- 2014-03-23 - Language variable changed to get the translation from wunderground.com in forcast -- 2014-03-24 - Added PL language -- 2014-03-24 - Select between PWS or LOCID to download weather data -- 2015-10-23 - New source code. -- 2015-11-13 - V3.0 - Fork Code by Sebastien Jauquet (3 days forecast, rain in mm) -- 2015-11-14 - V3.1 - Compatibilty with GEA, French translation -- 2015-11-14 - V3.2 - Catch rain errors (-999mm null empty etc.) -- 2015-11-14 - V3.3 - Catch json decode error (was stopping main loop) with pcall (can be extended to other jdon datas if needed) -- 2015-11-16 - V3.4 - Generate HTML and non HTML version (for compatibility with mobiles) -- 2015-11-18 - V3.5 - Fixed bug not updating Meteo_Day becaus WU.now was only updated at first launch -- 2015-11-18 - V3.6 - Merged some changes from jompa new version -- 2015-11-18 - Added autmatic creation of Global Variables if not existing -- 2015-11-19 - V3.7 - Modify schedule management and CleanUp code -- Look for nearest station here: http://www.wunderground.com ------------------------------------------------------------------------------------------- -- MAIN CODE -- ------------------------------------------------------------------------------------------- WU = {} -- WU settings WU.APIkey = "xxxxxxxxxxxxxxx" -- Put your WU api key here WU.PWS = "IGVLEBOR5" -- The PWS location to get data for (Personal Weather Station) WU.LOCID = "SWXX0076" -- The location ID to get data for (City location) WU.station = "PWS" -- PWS or LOCID -- Other settings WU.translation = {true} WU.language = "FR"; -- EN, FR, SW, PL (default is en) WU.smartphoneID = 1347 -- your smartphone ID WU.sendPush = true -- send forecast as push message WU.push_fcst1 = "07:00" -- time when forecast for today will be pushed to smartphone WU.push_fcst2 = "18:15" -- time when forecast for tonight will be pushed to smartphone WU.GEA = true -- subst % with %% when storing in the VG's (because gea bug with % in push messages) WU.CreateVG = true -- will atomaticaly create global variables at first run if = true updateEvery = 30 -- get data every xx minutes WU.startTime = os.time() WU.scheduler = os.time()+60*updateEvery WU.currentDate = os.date("*t"); WU.now = os.date("%H:%M"); DoNotRecheckBefore = os.time() WU.selfId = fibaro:getSelfId() WU.version = "3.7" WU.translation["EN"] = { Push_forecast = "Push forecast", Exiting_loop_slider = "Exiting loop earlier (Slider Changed)", Exiting_loop_push = "Exiting loop earlier (For push)", Last_updated = "Last updated", Temperature = "Temperature", Humidity = "Humidity", Pressure = "Pressure", Wind = "Wind", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", Update_interval = "Next update will be in (min)", No_data_fetched = "No data fetched", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["FR"] = { Push_forecast = "Push des prévisions", Exiting_loop_slider = "Sortie de boucle (Slider Changé)", Exiting_loop_push = "Sortie de boucle (Pour Push)", Last_updated = "Mise à jour", Temperature = "Actuellement", Humidity = "Hum", Pressure = "Pression", Wind = "Vent", Rain = "Pluie", Forecast = "Prévisions pour ce", Station = "Station", Fetched = "Données Reçues", Data_processed = "Données mises à jour", Update_interval = "Prochaine Mise à jour prévue dans (min)", No_data_fetched = "Pas de données reçues !!", NO_STATIONID_FOUND = "StationID non trouvée !!", NO_DATA_FOUND = "Pas de données disponibles !!" } WU.translation["SW"] = { Push_forecast = "Push forecast", Exiting_loop_slider = "Exiting loop earlier (Slider Changed)", Exiting_loop_push = "Exiting loop earlier (For push)", Last_updated = "Last updated", Temperature = "Temperatur", Humidity = "Fuktighet", Pressure = "Barometer", Wind = "Vind", Rain = "Regn", Forecast = "Prognos", Station = "Station", Fetched = "Hà¤mtat", Data_processed = "All data processat", Update_interval = "Nà¤sta uppdatering à¤r om (min)", No_data_fetched = "Inget data hà¤mtat", NO_STATIONID_FOUND = "StationID ej funnet", NO_DATA_FOUND = "Ingen data hos WU" } WU.translation["PL"] = { Push_forecast = "Push prognoza", Exiting_loop_slider = "Exiting loop earlier (Slider Changed)", Exiting_loop_push = "Exiting loop earlier (For push)", Last_updated = "Last updated", Temperature = "Temperatura", Humidity = "Wilgotnosc", Pressure = "Pressure", Wind = "Wiatr", Rain = "Rain", Forecast = "Forecast", Station = "Station", Fetched = "Fetched", Data_processed = "Data processed", No_data_fetched = "No data fetched", Update_interval = "Next update will be in (min)", NO_STATIONID_FOUND = "No stationID found", NO_DATA_FOUND = "No data found" } WU.translation["NL"] = { Push_forecast = "Push verwachting", Exiting_loop_slider = "Exiting loop earlier (Slider Changed)", Exiting_loop_push = "Exiting loop earlier (For push)", Last_updated = "Last updated", Temperature = "Temperatuur", Humidity = "Vochtigheid", Pressure = "Druk", Wind = "Wind", Rain = "Regen", Forecast = "Verwachting", Station = "Weerstation", Fetched = "Ontvangen", Data_processed = "Gegevens verwerkt", Update_interval = "Volgende update in (min)", No_data_fetched = "Geen gegevens ontvangen", NO_STATIONID_FOUND = "Geen stationID gevonden", NO_DATA_FOUND = "Geen gegevens gevonden" } WU.translation["DE"] = { Push_forecast = "Push vorhersage", Exiting_loop_slider = "Exiting loop earlier (Slider Changed)", Exiting_loop_push = "Exiting loop earlier (For push)", Last_updated = "Last updated", Temperature = "Temperatur", Humidity = "Luftfeuchtigkeit", Pressure = "Luftdruck", Wind = "Wind", Rain = "Regen", Forecast = "Vorhersage", Station = "Station", Fetched = "Abgerufen", Data_processed = "Daten verarbeitet", No_data_fetched = "Keine Daten abgerufen", Update_interval = "Das nà¤chste Update in (min)", NO_STATIONID_FOUND = "Keine stationID gefunden", NO_DATA_FOUND = "Keine Daten gefunden" } Debug = function ( color, message ) fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, message, "span")); end WU.createGlobalIfNotExists = function (varName, defaultValue) if (fibaro:getGlobal(varName) == "") then Debug("red", "Global Var: "..varName.." HAS BEEN CREATED") newVar = {} newVar.name = varName HC2 = Net.FHttp("127.0.0.1", 11111) HC2:POST("/api/globalVariables", json.encode(newVar)) end end WU.substPercent = function(doublePercentSymbol) if WU.GEA then doublePercentSymbol = string.gsub(doublePercentSymbol, "%%.", "%%%%") end return doublePercentSymbol end WU.cleanJson = function(jsontocheck,returnIfTrue) if jsontocheck == "-999.00" or jsontocheck == "--" or jsontocheck == json.null then jsontocheck = returnIfTrue end local ok = pcall(function() testConcatenate = "Test Concatenate: " .. jsontocheck -- test for non concatenate value end ) if (not ok) then decode_error = true Debug( "red", "decode raised an error") fibaro:call(WU.smartphoneID , "sendPush", "decode error in WU Meteo") end return jsontocheck end WU.HtmlColor = function(StringToColor,color) if MobileDisplay == false then StringToColor= "<font color=\""..color.."\"> "..StringToColor.."</font>" end return StringToColor end WU.IconOrText = function(icon,txt) if MobileDisplay == false then IconOrText = "<img src="..icon.."\>" else IconOrText = txt end return IconOrText end WU.getSlider = function() ValeurSliderfunct = fibaro:getValue(WU.selfId , "ui.WebOrMobile.value") return tonumber(ValeurSliderfunct) end WU.setSlider = function(position) fibaro:call(WU.selfId , "setProperty", "ui.WebOrMobile.value", position) return WU.getSlider() end WU.checkMobileOrWeb = function() ValeurSliderSleep = WU.getSlider() -- check slider value at first run if ValeurSliderSleep <= 50 then if ValeurSliderSleep == 1 then MobileDisplay = false else MobileDisplay = false WU.runDirect = 1 sleepAndcheckslider = 20*updateEvery -- exit wait loop Debug("orange", WU.translation[WU.language]["Exiting_loop_slider"]); end WU.setSlider(1) -- désactive le run immediat lors du prochain test end if ValeurSliderSleep >= 50 then if ValeurSliderSleep == 98 then else MobileDisplay = true WU.runDirect = 1 sleepAndcheckslider = 20*updateEvery -- exit wait loop Debug("orange", WU.translation[WU.language]["Exiting_loop_slider"]); end WU.setSlider(98) -- désactive le run immediat lors du prochain test end return WU.getSlider() end WU.fetchWU = function() decode_error = false WU.checkMobileOrWeb() local WGROUND = Net.FHttp("api.wunderground.com",80); local response ,status, err = WGROUND:GET("/api/"..WU.APIkey.."/conditions/forecast/lang:"..WU.language.."/q/"..WU.station..":"..locationID..".json"); if (tonumber(status) == 200 and tonumber(err)==0) then Debug( "cyan", WU.translation[WU.language]["Fetched"]) if (response ~= nil) then WU.now = os.date("%H:%M") jsonTable = json.decode(response); if jsonTable.response.error ~= nil then Debug( "red", WU.translation[WU.language]["NO_DATA_FOUND"]) fibaro:sleep(15*1000) return end stationID = jsonTable.current_observation.station_id; humidity = jsonTable.current_observation.relative_humidity temperature = jsonTable.current_observation.temp_c pression = jsonTable.current_observation.pressure_mb wind = jsonTable.current_observation.wind_kph rain = WU.cleanJson(jsonTable.current_observation.precip_today_metric,"0") weathericon = jsonTable.current_observation.icon_url fcstday1 = jsonTable.forecast.txt_forecast.forecastday[1].title -- Day meteo fcst1 = jsonTable.forecast.txt_forecast.forecastday[1].fcttext_metric fcst1icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcst1SmallTxt = jsonTable.forecast.simpleforecast.forecastday[1].conditions fcst1Tmax = jsonTable.forecast.simpleforecast.forecastday[1].high.celsius fcst1Tmin = jsonTable.forecast.simpleforecast.forecastday[1].low.celsius fcst1avewind =jsonTable.forecast.simpleforecast.forecastday[1].avewind.kph fcst1avewinddir =jsonTable.forecast.simpleforecast.forecastday[1].avewind.dir fcst1mm = WU.cleanJson(jsonTable.forecast.simpleforecast.forecastday[1].qpf_day.mm,"0") fcstday2 = jsonTable.forecast.txt_forecast.forecastday[2].title -- Evening Meteo fcst2 = jsonTable.forecast.txt_forecast.forecastday[2].fcttext_metric fcst2icon = jsonTable.forecast.txt_forecast.forecastday[2].icon_url fcst2SmallTxt = jsonTable.forecast.simpleforecast.forecastday[2].conditions fcst2Tmax = jsonTable.forecast.simpleforecast.forecastday[2].high.celsius fcst2Tmin = jsonTable.forecast.simpleforecast.forecastday[2].low.celsius fcst2avewind =jsonTable.forecast.simpleforecast.forecastday[2].avewind.kph fcst2avewinddir =jsonTable.forecast.simpleforecast.forecastday[2].avewind.dir fcst2mm = WU.cleanJson(jsonTable.forecast.simpleforecast.forecastday[1].qpf_night.mm,"0") fcstday3 = jsonTable.forecast.txt_forecast.forecastday[3].title -- Tomorrow fcst3 = jsonTable.forecast.txt_forecast.forecastday[3].fcttext_metric fcst3icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcst3SmallTxt = jsonTable.forecast.simpleforecast.forecastday[1].conditions fcst3Tmax = jsonTable.forecast.simpleforecast.forecastday[1].high.celsius fcst3Tmin = jsonTable.forecast.simpleforecast.forecastday[1].low.celsius fcst3avewind =jsonTable.forecast.simpleforecast.forecastday[1].avewind.kph fcst3avewinddir =jsonTable.forecast.simpleforecast.forecastday[1].avewind.dir fcst3mm = WU.cleanJson(jsonTable.forecast.simpleforecast.forecastday[2].qpf_allday.mm,"0") fcstday5 = jsonTable.forecast.txt_forecast.forecastday[5].title -- In 2 days fcst5 = jsonTable.forecast.txt_forecast.forecastday[5].fcttext_metric fcst5icon = jsonTable.forecast.txt_forecast.forecastday[1].icon_url fcst5SmallTxt = jsonTable.forecast.simpleforecast.forecastday[1].conditions fcst5Tmax = jsonTable.forecast.simpleforecast.forecastday[1].high.celsius fcst5Tmin = jsonTable.forecast.simpleforecast.forecastday[1].low.celsius fcst5avewind =jsonTable.forecast.simpleforecast.forecastday[1].avewind.kph fcst5avewinddir =jsonTable.forecast.simpleforecast.forecastday[1].avewind.dir fcst5mm = WU.cleanJson(jsonTable.forecast.simpleforecast.forecastday[3].qpf_allday.mm,"0") if (stationID ~= nil) and decode_error == false then fibaro:call(WU.selfId , "setProperty", "ui.lblStation.value", locationID); if temperature < 5 then cTemperature = WU.HtmlColor(temperature,"blue") elseif temperature > 18 then cTemperature = WU.HtmlColor(temperature,"red") else cTemperature = WU.HtmlColor(temperature,"yellow") end fibaro:call(WU.selfId , "setProperty", "ui.lblTempHum.value", WU.translation[WU.language]["Temperature"]..": "..cTemperature.." °C - "..WU.translation[WU.language]["Humidity"]..": "..humidity); fibaro:call(WU.selfId , "setProperty", "ui.lblWindRain.value", WU.translation[WU.language]["Wind"]..": "..wind.." km/h - "..WU.translation[WU.language]["Rain"]..": "..rain.." mm"); if (WU.now >= "00:00" and WU.now <= "15:59") then -- donne meteo du jour entre 00:00 (ou 3h) et 15:59. permet de garder la météo du soir jusqu'a 3h du matin, sinon change à minuit fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..WU.HtmlColor(fcstday1,"yellow")..": "..WU.HtmlColor(fcst1.." ("..fcst1mm.." mm)","green")); fibaro:setGlobal("Meteo_Day", WU.substPercent(WU.translation[WU.language]["Forecast"].." "..fcstday1..": ".." "..fcst1.." ("..fcst1mm.." mm)") ); fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value",WU.IconOrText(fcst1icon,fcst1SmallTxt)); elseif (WU.now >= "16:00" and WU.now <= "23:59") then -- donne meteo soirée entre 16:00 et 23:59 fibaro:call(WU.selfId , "setProperty", "ui.lblFcst.value", WU.translation[WU.language]["Forecast"].." "..WU.HtmlColor(fcstday2,"yellow")..": "..WU.HtmlColor(fcst2.." ("..fcst2mm.." mm)","green")); fibaro:setGlobal("Meteo_Day", WU.substPercent(WU.translation[WU.language]["Forecast"].." "..fcstday2..": ".." "..fcst2.." ("..fcst2mm.." mm)") ); fibaro:call(WU.selfId , "setProperty", "ui.lblIcon.value",WU.IconOrText(fcst2icon,fcst2SmallTxt)); end -- Meteo of Tomorrow fibaro:call(WU.selfId , "setProperty", "ui.lblFcstTomorrow.value", WU.translation[WU.language]["Forecast"].." "..WU.HtmlColor(fcstday3,"yellow")..": "..WU.HtmlColor(fcst3.." ("..fcst3mm.." mm)","green")); fibaro:setGlobal("Meteo_Tomorrow", WU.substPercent(WU.translation[WU.language]["Forecast"].." "..fcstday3..": ".." "..fcst3.." ("..fcst3mm.." mm)") ); fibaro:call(WU.selfId , "setProperty", "ui.lblIconTomorrow.value",WU.IconOrText(fcst3icon,fcst3SmallTxt)); -- Meteo in 2 Days fibaro:call(WU.selfId , "setProperty", "ui.lblFcst2Days.value", WU.translation[WU.language]["Forecast"].." "..WU.HtmlColor(fcstday5,"yellow")..": "..WU.HtmlColor(fcst5.." ("..fcst5mm.." mm)","green")); fibaro:setGlobal("Meteo_In_2_Days", WU.substPercent(WU.translation[WU.language]["Forecast"].." "..fcstday5..": ".." "..fcst5.." ("..fcst5mm.." mm)") ); fibaro:call(WU.selfId , "setProperty", "ui.lblIcon2Days.value",WU.IconOrText(fcst5icon,fcst5SmallTxt)); if WU.sendPush then if (os.date("%H:%M") == WU.push_fcst1) then -- fibaro:call(WU.smartphoneID , "sendPush", fcstday1.." - "..fcst1) -- envoie meteo du matin elseif (os.date("%H:%M") == WU.push_fcst2) then fibaro:call(WU.smartphoneID , "sendPush", fcstday2.." - "..fcst2) -- envoie meteo du soir end end if WU.sendPush then fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value", WU.translation[WU.language]["Push_forecast"].." = true"); else fibaro:call(WU.selfId , "setProperty", "ui.lblNotify.value",WU.translation[WU.language]["Push_forecast"].." = false"); end WU.scheduler = os.time()+updateEvery*60 fibaro:call(WU.selfId, "setProperty", "ui.lblUpdate.value", WU.translation[WU.language]["Last_updated"]..": "..os.date("%c")); Debug( "cyan", WU.translation[WU.language]["Data_processed"]) Debug( "white", WU.translation[WU.language]["Update_interval"].." "..updateEvery) else Debug( "red", WU.translation[WU.language]["NO_STATIONID_FOUND"]) end else fibaro:debug("status:" .. status .. ", errorCode:" .. errorCode); end end sleepAndcheckslider = 0 while sleepAndcheckslider <= 20*updateEvery do fibaro:sleep(3000) WU.checkMobileOrWeb() sleepAndcheckslider = sleepAndcheckslider+1 if (DoNotRecheckBefore <= os.time()) and ((WU.scheduler == os.time) or (os.date("%H:%M") == WU.push_fcst1) or (os.date("%H:%M") == WU.push_fcst2)) then Debug("orange", WU.translation[WU.language]["Exiting_loop_push"]); DoNotRecheckBefore = os.time()+60 sleepAndcheckslider = 20*updateEvery end end end Debug( "orange", "WU Weather - Original LUA Scripting by Jonny Larsson 2015"); Debug( "orange", "YAMS WU - Fork by Sébastien Jauquet 11/2015"); Debug( "orange", "Version: "..WU.version); if WU.station == "LOCID" then locationID = WU.LOCID elseif WU.station == "PWS" then locationID = WU.PWS end if WU.CreateVG then WU.createGlobalIfNotExists("Meteo_Day", "") WU.createGlobalIfNotExists("Meteo_Tomorrow", "") WU.createGlobalIfNotExists("Meteo_In_2_Days", "") end while true do WU.fetchWU() end
  17. OJC

    Heating Manager

    HEATING MANAGER v. 3.1.2 - 16/12//2017 Heating Manager est un programme permettant d'utiliser le Home Center 2 pour gérer avec une grande souplesse le chauffage d'une habitation, en permettant de franchir une étape supplémentaires dans la gestion de celui-ci. En effet, s'il est parfaitement capable de fonctionner en suivant une planification, Heating Manager permet de passer à l'étape suivante et d'exploiter pleinement les potentialités de la domotique en se passant totalement de planification et en gérant le chauffage sur une base événementielle exclusivement dynamique. Heating Manager, qui propose de réguler le chauffage sur un mode proportionnel avec prise en compte des déperditions (Ubat) ou sur un mode classique avec hystérésis, est compatible avec n'importe quel système de commande de chauffage, y compris des modules virtuels. Il peut fonctionner en tout ou partie en mode planification via l'utilisation des panneaux de chauffage natifs du Home Center 2, de modules dédiés ou de variables globales. En mode événementiel, il peut s'appuyer sur n'importe quelle propriété de n'importe quel module, virtuel ou non, ainsi que sur des variables globales. L'utilisation de boucles conditionnelles dans la configuration permet en outre de faire varier cette configuration en fonction de n'importe quelle condition. Ces développements doivent beaucoup aux échanges stimulants intervenus sur ce fil de discussion, qui m'ont amené à aller bien plus loin que ce qui était prévu au départ, à savoir simplement pouvoir utiliser les panneaux de chauffage avec les modules fils pilote proposés par Qubino... Que tous soient remerciés , ainsi que ceux qui relèvent des bugs et permettent d'améliorer le script. _ _ _ PRE-REQUIS Ce programme a été conçu et testé sur le Home Center 2 tournant avec le firmware v. 4.140. Il ne requiert aucun matériel particulier et peut s'adapter facilement à toutes les configurations. _ _ _ INSTALLATION 1. Pour une utilisation en tout ou partie en mode planification, il faut commencer par définir les plannings de chauffe souhaités. La première étape dans cette optique de fonctionnement est de définir un planning de chauffe dans lequel Heating Manager ira chercher la température de consigne à atteindre. Ce planning de chauffe peut être mis en place en utilisant les panneaux de chauffage fournis nativement par le Home Center 2. Attention cependant, un bug a été constaté, évoqué dans ce fil, entraînant l'absence de prise en compte du changement de température de consigne après minuit. Il peut également être mis en place en utilisant n'importe quel module virtuel ou bien celui, basique, fourni avec Heating Manager >>>> Heating_Provider.vfib Pour utiliser ce module virtuel, il faut adapter la configuration donnée en exemple à votre cas en modifiant, et en ajoutant le cas échéant, les étiquettes, chaque étiquette correspondant à une zone de chauffage. La définition du planning de chauffe pour chacun de ces zones intervient dans le main loop du module virtuel, dans la partie Configuration : HeatingManager:add(zone, day, time, temperature) zone correspond au nom d''une étiquette du module virtuel day est soit un ou plusieurs jours de la semaine (en anglais e.g. {"monday","friday"}), soit "weekday" (du lundi au vendredi), soit "weekend", soit "week" time est l''heure à laquelle la température de consigne devra être appliquée "hh:mm" temperature est la température de consigne devant être appliquée à compter de l''horaire défini juste avant Il est important que la construction du planning de chauffe soit faite de manière chronologique, le module virtuel ne faisant pas de tri chronologique, ce qui peut entraîner un comportement s'écartant de celui attendu. 2. Pour une utilisation en tout ou partie en mode événementiel, il faut importer un thermostat par pièce concernée >>>> Thermostat.vfib Ce module virtuel permet de définir la température de consigne (mode Confort et mode Economique) pour la pièce, de forcer l'un de ces deux modes ou de passer en mode manuel avec un minuteur permettant de retourner au mode automatique. Les ordres donnés par l'intermédiaire de ce module viruel l'emportent sur toute autre évènement défini dans la configuration de Heating Manager. Il faut juste mettre un module virtuel dans chaque pièce. Sa détection par Heating Manager se fait automatiquement. 3. [OPTIONNEL] Pour afficher de manière centralisée les températures de consigne en cours, il faut installer le module virtuel Heating Viewer >>>> Heating_Viewer.vfib Pour le bon fonctionnement de ce module, chaque pièce dont le chauffage est géré par Heating Manager doit avoir une étiquette, dont l'ID doit être le nom de cette pièce débarrassé de tous les accents, espaces et autres caractères exotiques. Ainsi, pour la pièce "Séjour Principal #1", l'ID de l'étiquette doit être "SejourPrincipal1". Les étiquettes inutilisées peuvent être supprimées, tout comme il peut être ajouté autant d'étiquettes que nécessaire. 4. Création d'une scène en mode Lua avec copier-coller du code >>>> Heating Manager - Scène.lua La configuration de Heating Manager est réalisée par l'exécution de neuf fonctions différentes à paramétrer dans la partie USER CONFIGURATION ZONE qui se trouve à partir de la ligne 100 du code. self:setConfiguration(checkConfig, oldLastTempUpdate, logInfo, pushWarnErrLog, pushTo, popupWarnErrLog, logMemory) checkConfig est un booléen dont la valeur par défaut est true, qui permet de définir si Heating Manager doit contrôler de manière approfondie la configuration (existence des pièces, des modules, des propriétés de modules, des variables globales, etc.) Une fois que votre configuration est rodée et fonctionne sans problème, vous pouvez passer ce paramètre à false. oldLastTempUpdate est un nombre dont la valeur par défaut est 180 et qui est le nombre de minutes depuis la dernière remontée de température d'une sonde intérieure au-delà duquel Heating Manager adressera un message d'alerte et arrêtera la chauffe. logInfo est un booléen dont la valeur par défaut est true et qui permet de définir si l'intégralité des messages doit s'afficher dans la fenêtre de debug, ou uniquement les plus importants (action, survenance d'un événement, changement de la température de consigne). pushWarnErrLog est un booléen dont la valeur par défaut est false et qui permet de définir si les messages d'alerte et d'erreur doivent faire l'objet d'une notification Push. pushTo est une table contenant l'ID des téléphones mobiles auxquels envoyer les notification Push si le paramètre précédent est à true. popupWarnErrLog est un booléen dont la valeur par défaut est false et qui permet de définir si les messages d'alerte et d'erreur doivent faire l'objet d'une notification dans le centre de notification du Home Center 2. logMemory est un booléen dont la valeur par défaut est true et qui permet d'afficher dans la fenêtre de debug, toutes les cinq minutes, la mémoire utilisée par Heating Manager. self:setProportionalMode(default_kP, auto_kP, default_kT, cycle, minCycle, defaultSetpoint) Cette fonction ne doit être utilisée que si vous souhaitez utiliser le mode de régulation proportionnel. default_kP est un nombre dont la valeur par défaut est 60 et qui est le coefficient proportionnel utilisé par Heating Manager dans le cadre de la régulation proportionnelle si aucun coefficient particulier n'est défini pour un radiateur donné. auto_kP est un booléen dont la valeur par défaut est true et qui permet de définir si Heating Manager doit adapter le coefficient proportionnel en fonction de l'expérience acquise lors des cycles de chauffe. default_kT est un nombre dont la valeur par défaut est 1 et qui est le coefficient de déperditions thermiques (Ubat) utilisé par Heating Manager dans le cadre de la régulation proportionnelle si aucun coefficient particulier n'est défini pour un radiateur donné. La valeur 1 correspond à une maison bien isolée. Pour un bâtiment mal isolé, ce coefficient peut être fixé à 3. cycle est un nombre dont la valeur par défaut est 15 et qui est la durée d'un cycle de chauffage en minutes, au sein duquel s'insère la période de chauffe calculée par Heating Manager. minCycle est un nombre dont la valeur par défaut est 1 et qui est la durée minimale en minutes d'une période de chauffe. defaultSetpoint est soit comfort, soit eco (sans guillemets) et permet de déterminer, uniquement pour un fonctionnement en mode événementiel, si la consigne à appliquer en dehors de tout événement est la température de confort définie dans le thermostat virtuel ou la température économique. La valeur par défaut est comfort. self:setHysteresisMode(hysteresis, cycle, defaultSetpoint) Cette fonction ne doit être utilisée que si vous souhaitez utiliser le mode de régulation par hystérésis. hysteresis est un nombre dont la valeur par défaut est 0 et qui est l'écart en degré entre la température courante et la température de consigne au-delà ou en-deça duquel le chauffage sera démarré. cycle est un nombre dont la valeur par défaut est 15 et qui est l'intervalle en minutes entre deux comparaisons de la température courante et de la température de consigne. defaultSetpoint est soit comfort, soit eco (sans guillemets) et permet de déterminer, uniquement pour un fonctionnement en mode événementiel, si la consigne à appliquer en dehors de tout événement est la température de confort définie dans le thermostat virtuel ou la température économique. La valeur par défaut est comfort. self:setEventDefaults(eCumulative, eSetpoint, eDuration, eStep, ePersistence) eCumulative est un booléen dont la valeur par défaut est true et qui permet de définir si les conditions d'un événement doivent toutes être réalisés pour que l'événement soit considéré comme survenu, ou si la réalisation d'une seule condition est suffisante. Il s'agit ici de définir la valeur par défaut qui sera utilisée à défaut de paramétrage contraire lors du paramétrage de chaque événement. eSetpoint est un nombre dont la valeur par défaut est 18 et qui permet de définir la température de consigne qui sera appliquée par défaut en cas de survenance d'un événement lorsqu'aucune température de consigne propre n'est définie lors du paramétrage de l'événement. eDuration est un nombre dont la valeur par défaut est 0 et qui permet de définir la durée en minutes devant s'écouler entre la survenance de l'événement et l'application de la température de consigne correspondante, permettant ainsi de prévoir une diminution ou une augmentation graduelle de la température de consigne. eStep est un nombre dont la valeur par défaut est 0.5 et qui permet de définir les étapes de diminution ou d'augmentation graduelle de la température de consigne. ePersistence est un nombre dont la valeur par défaut est 0 et qui permet de définir la durée par défaut pendant laquelle Heating Manager continuera à considérer qu'un événement est réalisé à partir de l'instant où les conditions de sa réalisation ne sont plus remplies. Si les conditions sont à nouveau remplies pendant le délai de persistence, Heating Manager agira comme si elles n'avaient jamais cessé d'être remplies. self:addHeater(idRoom, idHeater, idSonde, localkP, localkT) Cette fonction permet de déclarer les radiateurs qui seront gérés par Heating Manager. La fonction doit être paramétrée pour chaque radiateur. idRoom est l'ID de la pièce définie dans le Home Center 2 dans laquelle se trouve le module de commande du radiateur. idHeater désigne un module de commande d'un radiateur sous forme de table {ID du module, instruction pour mise en route, instruction pour arrêt, valeur à l'arrêt} : ID du module est l'ID d'un module, virtuel ou non, permettant de commander la mise en route ou l'arrêt du chauffage. instruction pour mise en route est soit la commande à transmettre s'il s'agit d'un module 'réel' ("turnOn" par exemple), soit le numéro d'ordre du bouton d'un module virtuel. instruction pour arrêt est soit la commande à transmettre s'il s'agit d'un module 'réel' ("turnOff" par exemple), soit le numéro d'ordre du bouton d'un module virtuel. valeur à l'arrêt est la valeur de la propriété value lorsque le radiateur est arrêté, et est utilisé pour éviter d'envoyer les commandes de mise en route et d'arrêt inutilement. idSonde désigne une sonde de température qui peut être définie spécifiquement pour un radiateur s'il n'est pas asservi à la sonde de température principale de la pièce définie dans le Home Center 2. Il peut s'agir d'une sonde de température proprement dite ou d'un module virtuel et sera dans tous les cas sous la forme {ID du module, nom de la propriété contenant la température}. Il peut également s'agir du nom d'une variable globale dans laquelle est stockée la température. localkP permet de définir un coefficient proportionnel fixe qui sera utilisé pour calculer la commande de chauffe de ce radiateur. localkT permet de définir un coefficient de déperditions thermiques qui sera utilisé pour calculer la commande de chauffe de ce radiateur. self:addEvent(idRoom, idEvent, conditions, cumulative, setpoint, duration, persistence) Cette fonction permet de définir les événements qui entraîneront une modification de la température de consigne (ouverture d'une fenêtre, absence temporaire ou prolongée, lumière allumée ou éteinte...). idRoom est l'ID de la pièce concernée par l'événement, ou une table contenant les IDs de plusieurs pièces concernées par l'événement. idEvent est le nom de l'événement, qui sera affiché dans la fenêtre de debug lors de sa survenance. conditions est une table contenant les différentes conditions devant être réalisées, ensemble ou séparément, pour que l'événement soit considéré comme survenu et la température de consigne modifiée en conséquence. Cette table contient elle-même une table par condition (il y a donc forcément une double accolade au début et à la fin), sous la forme {nom de variable globale, opérateur ("==", "~=", ">=", "<=", ">", "<"), valeur à vérifier, durée en minutes devant s'être écoulée depuis que le résultat de la comparaison est vrai} ou {ID d'un module, nom de la propriété d'un module, opérateur ("==", "~=", ">=", "<=", ">", "<"), valeur à vérifier, durée en minutes devant s'être écoulée depuis que le résultat de la comparaison est vrai}. cumulative est un booléen permet de définir, pour cet événement particulier, si sa survenance implique la réalisation de toutes les conditions ou si une seule est suffisante. setpoint permet de définir la température de consigne devant être appliquée lorsque l'événement survient. Dans le cadre du mode de fonctionnement événementiel, vous pouvez utiliser les variables comfort et eco qui font références aux températures définies pour la pièce avec le module virtuel Thermostat. duration est la durée en minutes devant s'écouler entre la survenance de l'événement et l'application de la température de consigne correspondante, permettant ainsi de prévoir une diminution ou une augmentation graduelle de la température de consigne. persistence est un nombre qui permet de définir la durée pendant laquelle Heating Manager continuera à considérer que l'événement est réalisé à partir de l'instant où les conditions de sa réalisation ne sont plus remplies. Si les conditions sont à nouveau remplies pendant le délai de persistence, Heating Manager agira comme si elles n'avaient jamais cessé d'être remplies. Dans le cadre de la configuration, cette fonction peut s'insérer dans une boucle conditionnelle permettant de ne laisser l'événement se réaliser que sous des conditions précises, par exemple d'horaires. self:addGlobalEvent(idEvent, conditions, cumulative, setpoint, duration, persistence) Cette fonction permet de définir un événement s'appliquant à toutes les pièces dont le chauffage est géré par Heating Manager, et se configure exactement de la même manière que la précédente, le paramètre idRoom en moins. Attention : le fait que l'événement soit global ne signifie pas qu'il l'emporte sur les événements spécifiques d'une pièce. Heating Manager contrôle les événements les uns à la suite des autres pour chaque pièce, dans l'ordre de leur configuration. Dès que les conditions d'un événement sont remplies, le programme cesse la boucle et n'analyse pas les autres événements déclarés. self:setIndoorSonde(idRoom, idSonde) Cette fonction permet de définir la sonde de température d'une pièce si vous ne souhaitez pas utiliser la sonde de température principale définie dans le Home Center 2. idRoom est l'ID de la pièce concernée. idSonde désigne une sonde de température proprement dite ou un module virtuel et sera dans tous les cas sous la forme {ID du module, nom de la propriété contenant la température}. Il peut également s'agir du nom d'une variable globale dans laquelle est stockée la température. self:setSetpoint(idRoom, idSetpoint) Cette fonction permet de définir, pour une pièce donnée, la source de la température de consigne qui devra être appliquée. L'utilisation de cette fonction n'est requise que dans le cas de l'utilisation du mode planification, et est inutile lorsque le chauffage de la pièce est effectué selon le mode événementiel. idRoom est l'ID de la pièce concernée. idSetpoint désigne la source de la température de consigne et peut être : l'ID d'un panneau de chauffage natif du Home Center 2. une table sous la forme {ID du module, propriété du module contenant la température de consigne} s'il s'agit d'un module, virtuel ou non. le nom d'une variable globale qui contiendra la température de consigne. self:setOutdoorSonde(idSonde) Cette fonction permet définir une sonde de température extérieure. Elle n'est utilise que dans le cas de la régulation proportionnelle qui tient compte de la température extérieure, et est inutile pour une régulation à base d'hystérésis. idSonde désigne une sonde de température proprement dite ou un module virtuel et sera dans tous les cas sous la forme {ID du module, nom de la propriété contenant la température}. Lorsqu'aucune sonde de température extérieure n'est définie et que le mode de régulation proportionnel est utilisé, Heating Manager utilise la température fournie par le plugin Météo. 5. Mise à jour depuis une version précédente Cette nouvelle version apporte des modifications en profondeur du programme et de la manière de le configurer. Il n'est donc pas possible de faire simplement un copier-coller de la configuration d'une version précédente à la 3.0, qui était éclatée entre la scène et un module virtuel, mais il est nécessaire de reprendre la configuration depuis le départ. Depuis la version 3.0, il est impératif de modifier les fonctions self:addEvent pour ajouter dans les conditions le paramètre operator : "==", "~=", ">=", "<=", ">" ou "<". Si le contrôle de configuration est activé, un message d'erreur s'affichera dans la fenêtre de debug sans faire planter le programme. L'ajout du paramètre ePersistence dans la fonction self:setConfiguration et persistent dans les fonctions self:addEvent n'est pas indispensable puisqu'il s'agit du dernier paramètre de ces fonctions. A défaut de les ajouter, c'est la valeur par défaut (0) qui s'appliquera. _ _ _ ROADMAP [VIDE] _ _ _ ICONES
  18. Bonjour, Il existe déjà plusieurs Virtual Devices relatifs à l'Eco-Devices sur le forum mais n'ayant pas trouvé mon bonheur, j'ai entièrement écrit un module de zéro en fonction de mes besoins et en espérant qu'il puisse également servir à d'autres. Que fait ce Virtual Device ? 1) Suivi en temps réel des statistiques d'un compteur téléinfo (T1 ou T2) HC/HP 2) Affichage temps réel d'une icône de type "jauge" présentant le tarif actuel (HC/HP) ainsi que la valeur de consommation actuelle 3) Affichage temps des index en kWatts au 1000ième, index en cours (HC ou HP) toujours en premier 4) Affichage temps réel d'un compteur de consommation journalier en Watts pour les HP et les HC 5) Affichage temps réel du coà»t de consommation journalier 6) Génération d'un rapport Email de consommation journalière 7) Fonction de remise à zéro manuelle des compteurs journaliers 8) Gestion de l'authentification utilisateur Eco-Devices Evolutions prévues : 1) Ajout d'un compteur de cumul mensuel 2) Estimation de prochaine facture et publication d'index "Releve Confiance" chez EDF (fera certainement l'objet d'un second module "EDF & Moi") Voici un aperçu des vues graphiques du Virtual Device : La liste des icones de jauges : Deux méthodes sont proposées pour la récupération des statistiques de l'Eco-Devices : L'existence de ces 2 méthodes est liée à un bug connu de la HC2 lors de l'utilisation de requêtes HTTP dans la mainLoop d'un Virtual Device qui bloque au bout d'un certain temps. Le moyen de contourner cela est l'utilisation d'un bouton déclenché depuis la mainLoop qui a comme inconvénient de modifier l'icône pour la durée du traitement ce qui personnellement ne me convient pas. - Méthode 1 (recommandée) : C'est la méthode que j'ai choisi car elle se base sur une scène afin de rafraichir les données et évite ainsi le changement d'icône indésirable durant la récupération des données. -> Pour utiliser cette méthode, vous devez en plus créer et configurer la scène fournie puis dans la MainLoop, positionner la variable useSceneToRefresh à true - Méthode 2 (par défaut ) : C'est la méthode configurée par défaut qui évite l'utilisation d'une scène en parallèle mais avec l'inconvénient de l'icône qui sera modifiée à chaque récupération des données. J'ai toutefois crée une icône dédiée à configurer sur ce bouton : afin que ce ne soit pas trop moche. -> Pour utiliser cette méthode, vous devez simplement positionner la variable useSceneToRefresh à false dans la MainLoop Comment l'utiliser ? 1) Importer la dernière version du Virtual Device : Eco_Devices_Live_Day_Reporter_V0.1.vfib 2) Renseignez l'adresse IP ainsi que le port (80 par défaut) de votre Eco-Devices 3) Importer la série d'icônes de jauges fournies en respectant l'ogre dans lequel elles sont fournies, c'est très important, puis notez l'Id correspondant à la première 4) Dans la mainLoop, renseignez les valeurs des variables teleInfoNB, baseIconId, userIdsToNotify, useSceneToRefresh et si besoin reportTime 5) Si vous utilisez la Méthode 1 (useSceneToRefresh = true) vous devez créer la scène Eco-Devices Refresh (voir ci-dessous) 6) Dans le code du bouton "Raraîchir" pensez à saisir vos in formations d'authentification si vous l'avez activée sur l'Eco-Devices 7) Pas besoin de créer de variables globales, elles sont automatiquement crées au premier démarrage du Virtual Device 8) Sauvegarder la scène et tout devrait bien fonctionner Pour ceux qui utilisent la Méthode 1 : Voici le code de la scènes Eco-Devices Refresh Il est IMPORTANT de bien renseigner le deviceId correspondant à l'Id de votre Virtual device importé ci-dessus. Si vous avez activé l'authentification sur l'Eco-Devices, vous devez ici saisir vos informations d'authentification encodées en base64. Si vous ne l'avez pas déjà fait, il suffit d'aller sur https://www.base64encode.org, d'encoder en UTF8 la chaine correspondante à "<login>:<password>" et de récupérer le résultat. Par exemple "admin:password" donnera "YWRtaW46cGFzc3dvcmQ=" saut de --[[ %% autostart %% properties %% globals --]] -- Récurrence de rafraichissement des stats en secondes local checkEvery = 3 -- Id du Virtual Device local deviceId = 228 -- Authentification ("" si pas d'authentification sinon chaine "<login>:<password>" en base64 local base64BasicAuthentication = "" local sourceTrigger = fibaro:getSourceTrigger() local ecoDevicesIP = tostring(fibaro:get(deviceId,"IPAddress")) local ecoDevicesStats = nil --- Usefull Functions --- function debug(text, color) color = color or "white" fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, text, "span")) end function setDevicePropertyValue(id, label, value) fibaro:call(id, "setProperty", "ui."..label..".value", value) end function getDevicePropertyValue(vDeviceid, propertyName) return fibaro:getValue(vDeviceid, "ui."..propertyName..".value") end function refreshEcoDevicesStats() debug("Rafraichissement des statistiques de l'EcoDevices...") ecoDevicesStats = nil local http = net.HTTPClient() http:request("http://"..ecoDevicesIP.."/api/xdevices.json?cmd=10", { options = { method = 'GET', headers = {["Authorization"] = 'BASIC '..base64BasicAuthentication}, }, success = function(response) ecoDevicesStats = response.data refreshEcoDevicesStatsAsync() end, error = function(err) debug("Error: " ..err, "red") fibaro:sleep(1000) refreshEcoDevicesStats() end }) end function refreshEcoDevicesStatsAsync() fibaro:setGlobal("ecoDevicesStats", ecoDevicesStats) debug("OK ! "..ecoDevicesStats, "green") if (sourceTrigger["type"] == "autostart") then setTimeout(refreshEcoDevicesStats, checkEvery*1000) end end refreshEcoDevicesStats() lignesaut de ligne Enfin, voici le code de la MainLoop : saut de ligne -------------------------------------------------------- -- Eco-Devices Live & Day Reporter v0.1 -- -------------------------------------------------------- -- Auteur : Brice Cassagnabère -- -------------------------------------------------------- -- Changelog : -- -- -- -- v0.1 : Version initiale -- -------------------------------------------------------- -- Plus d'infos : http://is.gd/tMgWdy -- -------------------------------------------------------- -- Renseignez ici le numéro de téléinfo à prendre en compte, T1 ou T2 teleInfoNB = "T1" -- Renseignez ici le numéro de la première icône de jauge (HC_0.png) baseIconId = 1047 -- Renseignez ici les id Utilistaurs à qui transmettre le rapport userIdsToNotify = {2, 154} -- Si vous utilisez la scène associée pour la MAJ, passer cette variable à true useSceneToRefresh = false -- Heure à laquelle vous souhaitez générer le rapport journalier reportTime = "23:59" -- Tarifs des kWh 2015 hcCost = 0.0623 hpCost = 0.1019 deviceId = fibaro:getSelfId() --- Usefull Functions --- function debug(text, color) color = color or "white" fibaro:debug(string.format('<%s style="color:%s;">%s</%s>', "span", color, text, "span")) end function setDevicePropertyValue(id, label, value) fibaro:call(id, "setProperty", "ui."..label..".value", value) end function getDevicePropertyValue(vDeviceid, propertyName) return fibaro:getValue(vDeviceid, "ui."..propertyName..".value") end function createGlobalIfNotExists(varName, defaultValue) if fibaro:getGlobal(varName) == "" then debug("Création de la variable "..varName.." avec comme valeur par défaut "..defaultValue) newVar = {} newVar.name = varName newVar.value = defaultValue HC2 = Net.FHttp("127.0.0.1", 11111) HC2:POST("/api/globalVariables", json.encode(newVar)) end end function refreshEcoDevicesStats() if not useSceneToRefresh then fibaro:call(deviceId, "pressButton", 5) fibaro:sleep(1000) end jsonStats = fibaro:getGlobalValue("ecoDevicesStats") if not string.find(jsonStats, '{"product":"Eco-') then debug("An error occured -> "..jsonStats, "red") debug("No stats found, please check documentation and configuration", "orange") return false end ecoDevicesStats = json.decode(jsonStats) tarif = string.format("%.2s", ecoDevicesStats[teleInfoNB.."_PTEC"]) conso = ecoDevicesStats[teleInfoNB.."_PAPP"] hcIndex = ecoDevicesStats[teleInfoNB.."_HCHC"] hpIndex = ecoDevicesStats[teleInfoNB.."_HCHP"] hcIndexStr = "HC : "..string.format("%.3f", hcIndex/1000) hpIndexStr = "HP : "..string.format("%.3f", hpIndex/1000) fibaro:log("Tarif : "..tarif.." - Conso : "..conso.." VA".." - "..hcIndexStr.." - "..hpIndexStr) iconId = baseIconId if tarif == "HP" then activeIndex = hpIndexStr inactiveIndex = hcIndexStr iconId = iconId + 9 else activeIndex = hcIndexStr inactiveIndex = hpIndexStr end -- Mise à jour des Labels setDevicePropertyValue(deviceId, "labelTarif", tarif) setDevicePropertyValue(deviceId, "labelConso", conso.." VA") setDevicePropertyValue(deviceId, "labelActiveIndex", activeIndex.." kW") setDevicePropertyValue(deviceId, "labelInactiveIndex", inactiveIndex.." kW") -- Mise à jour de l'icône conso = ecoDevicesStats[teleInfoNB.."_PAPP"] if conso >= 1000 then if conso < 9000 then iconId = iconId + tonumber(string.format("%.1s", conso)) else iconId = iconId + 8 end end fibaro:call(deviceId, "setProperty", "currentIcon", iconId) return true end function refreshDayStats() day_HC_Conso = hcIndex - day_HC_Index day_HP_Conso = hpIndex - day_HP_Index day_HC_ConsoStr = "HC : "..day_HC_Conso.." W" day_HP_ConsoStr = "HP : "..day_HP_Conso.." W" if tarif == "HP" then activeDayIndex = day_HP_ConsoStr inactiveDayIndex = day_HC_ConsoStr else activeDayIndex = day_HC_ConsoStr inactiveDayIndex = day_HP_ConsoStr end -- Calcul du coà»t en € dayCost = ((day_HP_Conso * hpCost) + (day_HC_Conso * hcCost)) / 1000 dayCost = dayCost + (dayCost * 0.2) dayCostStr = "Coà»t : "..string.format("%.2f", dayCost).." €" setDevicePropertyValue(deviceId, "labelActiveDayIndex", activeDayIndex) setDevicePropertyValue(deviceId, "labelInactiveDayIndex", inactiveDayIndex) setDevicePropertyValue(deviceId, "labelToday", dayCostStr) end function reportDayStats() message = "HC : "..day_HC_Conso.." Watts\nHP : "..day_HP_Conso.." Watts\n"..dayCostStr for k,v in pairs(userIdsToNotify) do fibaro:call(v, "sendEmail", "Consommation électrique du "..os.date("%d/%m/%Y"), message) end end function checkCptRaz() -- Tous les jours à minuit, je stockera valeur de l'index en cours if tostring(os.date("%H:%M")) == reportTime or day_HC_Index == 0 or ecoDevicesStats.raz then debug("Initialisation du compteur journalier", "green") if tostring(os.date("%H:%M")) == reportTime then reportDayStats() end day_HC_Index = hcIndex day_HP_Index = hpIndex fibaro:setGlobal("day_HC_Index", day_HC_Index) fibaro:setGlobal("day_HP_Index", day_HP_Index) while tostring(os.date("%H:%M")) == reportTime do fibaro:sleep(1000) end end end -- Création automatique des variable globales createGlobalIfNotExists("ecoDevicesStats", "0") createGlobalIfNotExists("day_HC_Index", "0") createGlobalIfNotExists("day_HP_Index", "0") -- Je rafraichis les stats une première fois pour initialiser mes variables locales if not refreshEcoDevicesStats() then return end day_HC_Index = tonumber(fibaro:getGlobalValue("day_HC_Index")) day_HP_Index = tonumber(fibaro:getGlobalValue("day_HP_Index")) -- Boucle principale while true do -- ## Pensez à bien choisir votre méthode de mise à jour des stats -- ## Méthode 1 (useSceneToRefresh = true) ## : Vous utilisez la Scene de Mise à jour des stats qui évite -- le changement d'icône indésirable -- ## Méthode 2 (useSceneToRefresh = false) ## : Pas besoin de créer la scene mais entrainera un court changement -- de l'icône durant le reresh contrairement à la précédente if not refreshEcoDevicesStats() then return end refreshDayStats() checkCptRaz() fibaro:sleep(2000) end saut de ligne Historique des versions : - V0.1 du 11/05/2015 : Eco_Devices_Live_Day_Reporter_V0.1.vfib
  19. pinou

    Zibasegateway Pour Hc2

    Après le calendrier Google, je me suis attaqué maintenant à ma Zibase. En effet, j'ai commencé la domotique il y a quelques temps de ça, avec une Zibase. Depuis elle ne m'a jamais quitté. Même si aujourd'hui j'ai migré (pratiquement) tous mes modules zwave sous la Home center, j'utilise toujours ma Zibase pour les devices Oregon et EnOcean essentiellement. J'ai vu passer différentes solutions permettant de récupérer les infos/valeurs de ces modules au sein de la HC2. Ceci dit, rien de satisfaisant pour moi, car les solutions sur lesquelles je suis tombé font essentiellement du pooling vers la Zibase, or j'ai besoin de temps réel. Pas pour les relevés des sondes Oregon mais pour les détecteur d'ouverture EnOcean. Je me suis donc amusé à trouver une autre solution répondant à mon besoin. Le principe Le principe est assez simple : plutôt que d'aller voir de façon périodique l'état des devices de la Zibase, je me suis dit qu'il suffit en fait "d'écouter" ce que broadcast la Zibase et de chopper dans ce flux ce qui m'interesse. Il suffit alors de passer par l'api de Fibaro pour mettre à jour les variables correspondantes dans ma HC2. Dans le détail... Il s'agit d'un script PHP que j'ai hébergé sur mon syno (mais un RPI ou toute autre machine pouvant faire tourner du PHP 24h/24 suffit). Pas besoin de configurer un serveur web puisque le script PHP tourne en mode CLI (lancé automatiquement au démarrage du syno dans mon cas). Lors du lancement du script, ce dernier va s'abonner aux messages de la Zibase. Il va donc recevoir un flux de ce type a chaque fois qu'un device remonte une info vers la Zibase : Received radio ID (<rf>433Mhz Oregon</rf> Noise=<noise>2420</noise> Level=<lev>3.4</lev>/5 <dev>Temp-Hygro</dev> Ch=<ch>2</ch> T=<tem>+18.4</tem>C (+65.1F) Humidity=<hum>45</hum>% Batt=<bat>Ok</bat>): <id>OS439218434</id> On décode alors ces données pour pouvoir mettre à jour la ou les variables associées au niveau de la HC2. Un des points délicats concerne la configuration du fichier permettant de mettre en place ce décodage. Le fichier de configuration des messages de la Zibase Ce fichier est donc un des éléments essentiels de cette solution. Il s'agit d'un fichier json (pour la facilité de lecture et construction). Il y a 2 parties dans ce fichier : Un premier élément de configuration permettant de définir les différents protocoles radio qui seront reconnus par le script. On vient dire ici, par protocol (Oregon, EnOcean, ...) et par type de device (Détecteurs, sondes température, etc.) quelles sont les données qu'il faut récupérer dans le flux correspondant. Un second élément permet de définir pour chaque device reconnu (par son ID Radio) quelles sont les variables qui seront mise a jour avec quelles données. On indiquera également si cette mise a jour doit se faire à chaque remontée d'info (exemple du détecteur), ou seulement si la donnée à été modifiée depuis la dernière mise à jour (afin de ne pas saturer la HC2 de requêtes inutiles). Autant vous prévenir tout de suite, cette configuration est chiante à souhait à mettre en place, mais bon j'ai pas trouvé plus simple et/ou plus automatisé. Ceci dit, une fois au point, on y touche plus ! Le script PHP Ce dernier vient avec un script contenant les variables de configuration dont les valeurs sont à modifier en fonction de votre installation. C'est assez explicite, je ne vais pas m'attarder dessus. Côté Home center Alors ici, il y a quelques petites choses à faire. Le plus gros problème est que je passe par l'api HTTP pour mettre à jour les variables. Or par ce biais, même si la mise à jour fonctionne, elle ne permet pas de déclencher les scènes et autres scripts qui seraient basés sur ces dernières (limitation de Fibaro ... va comprendre pourquoi ...). Du coup, j'ai implémenté la solution proposée par Jojo dans un autre post qui consiste à passer par l'intermédiaire d'un bouton de module virtuel qui vient mettre à jour la variable avec sa valeur. Bon ne pouvant pas m'amuser à créer un bouton pour chaque valeur discrète possible et imaginable, le script PHP va mettre à jour 2 variables permettant de stocker le nom de la variable finale à mettre à jour et sa valeur(1). On va ensuite déclencher le module virtuel (2) qui va récupérer ces données (3) et mettre à jour à son tour la variable désirée avec la bonne valeur (4). Et voilà , les scènes basées sur cette variable fonctionnent du coup (5) ! Je ne sais pas si vous me suivez toujours dans mon raisonnement (un peu tordu), j'essaye de vous faire un p'tit dessin pour illustrer la chose : script PHP ---------+----(1)--->zibaze_variable = "anemometre" <-. +----(1)--->zibaze_value = "3.2" <-----------+ | (3) `----(2)--->VModuleID = 99, PushButton n°1 --+ | (4) | v anemometre = "3.2" | (5) | v scene "FermetureStore" start Installation Du coup l'installation de tout ce bordel s'effectue en plusieurs étapes : A/ Pour la partie PHP il faut 1) Poser les différents fichiers dans un espace sur votre serveur et connectez vous dessus (ssh, telnet, ...) 2) Modifiez le fichier zibaseGateway_config.php et zibaseGateway.php afin d'initialiser les variables avec les bonnes valeurs (partout ou il y a des XXXX vous devez configurer en fonction de votre installation) 3) Assurez vous que la variable verbose soit positionnée à LogType::CONSOLE dans un premier temps (une fois que tout sera au point vous la changerez comme bon vous semble) 4) Lancez le script à la main php zibaseGateway.php 5) Si tout va bien, les messages reçus de la Zibase devraient s'afficher à l'écran. A vous de jouer maintenant pour mettre à jour le fichier zibaseMessages.json en conséquence. 6) Arrêtez les script (CTRL+c) et relancez le pour vérifier que la configuration est bien prise en compte correctement. B/ On passe maintenant au niveau de la Home Center 7) Déclarez les différentes variables que vous avez déclaré au point 5) 8) Déclarez les 2 variables Zibase_variable et Zibase_value (cf. fichier de configuration zibaseGateway_config.php) 9) Importez le module virtuel C/ Le test final 10) Relancez le script et vérifiez que les variables de votre HC soient bien mises à jour. Si ce n'est pas le cas, reprenez depuis le point 2) : soit vous n'avez pas initialisé vos variables correctement, soit le fichier json ne reflète pas la réalité... D/ Mode automatique Etant nouveau dans le monde des syno, j'avoue avoir un poil galéré pour que mon script php se lance automatiquement au démarrage du NAS. En gros il faut transformer ce script en deamon. 11) Tout d'abord j'ai modifié la config PHP au niveau de l'interface d'admin du NAS : Panneau de configuration > Services web > Paramètres PHP : cliquez sur personnaliser PHP openbase_dir et rajouter les chemins vers vos repertoires d'installation. Sans cette config vous risquez d'avoir des warnings/erreurs PHP lors de l'exécution. 12) J'ai créé un script SH qui permet de "deamonsier" le script PHP. Il suffit de faire un lien de ce script dans le bon répertoire : ln -s S99zibase.sh /usr/syno/etc/rc.d/S99zibase.sh Et voilà , le script sera lancé ou arrêté automatiquement au startup/shutdown de votre NAS. Bien entendu, ces différents points sont à adapter en fonction de votre config... Maintenant que tout fonctionne, il ne vous reste plus qu'a redémarrer votre NAS et vérifier que les variables HC2 soient bien mises à jour. A vous de créer des modules virtuels pour afficher l'état de vos variables dans vos interfaces... Remerciements Un gros merci à Cmoi20, auteur du projet ZiHome dont je me suis très très fortement inspiré pour mettre en place le script PHP jojo pour sa solution de mise à jour d'une variable via un module virtuel Bejamin Garel pour son sdk PHP pour la Zibase Téléchargements package PHP : zibaseGateway.zip Module virtuel : Zibase.vfib Image pour module virtuel :
  20. Sur une idée originale de razowski et dans la continuité du sujet de Steven ici (http://www.domotique-fibaro.fr/index.php/topic/1303-double-clique-pour-confirmer/) voici un module virtuel permettant de déclencher une action sur validation d'un code PIN au préalable renseigné dans le code du Main Loop. Version 1.0.1 L'action peut-être le déclenchement d'une scène, l'allumage ou l’extinction d'un périphérique ou bien encore l’exécution d'un script LUA afin de laisser cours à votre imagination . Le clavier est simple avec juste 12 touches: 10 boutons de 0 à 9, un bouton "clear" et un "Enter". La validation est automatique lorsqu' un code à 4 chiffre est renseigné, sinon il faut utiliser la touche correspondant à "Enter". J' ai fait ça vite fait entre midi et deux et juste pour poser les bases, je ferais évoluer la chose si le code suscite de l’intérêt. Pour la mise en place il faut commencer par créer un variable globale PINCode000, puis d'importer le fichier vfib en téléchargement sur cette page. Ensuite vous devez modifier le code dans le MainLoop pour l'adapter à vos besoins. Explications succinctes: - ["1010"] : correspond au code qui est formaté sur 4 chiffres (de 1 à 4 chiffres). - caption : une légende pour l'action associée au code - task.object : Peut prendre les valeurs suivantes: scene, device, lua, virtual, globalv - task.id : Identifiant de la scène, du device, de la varible ou du vd utilisé [option] - task.value: pour une scène [start, stop], un périphérique [on, off, dim], lua [function], valeur de la variable globale etc. - task targetId: l'id d'un bouton ou d'un slider dans le cas d'un vd. Les options de l'objet task: -- object: device - actions: [on, off, dim] - id: [num] - value: [0-100] (option) -- object: scene - actions: [start, stop] - id: [num] -- object: virtual - actions: [pressButton, setSlider] - id: [num] - value: [0-100] - targetId: [num] -- object: lua - value: [lua function] (ex: function() -- lua code here end) -- object: globalv - id: [name] - value: [xxx] cf. code extrait du Main Loop: local codeTable = { ["1010"] = { caption = "Disarm perimeter with scene", task = { object = "scene", id = 999, action = "start" } }, ["2020"] = { caption = "lua sample", task = { object = "lua", value = (function() fibaro:debug("Custom lua action!"); end) } }, ["3030"] = { caption = "turn on device", task = { object = "device", id = 999, action = "off" } }, ["4040"] = { caption = "dim device", task = { object = "device", id = 999, action = "dim", value = 25 } }, ["5050"] = { caption = "set global variable 'myvar' to 8989", task = { object = "globalv", id = "myvar", value = 8989 } }, ["6060"] = { caption = "set slider id#8 to 75 in virtual device #999", task = { object = "virtual", id = 999, targetId = 8, action = "setSlider", value = 75 } } }; Modifications: Version 1.0.1 - 08/07/2014 1. Renommage du module en "Security Virtual Keybaord" (ça sert à rien mais je préfère) 2. Ajout du support pour: scène, vd, variable globale VirtualDevice-Security-Keyboard-V1.0.1.vfib
  21. Krikroff

    Hc2 Waze Calculator

    Après longue absence voici un petit script permettant d’utiliser sur notre HC2 le service de trafic et de navigation communautaire WAZE (https://www.waze.com/fr/) Le principe du script est très simple : 1 scène pour interroger l’ API Waze pour tous les trajets parametrés et autant de vd qui seront mis à jour par la dite scène.] 1 - Installation Importer le vd HC2_Waze_Calculator.vfib sur le HC2, 1x pour un trajet, 2x pour deux etc... Créer la scène HC2 Waze Calculator cf. fichier HC2 Waze Calculator Scene.txt puis passer au paramètrage 2 - Paramétrage Configurer l'object params: nom, id du vd cible, polling, latitude, longiture etc... pour tous les trajets. Pour trouver les coordonnées GPS, latitude et longitude il existe les services : www.coordonnees-gps.fr, www.torop.net/coordonnees-gps.php, www.gpsfrance.net etc. local params = { { name = "Trajet 1", virtualDeviceId = 1449, from = { name = "Palais de l'Élysée", x = 2.3167538999999806, -- longitude y = 48.8704156 -- latitude }, to = { name = "Théâtre Guignol", x = 2.311747670173645, -- longitude y = 48.86977710077997 -- latitude }, pollingMs = 60*1000 }, { name = "Trajet 2", virtualDeviceId = 1452, from = { name = "Palais de l'Élysée", x = 2.3167538999999806, -- longitude y = 48.8704156 -- latitude }, to = { name = "Théâtre Guignol", x = 2.311747670173645, -- longitude y = 48.86977710077997 -- latitude }, pollingMs = 5*60*1000 } } 4 - Icône Merci à Moicphil de m’avoir suggéré la chose et aussi pour son icône tip-top Fichier du vd: HC2_Waze_Calculator.vfib Fichier de la scène: HC2 Waze Calculator Scene.txt
  22. ZerobrainStudio pour ecrire et tester vos scripts lua directement sur votre PC Merci a steven et Fred le ouf Dans un premier temps il faut telecharger ZerobrainStudio. Choisir la version qui correspond a votre systéme d'explotation pour moi ce sera Windows 32bit (exe installer) https://studio.zerobrane.com/download?not-this-time Il suffit d'installer le programme comme vous en avez l'habitude et bien regarder ou il sera installer Ensuite il va falloir ajouter le fichier que @Steven a partager sur le forum lualibs1.01.zip By Steven Ajout : le fibaro:sleep(<millisecondes>) fibaro:countScene() retournera toujours 1. Manque encore une astuce pour simuler le fibaro:getSourceTrigger() Il ne vous reste plus qu'a décompresser ce fichier dans le répertoire C:.......\ZeroBraneStudio\lualibs Utilistation : require("FibaroSceneAPI") hc2_user = "admin" hc2_pwd = "admin" hc2_ip = "192.168.x.x" -- Inséré votre code en dessous de cette ligne ----------------- Et pour ceux qui n'aime pas l'anglais : Edit -> Preferences -> Settings: System --[[-- Use this file to specify **System** preferences. Review [examples](+C:\PRGMS\ZeroBraneStudio\cfg\user-sample.lua) or check [online documentation](http://studio.zerobrane.com/documentation.html) for details. --]]-- language = "fr" Et redémarrer l'application Pour ceux qui souhaite les même couleurs que dans leur HC2, il faut aller dans le menu : Edit -> Preferences -> Settings: User et copier le code ci-dessous puis redémarrer. --[[-- Use this file to specify **User** preferences. Review [examples](+C:\PRGMS\ZeroBraneStudio\cfg\user-sample.lua) or check [online documentation](http://studio.zerobrane.com/documentation.html) for details. --]]-- styles = loadfile('cfg/tomorrow.lua')('TomorrowNight') stylesoutshell = styles -- apply the same scheme to Output/Console windows styles.auxwindow = styles.text -- apply text colors to auxiliary windows styles.calltip = styles.text -- apply text colors to tooltips local colors = { orange = {255,158,89}, braun = {217,191,140}, darkgray = {38,38,38}, blue = {89,158,255}, green = {188,210,121}, red = {179,94,77}, white = {255,255,255}, gray = {102,102,102} } styles.comment = {fg = colors.gray} styles.operator = {fg = colors.white} styles.number = {fg = colors.red} styles.stringtxt = {fg = colors.green} styles.keywords0 = {fg = colors.blue} styles.text = {fg = colors.braun, bg = colors.darkgray} styles.keywords3 = {fg = colors.orange} styles.keywords4 = {fg = colors.orange} styles.keywords5 = {fg = colors.orange} styles.keywords6 = {fg = colors.orange} styles.keywords7 = {fg = colors.orange} Encore une amélioration : Copier le fichier ci-joint "fibaro.lua" dans le sous-répertoire /api/lua/ fibaro.lua puis dans le menu : Edit -> Preferences -> Settings: System ajouter cette ligne : api = {luadeb = {'fibaro'}} Vous allez avoir l'auto-complétion des commandes fibaro ainsi que leur description. Astuce. Pour pouvoir tester les triggers, voici le code à utiliser __fibaroSceneSourceTrigger = {type="global", name="Pushbullet"} -- __fibaroSceneSourceTrigger = {type="global", name="Pushbullet"} -- __fibaroSceneSourceTrigger = {type="property", deviceID=6, propertyName="value"} -- __fibaroSceneSourceTrigger = {type="autostart"} -- __fibaroSceneSourceTrigger = {type="other"} print(fibaro.getSourceTrigger().type) -- global print(fibaro.getSourceTrigger().name) -- Pushbullet __fibaroSceneSourceTrigger = {type="autostart"} print(fibaro.getSourceTrigger().type) -- autostart Il suffit donc de modifier la variable __fibaroSceneSourceTrigger en utilisant un des exemple fourni. il est aussi possible de débuguer ligne à ligne, et même de modifier dynamiquement la valeur d'une variable directement en cours d'exécution. Allez, je me lance pour mon 1er tuto Ouvrir Zerobranstudio et afficher les fenêtres suivantes si ce n'est pas encore déjà fait insérer le code suivant dans une nouvelle fenêtre vide de Zerobranstudio (on va réviser les multiplications ) local boucle = true local i = 1 local j = 1 while boucle == true do i = i + 1 j = j + 2 print(i.." x "..j.." = "..i * j) end Pour activer le suivi dynamique des variables, il suffit de sélectionner le nom de la variable que l'on veut suivre, puis de faire clic droit dessus pour faire apparaitre un menu contextuel. Il faut ensuite sélectionner l'option Add watch expression comme dans l'image ci dessous. Dans notre cas, il faut le faire pour les 2 variables i & j. Pour passer en mode debug, appuyer 1 fois sur la touche F5, la fenêtre doit ressembler à ça. Le curseur vert est positionné sur la première instruction, et la fenêtre Watch affiche les valeurs de i et j (à nil pour le moment ce qui est logique) Appuyer maintenant plusieurs fois sur la touche F10 pour exécuter le programme pas à pas, jusqu'à afficher le premier résultat de la multiplication, comme ci dessous. Le résultat de la multiplication est en cohérence avec les valeurs de i et j. Pour tester maintenant la modification à la volée d'une variable, on va continuer l'exécution du programme et réexécuter une seconde fois la boucle en appuyant plusieurs fois sur la touche F10 mais sans exécuter l'instruction print, comme dans l'image ci dessous. La valeur des 2 variables a bien été modifiée par programmation. Pour modifier maintenant dynamiquement la valeur de j, il faut cliquer sur l'onglet Remote console, taper la ligne j = 20 puis appuyer sur la touche Entrée pour valider la commande, comme dans l'image ci dessous. On peut alors voir que la valeur de j a bien été modifiée dans la fenêtre de Watch. Il suffit maintenant de recliquer sur l'onglet Output (suspended), et d'appuyer de nouveau sur la touche F10 pour reprendre l'exécution du programme. On constate alors que la valeur de j mise à 20 à la main a bien été prise en compte dynamiquement par le programme. Je remercie encore une fois steven pour ce super travail
  23. Bonsoir, Je vous propose un petit module virtuel que j'ai développé hier soir pour bien gérer le décodeur Orange LiveBox Play. J'ai en ce qui me concerne développé ce module pour pas mal de raisons dont voici les principales : 1) Pouvoir piloter la LiveBox bien sà»r 2) Gérer son état (ON, OFF, SLEEPING, STARTING) en temps réel 3) Trouver une solution de contournement à son absence de HDMI CEC, très ennuyeux 4) Pouvoir la couper durant l'absence prolongée, la nuit et surtout la redémarrer proprement chaque jour au bon moment et ainsi éviter de devoir la rebooter manuellement lorsqu'on en a vraiment besoin 5) Faire des économies car même en veille elle consomme quand même 17W à moins d'activer la veille profonde qui désactive les enregistrements programmés. Voici donc le code du module virtuel. Et 4 icônes que je propose pour les 4 états : Une fois le module importé, il faudra renseigner l'adresse IP de votre décodeur LiveBox (réservation DHCP recommandée) ainsi que le port qui est 8080. A noter : une des partie chiante de ce développement est liée à un bug de la version actuelle de l'API JSON de la LiveBox qui retourne une erreur lorsque l'ont souhaite récupérer son état courant. Or j'en ai besoin pour initialiser mon Virtual Device... La solution de contournement que j'ai trouvé repose sur l'utilisation de la Long Polling API qui permet d'être notifié d'un changement de contexte sur la LiveBox. Ainsi au démarrage de la MainLoop, afin de connaître l'état courant de la bête : 1) Je simule un appui sur un bouton (le dernier du Virtual Device) qui va simplement me permettre de faire un appel asynchrone temporisé simulant un appui sur Menu puis CH+ 2) Je lance immédiatement un appel de cette fameuse Long Polling API (notifyEvent) qui est bloquante 55s si rien ne se passe ou répond instantanément si un événement survient 3) Je peux ainsi initialiser mon état et être notifié des futurs changements en appellant en permanence la méthode notifyEvent qui au pire partira en timeOut au bout de 55s Pour ne rater aucun événement, je suis obligé de faire un while true dans la MainLoop sinon je prend le risque de perdre un événement qui pourrait survenir durant les 3s de sleep de celle-ci... Je teste ce module depuis hier et tout fonctionne très bien, c'est hyper réactif, vous pouvez faire des essais avec la télécommande physique de la LiveBox ou tout autre moyen de pilotage. Je suis même étonné de ne pas rencontrer de souci. Si vous n'avez pas de module relais en amont de l'alimentation de votre LiveBox, mettez simplement nil comme valeur pour la variable powerSwitchId (MainLoop, button ⎋ ON/VEILLE et button ⎋ POWER OFF. Vous n'aurez pas de gestion de l'état OFF mais ne supprimez pas le bouton ⎋ POWER OFF car cela décalera les ID des boutons. Si vous souhaitez le faire il faudra aller modifier en conséquence du dernier bouton de la MainLoop ligne 54 (32->31) -- Si je ne connais pas l'état, je déclenche un appui temporisé sur le bouton menu if (lbCurrentStatus == "NA") then fibaro:call(deviceId, "pressButton", 32) end Pensez également à mettre à jour les ID de vos icônes dans la fonction updateLiveBoxIcon() ​Il est fort probable qu'il y ait quelques bugs que je n'ai pas encore vus donc n'hésitez pas à me les signaler. Aussi, je viendrais mettre à jour le Device si j'apporte des améliorations. Voici enfin le code complet de la MainLoop ------------------------------------------------------ -- TV Commande v0.2 -- ------------------------------------------------------ -- Auteur : Brice Cassagnabère -- ------------------------------------------------------ -- Changelog : -- -- v0.2 : Ajout d'un test port et IP au démarrage -- -- Amélioration du code -- -- v0.1 : Version initiale -- ------------------------------------------------------ -- Plus d'infos : http://is.gd/RcK1xZ -- ------------------------------------------------------ -- Variables globales de la MainLoop lbCurrentStatus = "NA" lbNewStatus = "NA" -- ID du module relais de l'alimentation (FGS, WallPLug, Greenwave...) nil si pas présent powerSwitchId = 235 deviceId = fibaro:getSelfId() -- Functions utiles function debug(text, color) color = color or "white" fibaro:debug("<font color='"..color.."'>"..text.."</font>") end function updateLiveBoxUIStatus() if (lbCurrentStatus == lbNewStatus) then return end lbCurrentStatus = lbNewStatus fibaro:log("Status : "..lbCurrentStatus) debug("LiveBox status : "..lbCurrentStatus, "green") fibaro:call(deviceId, "setProperty", "ui.labelStatus.value", lbCurrentStatus) end function updateLiveBoxIcon() if lbCurrentStatus == "ON" then iconId = 1035 elseif lbCurrentStatus == "SLEEPING" then iconId = 1033 elseif lbCurrentStatus == "OFF" then iconId = 1034 elseif lbCurrentStatus == "STARTING" then iconId = 1032 end fibaro:call(deviceId, "setProperty", "currentIcon", iconId) end function liveBoxEventPolling() if (tonumber(powerSwitchId ~= nil and fibaro:getValue(powerSwitchId, 'value')) == 0) then lbNewStatus = "OFF" debug("LiveBox à l'arrêt complet", "red") else -- Detection de l'état de la livebox debug("En attente d'événement de la LiveBox...") LBox = Net.FHttp(tostring(fibaro:get(deviceId, 'IPAddress')), tostring(fibaro:get(deviceId, 'TCPPort'))) -- Si je ne connais pas l'état, je déclenche un appui temporisé sur le bouton menu if (lbCurrentStatus == "NA") then fibaro:call(deviceId, "pressButton", 32) end -- Je lance une commande long polling response = LBox:GET("/remoteControl/notifyEvent") -- Un événement est survenu, je traite l'événement if (response ~= nil and response ~= "") then debug(response, "yellow") jsonResponse = json.decode(response) if jsonResponse.result.message == "request timeout" then if lbCurrentStatus == "NA" then lbNewStatus = "SLEEPING" else debug("Pas d'événement durant 55s, LiveBox toujours en état : "..lbCurrentStatus, "orange") end elseif jsonResponse.result.message == "event notification" then if jsonResponse.result.data.eventType == "OSD_CONTEXT_CHANGED" then debug(jsonResponse.result.data.service, "orange") -- Dans ce cas, la LiveBox est allumée donc je peux mettre à jour son statut if (jsonResponse.result.data.service == "HOMEPAGE") then lbNewStatus = "ON" elseif (jsonResponse.result.data.service == "MAIN_PROCESS") then lbNewStatus = "SLEEPING" end elseif jsonResponse.result.data.eventType == "MEDIA_STATE_CHANGED" then lbNewStatus = "ON" debug("ZAPPING", "orange") fibaro:log("ZAPPING") end end elseif lbCurrentStatus == "OFF" or lbCurrentStatus == "NA" then lbNewStatus = "STARTING" end end end local error = false if (fibaro:get(deviceId, 'IPAddress') == "") then debug("Vous devez renseigner l'Adresse IP du décodeur dans le champs dédié du Virtual Device", "red") debug("Vous pouvez retrouver cette adresse dans l'interface d'administration de la LiveBox") debug("Il est recommandé de faire une réservation DHCP pour être sà»r que l'IP ne change jamais") error = true end if (fibaro:get(deviceId, 'TCPPort') == "0") then debug("Vous devez renseigner le Port dans le champs dédié du Virtual Device", "red") debug("Le port par défaut est 8080 sur le décodeur LiveBox Play (noir)") error = true end if (error) then return end while true do pcall(liveBoxEventPolling) pcall(updateLiveBoxUIStatus) pcall(updateLiveBoxIcon) if (lbCurrentStatus == "OFF" or lbCurrentStatus == "STARTING") then fibaro:sleep(5000) end end J'espère que cela vous sera utile ! TV_Commande v0.2.vfib
  24. Voici une interprétation / traduction du premier onglet « Résumé des fonctions » (Spis funkcji) de la page officielle de documentation Fibaro http://docs.fibaro.com/?page_id=861. Il s’agit surtout des bases du langage LUA pour les scripts Fibaro. J’ai rajouté quelques interprétations, moyens de compréhension… pour que cette traduction ressemble également à un tutoriel comme j’aurai aimé le trouver quand j’ai commencé il y a quelques mois à écrire quelques bouts de code. Certaines fonctions semblent manquer, avoir changé, avoir disparu, ou même ne fonctionnent pas encore (j’ai cru lire ça quelque part à propos des scripts utilisant les données géographiques), car je ne pense pas que Fibaro mettent à jour très régulièrement cette base de donnée. J’espère que les débutants surtout, apprécieront, et pour les pros, n’hésitez pas à me faire corriger les mauvaises traductions / interprétations. Je ferai surement par la suite, d’autres traductions de leurs pages car cette première m’a vraiment été d’une grande utilité pour démarrer dans le monde de l’automatisme (en LUA ici) sachant que je partais presque de zéro (juste des notions avec excel, si on peut les apparenter de loin…) Comprendre certaines choses avant de démarrer : Un script LUA doit toujours commencer par l’entête suivant. Certes cela fonctionne aussi sans, mais si vous voulez modifier plus tard le script pour : - intégrer des déclenchements automatiques de la scène (trigger) en fonction de certaines actions ou évenements extérieurs - démarrer automatiquement la scène après enregistrement (pratique dans le cas d’une lecture infinie de la boucle de code, puisque cela vous permet de ne pas oublier d’appuyer sur le bouton ‘démarrer’ la scène après enregistrement) - d’autres choses encore, il faudra insérer des éléments dans cet entête. --[[ %% properties %% globals --]] Le mot " local " permet de signaler dans le script qu’on va stocker derrière, une variable en tant que ‘variable locale’. Imaginez que vous ouvrez un tiroir et que vous y mettiez la variable 'a' (ou appelez la comme vous voulez).Vous pouvez lui donner une valeur directement (cas 1) : local a = 50 ou l’associer à une fonction (cas 2) : a = fibaro:getValue(107, 'value') Dans le script vous pourrez rouvrir ce tiroir pour chercher la valeur de 'a' dans le cas 1, ou éviter de retaper plusieurs fois la fonction entière dans le cas 2. - Cas 1 : Imaginons qu’on associe 'a' à l’intensité lumineuse en pourcent d’un spot branché sur un variateur (dimmer fibaro par exemple). Dans le script on pourra faire allumer le spot à une certaine intensité (50%) en demandant à ce que le paramètre de luminosité du variateur associé au spot prenne la valeur de 'a' (ainsi pas besoin de lui donner la valeur 50) ou bien de a + 10 par exemple. local a = 50 -- on définit la variable locale avec nom et valeur fibaro:call(12, 'setValue', a) -- on demande au système d'appeler (call) le module 12 et de lui donner la valeur (setValue) de 'a' (soit 50) -- ou par exemple fibaro:call(12, 'setValue', a + 10) - Cas 2 : Imaginons maintenant que 'a' représente la fonction qui vérifie l'intensité du spot 107. On va créer une scène qui éteint le spot numéro 108, si le spot 107 est allumé et inversement. local a = fibaro:getValue(107, 'value') -- 'a' représente la fonction qui récupère (get) la valeur (Value) de l'intensité (value) du spot 107 if tonumber(a) >= 1 then -- si la valeur récupérée (ramenée en valeur numérique grâce à tonumber) est supérieure à 1 (allumé), alors fibaro:call(108, 'turnOff') -- le spot 108 s’éteint. else fibaro:call(108, 'turnOn') -- sinon le spot 108 s’allume end -- fin de la condition En utilisant 'a' dans ce genre de cas et si on doit répéter plusieurs fois la fonction associée, on évite de surcharger le script ou de faire des erreurs de saisie en retapant plusieurs fois une longue fonction. Le mot " local " n’est pas obligatoire, les variables locales fonctionnent même sans les introduire par ce mot. Cependant il est plus aisé à la relecture d’un script de retrouver les variables qu’on va utiliser en les précédant de ce mot. Ne mettez pas d’accents, d’espace ou de caractères spéciaux dans le nom de vos variables. Il est important de respecter les minuscules et les majuscules des commandes, fonctions, par contre vous pouvez utiliser ‘ ‘ou « » dans vos scripts ça ne changera rien … Dans une parenthèse on peut mettre un espace après l’ouverture de parenthèse et avant la fermeture, ou ne pas en mettre. Cela n’a aucune incidence. Il semble d’ailleurs que les espaces ne soient pas importants dans la construction du script (sauf entre les mots évidemment, mais pas importants entre les mots et les ponctuations). La fonction fibaro:debug() permet « d’imprimer » des messages dans la case sous le script, au fur et à mesure de sa lecture par le système et ainsi permet à l’utilisateur de pouvoir vérifier des résultats de l’automate.Si vous avez besoin de mettre une apostrophe dans une phrase pour la fonction debug, il faut mettre devant le \ pour que la lecture du script ne bug pas sur l’apostrophe. fibaro:debug('Il n\’y a qu\’une action en cours') Une seconde correspond à 1000ms. Lorsqu’on veut donner une durée dans le script il faut convertir le temps voulu en ms. Les tabulations automatiques ou manuelles lors de l’écriture du script ne sont pas importantes, mais un script bien agencé sera plus facile à comprendre, ou permet de repérer des erreurs ou oublis (par exemple en utilisant du conditionnel if then else, il faut finir cette condition par end, mais dans certains cas cette condition se retrouve dans une autre condition ou dans une autre chaîne qui nécessite également un end à la fin).Exemple : la chaine while true do en 1 nécessite end en 14 quand on veut arrêter la lecture en boucle qu’elle commande et reprendre la lecture au début. Dans cette boucle de lecture on a inséré une condition qui commence en 3-4 et se finit en 12, dans laquelle on a glissé une autre condition en 6-7 qui se finit en 10. L’architecture structurée permet de voir plus clair dans le script. while true do local--- if then --------- local--- if then -------- else ------ end else ------ end end On retrouvera des couleurs dans le script. Le gris correspond à des notes personnelles, il faut commencer chaque ligne par -- puis votre texte, ou --[[ texte ]]-- (sur plusieurs lignes). Le système ne tiendra pas compte de nos notes, sauf dans l’entête. Les caractères spéciaux et accents ne posent pas de problème dans ces notes. Le vert correspond aux actions à effectuer sur les modules (‘turnOff’, ‘setValue’…) ; au nom d’une propriété que l’on veut surveiller ou sur laquelle on veut agir (‘value’, ‘dead’, ‘isLight‘…) ; aux messages qu’on associera aux fonctions debug : fibaro:debug('La scène est en cours d\’exécution') ) ; à une valeur à atteindre par une fonction (ouverture de volet ou allumage d’une lampe sur variateur ‘50’, ‘75’). Attention aux valeurs ‘1’ et ‘0’ qui peuvent correspondent à un état d’une propriété d’un module (le module gère l'éclairage ('1') ou le module ne gère pas l'éclairage('0') est le retour d’état de la propiété isLight d'un module dimmer, ON ('1) et OFF ('0') est le retour d'état de la propriété value d'un module relai switch) ; au nom d'une variable globale qu'on utilise dans une fonction; à une position géographique « 52.5648 ;-12.5861 » ; et encore d'autres choses... Le rouge correspond au numéro d’identification d'un module ou d'une scène (DeviceID, SceneID… : 12, 54…) ; à une durée dans la fonction sleep ; à une valeur assignée à une variable locale ou une valeur à comparer. Le bleu correspond à toute l’architecture du système : local qui permet de signaler une variable du nom qu’on choisira et à laquelle on peut associer une fonction ou une valeur ; à des conditions if then else (si alors sinon), while true do (lance une lecture en boucle infinie du script); des valeurs booléennes (false et true dans par exemple la vérification de l'activité ou non d'une scène) …. Le jaune correspond aux variables dont on choisit le nom (en français, en anglais ou autre, sans espace entre les mots ex : MaVariable, qu’on peut retrouver derrière local forcément, mais aussi dans des messages de la fonction fibaro:debug, ou de la fonction fibaro:call, ou bien dans une condition if then pour récupérer ou comparer une valeur associée à cette variable) ; ainsi qu’à toutes les fonctions (fibaro:abort, fibaro:get...). Le orange correspond à des outils système (os.date, string.format, tonumber…) Liste des fonctions (par ordre alphabétique)fibaro:abort() fibaro:calculateDistance(position1, position2) fibaro:call(deviceID, actionName, …) fibaro:countScenes() fibaro:countScenes(sceneID) fibaro:debug(text) fibaro:get(deviceID, propertyName) fibaro:getGlobal(varName) fibaro:getGlobalModificationTime(varName) fibaro:getGlobalValue(varName) fibaro:getModificationTime(deviceID, propertyName) fibaro:getRoomID(deviceID) fibaro:getSectionID(deviceID) fibaro:getSourceTrigger() fibaro:getSourceTriggerType() fibaro:getType(deviceID) fibaro:getValue(deviceID, propertyName) fibaro:isSceneEnabled(sceneID) fibaro:killScenes(sceneID) fibaro:setGlobal(varName, value) fibaro:setSceneEnabled(sceneID, enabled) fibaro:sleep(time) fibaro:startScene(sceneID) Résumé des fonctions (thématique)DISPOSITIFS DE CONTRà”LE fibaro:call(deviceID, actionName, …) fibaro:get(deviceID, propertyName) fibaro:getValue(deviceID, propertyName) fibaro:getModificationTime(deviceID, propertyName) fibaro:getType(deviceID) fibaro:getRoomID(deviceID) fibaro:getSectionID(deviceID) SCENES DE CONTROLE fibaro:abort() fibaro:getSourceTrigger() fibaro:getSourceTriggerType() fibaro:startScene(sceneID) fibaro:killScenes(sceneID) fibaro:setSceneEnabled(sceneID, enabled) fibaro:isSceneEnabled(sceneID) fibaro:countScenes() fibaro:countScenes(sceneID) TRAITEMENT DES GLOBALS fibaro:setGlobal(varName, value) fibaro:getGlobal(varName) fibaro:getGlobalValue(varName) fibaro:getGlobalModificationTime(varName) CARACTÉRISTIQUES SUPPLÉMENTAIRES fibaro:debug(text) fibaro:calculateDistance(position1, position2) Liste des fonctions (par ordre alphabétique) - fibaro:abort() DESCRIPTION On arrête le script en cours d'exécution. CARACTÉRISTIQUES Aucune VALEURS RÉCUPÉRÉES Aucune EXEMPLE local a = 0 -- on définit la variable avec nom et valeur -- On démarre une boucle infinie de lecture, le script sera relu sans arrêt grâce à la commande: while true do -- si a est supérieur à 10 alors la lecture du script s'arrête en 7 if (a > 10) then fibaro:abort() end -- fin de la condition -- si a est inférieur à 10, la lecture du script continue -- on augmente maintenant de 1 la valeur de la variable a a = a + 1 -- on attend 1 seconde fibaro:sleep(1000) end -- fin de la boucle de lecture. La lecture reprend en 3 -- la lecture s'arrête en 13 et redémarre en 3 avec la nouvelle valeur de a jusqu'à ce que a soit supérieur à 10 et que la lecture du script s'arrête - fibaro:calculateDistance(position1, position2) DESCRIPTION On calcule la distance entre deux points géographiques: position1 et position2. CARACTÉRISTIQUES position1: premier point position2: second point Le point est exprimé avec sa latitude et sa longitude. Ces deux valeurs sont exprimées en degrés avec une partie décimale, et sont séparées par un point-virgule. Une valeur négative est donnée pour les valeurs de l'ouest et du sud. Le séparateur décimal est un point. Par exemple, le point 40°44'55"N, 73°59'11"W doit être enregistré comme une chaîne (string) "40.7486;-73.9864". Ce format correspond à la propriété « Location » (emplacement) du device « HC_user » (l’utilisateur) et stocke la dernière position de l'utilisateur du Home Center 2. VALEURS RÉCUPÉRÉES La distance, exprimée en mètres. EXEMPLE -- le système repère l'emplacement (propriété Location) du device 123 (moi par exemple grâce à mon smartphone) et stocke les données de mon emplacement dans la variable : local MonEmplacement = fibaro:getValue(123, 'Location') -- on crée une variable correspondant à la fonction qui récupère (get) la valeur (Value) de la propriété Location (emplacement) du device 123 (moi) -- on va ensuite stocker l'emplacement de notre maison dans une seconde variable: local EmplacementMaison = "52.4325295140701;16.8450629997253" -- on crée une dernière variable qui correspondra au résultat de la fonction qui calcule la distance entre nos 2 points: local Distance = fibaro:calculateDistance(MonEmplacement, EmplacementMaison) -- enfin la fonction debug m'indiquera cette distance grâce au texte que j'y associe et dans lequel j'ai inséré le résultat de ma variable Distance (qui sera retranscrite en valeur numérique) fibaro:debug('La distance est de '..Distance..'m') - fibaro:call(deviceID, actionName, arguments) DESCRIPTION On envoie une demande à un module (device) pour qu’il exécute une action. CARACTÉRISTIQUES deviceID: numéro du module (c’est son identité dans le système) actionName: chaîne (string) qui représente le nom de l’action argument: les arguments peuvent se succéder. De 0 à 7 arguments par action. VALEURS RÉCUPÉRÉES Aucune EXEMPLE -- on demande au module d'ID=12 de s'éteindre fibaro:call(12, 'turnOff') -- on demande au module d'ID=12 de fixer sa valeur à 23 (intensité en % d'une lampe sur variateur, ouverture d'un volet) fibaro:call(12, 'SetValue', '23') DESCRIPTION ÉTENDUE Il convient de noter que tous les arguments des fonctions call sont des chaînes (string). Ici '23' est une chaîne et non une valeur numérique (c'est pour cela qu'il faut mettre des guillemets sinon ça ne fonctionnera pas). Cependant, grâce au mécanisme intégré coercitif [lien Fibaro manquant pour l'explication], il n'est pas nécessaire de convertir les types numériques en chaîne (vous pouvez autant mettre une valeur numérique que le nom d'une variable qui est un format string). Nous verrons plus tard qu'à certains moments il faudra convertir une chaîne en valeur numérique grâce l'outil tonumber). -- le système stocke la valeur 50 pour la variable qu'on appelle 'a' local a = 50 -- on demande au module d'ID=12 de prendre la valeur de 'a' qui est en format string fibaro:call(12, 'SetValue', a) Une description des actions disponibles ainsi que le nombre de paramètres requis est disponible ici. [lien Fibaro manquant]. - fibaro:countScenes() DESCRIPTION On obtient le nombre de lecture en cours de la scène. Par exemple, en cliquant 2x (ou plus) sur 'démarrer' avant la fin de la première lecture, vous démarrez une seconde (ou plus) lecture du script, la première ne s'arrêtera pas ; vous pouvez avoir également plusieurs scènes qui démarrent une scène particulière, il peut donc être utile en début de script de cette scène particulière, d'interdire une nouvelle lecture du script si une lecture est déjà en cours d’exécution. CARACTÉRISTIQUES Aucune VALEURS RÉCUPÉRÉES Un entier positif qui spécifie le nombre d’exécution en cours de la scène. EXEMPLES -- on stocke dans la variable num, le nombre d'instances en cours de la scène local num = fibaro:countScenes() -- si il n'y a qu'une lecture en cours de la scène, alors la fonction debug m'indiquera la phrase que j'y associe ('il n'y a qu'une lecture en cours') if num == 1 then fibaro:debug('Il n\’y a qu\’une lecture en cours') -- sinon la fonction debug intégrera le nombre de lectures de la scène dans une autre phrase que j'y associe ('nombre d'instances en cours: ') else fibaro:debug('Nombre d\’instances en cours: '..num) -- notez que pour insérer une valeur d'une variable dans la fonction debug, il faut 2 points du coté du texte (avant et/ou après) end -- avant qu'une scène ne s'exécute, elle peut vérifier si elle est déja en cours d'exécution pour ne pas être lue plusieurs fois en même temps if fibaro:countScenes() > 1 then -- si la scène est lancée plus d'une fois alors fibaro:abort() -- arrêt de cette lecture du script end -- fin de la condition -- notez qu'on peut écrire aussi de cette façon local num = fibaro:countScenes() if num > 1 then fibaro:abort() end - fibaro:countScenes(sceneID) DESCRIPTION On obtient le nombre d’exécution en cours pour une scène donnée (chaque scène est identifiée par son identité sceneID et peut être utilisée dans d’autres scènes) CARACTÉRISTIQUES sceneID: Numéro de la scène, identité de la scène VALEURS RÉCUPÉRÉES Un entier positif qui spécifie le nombre d'exécution en cours d'une scène donnée. EXEMPLE -- on veut afficher le nombre d'exécution en cours de la scène d'ID=12 local num = fibaro:countScenes(12) fibaro:debug('Nombre d\’instances en cours de la scène 12 '..num) -- on veut vérifier que la scène 12 est en cours d'exécution if fibaro:countScenes(12) >= 1 then fibaro:debug('La scène 12 est en cours d\’exécution') else fibaro:debug('La scène 12 n\’est pas en cours d\’exécution') end - fibaro:debug(text) DESCRIPTION On imprime le message dans la console de débogage associée au script. CARACTÉRISTIQUES text: texte à afficher VALEURS RÉCUPÉRÉES Aucune EXEMPLE fibaro:debug('Exemple de message') Résultat dans la console de débogage du script: - fibaro:get(deviceID, propertyName) DESCRIPTION On récupère les informations (valeur et heure de dernière modification) sur les propriétés d’un module CARACTÉRISTIQUES deviceID: numéro d'identité du module propertyName: intitulé de la propriété VALEURS RÉCUPÉRÉES Une chaîne contenant la valeur actuelle d’une des propriétés d’un module Horodatage (timeStamp) [lien Fibaro manquant pour l'explication] de la dernière modification EXEMPLE -- on veut récupérer (get) l'heure et la valeur de la dernière modification de la propriété 'value' du module d'ID=11. Il existe plusieurs propriétés qu'on peut récupérer ou modifier pour chaque module. La propriété 'value' peut correspondre à une température, une intensité lumineuse en %, une ouverture d'un volet en %... local valeur, HeureModification = fibaro:get(11,'value') -- en LUA, on peut ignorer la seconde valeur de retour (pas très clair) local valeur2 = fibaro:get(11, 'value') -- les valeurs obtenues peuvent ensuite être utilisées dans des scènes -- l'outil tonumber permet de convertir une variable (qui est au format chaîne (string)) en valeur numérique, afin de la comparer à une autre valeur numérique if tonumber(valeur2) >= 50 then -- si la valeur récupérée et transformée en valeur numérique est supérieure à 50 alors fibaro:call(142, 'turnOff') -- le système demande au module d'ID=142 de s'éteindre DESCRIPTION ÉTENDUE Les principales fonctions : fibaro:get(deviceID, propertyName) fibaro:getValue(deviceID, propertyName) fibaro:getModification(deviceID, propertyName) Elles sont utilisées dans les scripts de scènes pour récupérer l'état actuel des modules. La valeur récupérée doit être affectée à des variables locales afin de pouvoir utiliser des instructions conditionnelles (if, then). Voir exemple ligne 7. Ces 3 fonctions ne diffèrent que par la valeur récupérée. Notez que les valeurs récupérées sur les propriétés (propertyName), sont des variables de type ‘chaîne’ (string), ce qui signifie que, si on veut les comparer avec des valeurs numériques, il faut transformer ces variables en valeurs numériques elles aussi, grâce à la commande tonumber. Voir exemple ligne 7. Exemple concret, car l'exemple ci-dessus de la documentation Fibaro n'est pas très intéressant car pour récupérer les valeurs des propriétés des modules classiques, on peut autant utiliser la fonction fibaro:get(deviceID, propertyName) que la fonction fibaro:getValue(deviceID, propertyName). Pour récupérer l'adresse IP d'un module virtuel d'ID=126 deviceIp = fibaro:get(126, "IPAddress") -- merci à i-magin grâce à qui j'ai trouvé l'exemple là sur le forum - fibaro:getGlobal(varName) DESCRIPTION On récupère des informations (valeur et heure de la dernière modification) de la variable globale enregistrée dans le système. CARACTÉRISTIQUES varName: Le nom de la variable globale VALEURS RÉCUPÉRÉES Une chaîne contenant la valeur actuelle de la variable globale Horodatage (timeStamp) [lien Fibaro manquant pour l'explication] de la dernière modification EXEMPLE -- on veut récupérer l'heure et la valeur de la dernière modification de la variable globale appelée 'Nuit' à laquelle on a associé les valeurs '0' (jour) ou '1' (nuit), on aurait pu choisir d'autres noms comme jour et nuit directement ou oui et non... local valeur, HeureModification = fibaro:getGlobal('Nuit') -- en LUA, on peut ignorer la seconde valeur de retour (pas très clair) local valeur2 = fibaro:getGlobal('Nuit') -- les valeurs ainsi obtenues peuvent être utilisées dans des scènes if (value == '1') then fibaro:debug('Il fait nuit') end DESCRIPTION ÉTENDUE Les principales fonctions : fibaro:getGlobal(varName) fibaro:getGlobalValue(varName) fibaro:getGlobalModificationTime(varName) Elles sont utilisées dans les scripts de scènes pour récupérer l'état actuel des variables globales. La valeur récupérée doit être affectée à des variables locales afin de pouvoir utiliser des instructions conditionnelles (if then). Ces 3 fonctions ne diffèrent que par la valeur récupérée. - fibaro:getGlobalModificationTime(varName) DESCRIPTION On récupère des informations (seul l'horodatage de la dernière modification) de la variable globale enregistrée dans le système. CARACTÉRISTIQUES varName: Le nom de la variable globale VALEURS RÉCUPÉRÉES Horodatage de la dernière modification de la variable globale. EXEMPLE -- on veut récupérer la date de la dernière modification de la variable globale nommée 'compteur' local DerniereModif = fibaro:getGlobalModificationTime('compteur') -- si la valeur de cette variable globale a été modifiée il y a plus de 10 secondes if os.time() - DerniereModif >= 10 * 1000 then fibaro:debug('La modification a eu lieu il y a plus de 10s') else fibaro:debug('La modification a eu lieu il y a moins de 10s') VOIR AUSSI fibaro:getGlobal fibaro:getGlobalValue - fibaro:getGlobalValue(varName) DESCRIPTION On récupère des informations (seule la valeur) de la variable globale enregistrée dans le système. CARACTÉRISTIQUES varName: Le nom de la variable globale VALEURS RÉCUPÉRÉES Une chaîne contenant la valeur actuelle de la variable globale. EXEMPLE -- on veut récupérer la valeur de la variable globale nommée 'compteur' local ValeurCompteur = fibaro:getGlobalValue('compteur') VOIR AUSSI fibaro:getGlobal fibaro:getGlobalModificationTime - fibaro:getModificationTime(deviceID, propertyName) DESCRIPTION On récupère des informations (seule l'horodatage de la dernière modification) sur les propriétés d'un module. CARACTÉRISTIQUES deviceID: numéro d'identité du module propertyName: nom de la propriété VALEURS RÉCUPÉRÉES Horodatage des dernières modifications de propriétés du module. EXEMPLE -- on veut récupérer la date de la dernière modification de la propriété 'value' du module d'ID=11, exemple l'heure à laquelle la lampe a changé d'intensité local HeureModif = fibaro:getModificationTime(11, 'value') -- os.time() correspond à l'horodatage au moment de la lecture du script if os.time() - HeureModif >= 10*1000 then -- si la différence de temps entre le moment où le script est lu et le moment de la dernière modification est supérieur à 10s alors fibaro:debug('La dernière modification de la valeur date de plus de 10s') else fibaro:debug('La dernière modification de la valeur date de moins de 10s') - fibaro:getRoomID(deviceID) DESCRIPTION On récupère le numéro de la pièce dans laquelle se trouve le module. CARACTÉRISTIQUES deviceID: numéro d’identité du module VALEURS RÉCUPÉRÉES RoomID: Numéro qui identifie la pièce dans laquelle se trouve le module (Le RoomID de la pièce sans nom ‘non assigné’ est 0) EXEMPLE -- on veut récupérer le numéro d'identité de la pièce dans laquelle se trouve le module d'ID=9 local Piece = fibaro:getRoomID(9) -- on demande au système de récupérer (get) l'identité de la pièce (RoomID) où se trouve le module d'ID=9 et on stocke cette valeur dans la variable qu'on appelera Piece if Piece == 0 then fibaro:debug('Le module se trouve dans la pièce \’non assigné\’') else fibaro:debug('Le module se trouve dans la pièce d\’ID '..Piece) VOIR AUSSI fibaro:getSectionID fibaro:getType - fibaro:getSectionID(deviceID) DESCRIPTION On récupère le numéro d’identité de la section dans laquelle le module est situé. CARACTÉRISTIQUES deviceID: numéro d’identité du module VALEURS RÉCUPÉRÉES SectionID : numéro de la section dans laquelle l'appareil est situé (le SectionID de la section sans nom ‘non assigné’ est 0) EXEMPLE -- on veut récupérer le numéro d'identité de la section dans laquelle se trouve le module d'ID=9 local Section = fibaro:getSectionID(9) -- on demande au système de récupérer (get) l'identité de la section (SectionID) où se trouve le module d'ID=9 et on stocke cette valeur dans la variable qu'on appelera Section if Section == 0 then fibaro:debug('Le module se trouve dans la section \’non assigné\’' else fibaro:debug('Le module se trouve dans la section '..Section) VOIR AUSSI fibaro:getRoomID fibaro:getType - fibaro:getSourceTrigger() DESCRIPTION On récupère les informations sur l’origine du trigger (déclencheur) qui a démarré la scène automatiquement. CARACTÉRISTIQUES Aucune VALEURS RÉCUPÉRÉES Des informations sur le « type » de déclenchement qu’on peut classer dans un tableau. Selon le déclenchement, le « type », peut avoir ces 3 valeurs: ‘property’ - scène déclenchée par la modification d'une propriété d'un module ‘global’ - scène déclenchée par la modification d'une variable globale ‘other’ - dans les autres cas (scène lancée directement grâce à un autre script ou en manuel depuis l'interface par l'utilisateur) Selon la valeur du « type » de déclenchement, la table peut encore avoir des champs supplémentaires, qu'on pourra également récupérer. DESCRIPTION ÉTENDUE Cette fonction peut être utilisée pour déterminer l’origine directe du déclenchement du script. En début de script, dans l’en-tête, on définit les paramètres déclencheurs qui peuvent causer l’exécution du script. Sans cet en-tête rempli correctement, le script ne s’exécutera pas automatiquement. Grâce à la fonction fibaro:getSourceTrigger() on peut récupérer plusieurs éléments en rajoutant derrière : ['type'],['deviceID],[propertyName] ou [varName] : - Le 'type' de l'origine du déclenchement de la scène. On récuperera une des valeurs suivantes: property: si lancement auto de la scène grâce à une modification d'une propriété d'un module global: si lancement auto de la scène grâce à une modification d'une variable globale other: si déclenchement manuel de la scène par l'utilisateur ou depuis une autre scène - 'deviceID' est le numéro d'identité du module surveillé dans l'entête, qui est à l'origine du déclenchement automatique de la scène. - 'propertyName' est le nom de la propriété d'un module surveillé dans l'entête, qui a vu sa valeur changer et qui est à l'origine du déclenchement automatique de la scène. Par exemple une modification de la propriété 'value' quand un éclairage change d'intensité, ou qu'un radiateur se met en route etc, de la propriété 'baterryLevel' quand un module fonctionnant avec pile atteint un certain niveau de batterie, de la propriété 'armed' quand un module comme le capteur d'ouverture de porte est armé au moment de votre départ au travail et que cela démarre la scène qui vous préviendra par notification si la porte s'ouvre et que personne n'a désarmé le module... - 'varName' est le nom de la variable qui a vu sa valeur changer et qui est à l'origine du déclenchement automatique de la scène. Exemple on a crée une variable globale 'SAISON' qui peut prendre la valeur ETE ou HIVER. Quand on modifie cette saison via un module virtuel par exemple, une scène qu'on aura crée auparavant va se lancer automatiquement pour mettre les radiateurs en fonctionnement ou à l'arrêt suivant la saison indiquée. EXEMPLE Démarrage auto de la scène si : Changement de la propriété ‘value’ du module 13 Changement de la propriété ‘value’ du module 15 Changement de la variable globale 'JourNuit’ En outre, le script peut être exécuté directement à partir de l'interface ou en utilisant une autre scène (voir Fibaro: runScene (sceneID)). Lorsque le script est exécuté, il affiche les informations de débogage de la console sur l’origine de son exécution. --[[ %% properties 13 value 15 value %% globals JourNuit --]] local OrigineDeclenchement = fibaro:getSourceTrigger() -- on demande au système de récupérer (get) l'origine (Source) du déclenchement de la scène (Trigger) if OrigineDeclenchement['type'] == 'property' then -- si l'origine du déclenchement de la scène est la modification d'une propriété d'un module surveillée dans l'entête alors fibaro:debug('L\’ origine est la modification d\’une propriété du module '..OrigineDeclenchement['deviceID']) elseif OrigineDeclenchement['type'] == 'global' then -- sinon si l'origine du déclenchement de la scène est la modification d'une variable globale surveillée dans l'entête alors fibaro:debug('L\’ origine est la modification de la variable globale '..OrigineDeclenchement['varName']) elseif OrigineDeclenchement['type'] == 'other' then -- sinon si l'origine du déclenchement de la scène est autre alors fibaro:debug('La scène a été lancée manuellement') end VOIR AUSSI fibaro:getSourceTriggerType() - fibaro:getSourceTriggerType() DESCRIPTION On récupère des informations sur la valeur du « type » du déclencheur qui a causé la scène. CARACTÉRISTIQUES Aucune VALEURS RÉCUPÉRÉES Une chaîne (string) contenant la valeur du « type » du déclencheur (voir fibaro: getSourceTrigger () ) EXEMPLE -- on veut vérifier si la scène a été lancée manuellement if fibaro:getSourceTriggerType() == 'other' then -- si la fonction qui récupère (get) le type (Type) de l'origine (Source) du déclencheur (Trigger) est 'other' alors fibaro:debug('La scène a été lancée manuellement') end -- on a vu au dessus que la même chose peut être obtenue en utilisant le tableau précédent avec l'utilisation de getSourceTrigger() et en se référant au champ 'type' local OrigineDeclenchement = fibaro:getSourceTrigger() if OrigineDeclenchement['type'] == 'other' then fibaro:debug('La scène a été lancée manuellement') VOIR AUSSI fibaro:getSourceTrigger() - fibaro:getType(deviceID) DESCRIPTION On récupère le type de l'appareil. Les différents types d'appareils sont référencés ici PARAMàˆTRES deviceID: numéro d’identification du module VALEURS RÉCUPÉRÉES Une chaîne contenant le type du module EXEMPLE -- on veut récupérer le 'type' du module d'ID=100 local TypeModule = fibaro:getType(100) -- on récupère (get) le type (Type) du module d'ID=100 et on stocke le résultat dans la variable qu'on appelle 'TypeModule' if TypeModule == 'blind' then -- si le module commande un volet roulant alors fibaro:debug('Le module commande un volet roulant') else fibaro:debug('Type du module : '..TypeDispositif) -- sinon la fonction debug indique directement le type du module end VOIR AUSSI fibaro:getRoomID fibaro:getSectionID - fibaro:getValue(deviceID, propertyName) DESCRIPTION On récupère des informations (uniquement la valeur) d'une propriété d'un module. PARAMàˆTRES deviceID: numéro d’identification du module propertyName: nom de la propriété VALEURS RÉCUPÉRÉES une chaîne contenant la valeur actuelle de la propriété voulue EXEMPLE -- on veut récupérer la valeur de la 'valeur de luminosité' du module d'ID=11 local ValeurLum = fibaro:getValue(11, 'brightness') -- C'est ce qu'il y a indiqué sur le document fibaro mais la propriété brightness n'existe plus local ValeurLum = fibaro:getValue(11, 'value') -- C'est maintenant la propriété 'value' d'un dimmer qui permet de récupérer la valeur de la luminosité en pourcentage Exemple concret, une sonde de température dont on veut simplement récupérer la mesure : local TempSalon = fibaro:getValue(115, 'value') -- on demande au système de récupérer (get) la valeur (Value) de la propriété mesure de la température (value) de la sonde de température de salon (module 115) if tonumber(TempSalon) > 20 then -- si la valeur récupérée, une fois transformée en valeur numérique, est supérieure à 20 alors fibaro:call(12, 'turnOff') -- le système demande au relai 12 connecté au radiateur de se couper VOIR AUSSI fibaro:get fibaro:getModificationTime - fibaro: isSceneEnabled (sceneID) DESCRIPTION On vérifie si la scène avec un sceneID donné est active. PARAMàˆTRES sceneID: numéro d’identification de la scène VALEURS RÉCUPÉRÉES valeur booléenne: true si la scène est active, false si non active : d'après la documentation Fibaro, HORS cela ne fonctionne pas. Voir exemple 2 EXEMPLE if fibaro:isSceneEnabled(3) then -- si la scène 3 est activée cela activera la scène 5 fibaro:setSceneEnabled(5, true) end Exemple qui montre qu'on ne récupère pas la valeur true ou false local SceneActive = fibaro:isSceneEnabled(3) if SceneActive == 'true' then fibaro:debug('active') else fibaro:debug('inactive') end Que la scène soit active ou pas, le débogage indiquera inactive. Dans l'exemple précédent on ne pourrait donc pas activer la scène 5 si la scène 3 est inactive... VOIR AUSSI fibaro:setSceneEnabled(sceneID, enabled) - fibaro:killScenes(sceneID) DESCRIPTION On termine toutes les instances en cours d’exécution d'une scène donnée. (On se rappelle que le système peut lire plusieurs fois en même temps un script déjà en cours de lecture) PARAMàˆTRES sceneID: numéro d’identification de la scène VALEURS RÉCUPÉRÉES Aucune EXEMPLE -- si la valeur de 'a' est comprise dans l'intervalle [1;5], toutes les lectures en cours de la scène d'ID=2 s'arrêtent if a >= 1 and a <= 5 then fibaro:killScenes(2) VOIR AUSSI fibaro: startScene (sceneID) fibaro: countScenes () fibaro: countScenes (sceneID) - fibaro:setGlobal(varName, value) DESCRIPTION Modifie la valeur d'une variable globale. PARAMàˆTRES varName: le nom de la variable globale value: la nouvelle valeur de la variable globale VALEURS RÉCUPÉRÉES Aucune EXEMPLE -- on veut attribuer la valeur de 1 à une variable globale nommée 'index' fibaro:setGlobal('index', 1) -- on veut augmenter de 3 la valeur de la variable globale nommée 'test' fibaro:setGlobal('test', fibaro:getGlobalValue('test') + 3) -- on veut assigner à la variable globale nommée 'index', la valeur de la variable locale 'a' local a = 10 * 234 fibaro:setGlobal('index', a) DESCRIPTION ÉTENDUE La fonction fibaro:setGlobal(varName, value) ne peut être utilisée que pour les variables globales qui ne sont pas des variables en lecture seule. Si vous essayez de remplacer la valeur d’une variable en lecture seule, un avertissement sera généré et l'opération ne sera pas effectuée (pas clair). - fibaro:setSceneEnabled(sceneID, enabled) DESCRIPTION Active ou désactive une scène donnée. PARAMàˆTRES sceneID: numéro d’identification de la scène enabled: valeur booléenne (true - active la scène, false - désactive la scène) VALEURS RÉCUPÉRÉES Aucune EXEMPLE if a > 0 then fibaro:setSceneEnabled(3, false) -- si la valeur de la variable 'a' est positive, cela désactive la scène d'ID=3 else fibarosetSceneEnabled(3, true) -- sinon cela active la scène d'ID=3 end VOIR AUSSI fibaro:isSceneEnabled(sceneID) - fibaro:sleep(time) DESCRIPTION On suspend l'exécution du script pendant le temps spécifié en millisecondes. PARAMàˆTRES time: le temps en millisecondes VALEURS RÉCUPÉRÉES Aucune EXEMPLE -- on suspend la lecture du script pendant 10 secondes fibaro:sleep(10000) -- comme les durées doivent être indiquées en millisecondes, pour plus de compréhension on peut écrire fibaro:sleep(10 * 1000) - fibaro:startScene(sceneID) DESCRIPTION On veut démarrer l’exécution d'une scène donnée. PARAMàˆTRES sceneID: numéro d’identité de la scène qui doit être lancée VALEURS RÉCUPÉRÉES Aucune EXEMPLE if a > 20 then fibaro:startScene(10) -- si la valeur de 'a' est supérieure à 20, on démarre l'exécution de la scène d'ID=10 end
  25. Barelle

    VD UPS

    Hello, Comme vous le savez, nos matériels électroniques n’apprécient pas du tout les coupures électriques. Pour cela, il est plus que recommandé d’utiliser un onduleur (ou UPS, "Uninterruptible Power Supply")… Le VD que je vous propose ici permet l’interrogation du serveur UPS résidant sur un NAS Synology (auquel l’onduleur est connecté par un port USB). Il met à jour une variable globale (appelée UpsStatus par défaut) avec les valeurs "power-line" ou "battery" selon que l’onduleur est sur secteur ou sur batterie. Cette variable globale permet le lancement de la scène ci-après qui : - lors d’un passage sur batterie, après le délai "delayBeforePowerOff" réalisera l’arrêt de la HC2 ; - lors du retour de l’alimentation, appuiera sur le bouton "WOL" du VD. Là aussi, le réveil se fera après un délai "delayBeforeWakeUp". Ces délais ont pour objet de s’affranchir de retours temporaires de tension. --[[ %% properties %% events %% globals UpsStatus --]] local globalVarName = "UpsStatus"; -- values "power-line" or "battery" local wolVdId = "337"; local wolVdBtnId = "11"; local delayBeforePowerOff = 5; -- minutes local delayBeforeWakeUp = 5; -- minutes local debug = true; function trace(text, color) color = color or "white"; if debug then fibaro:debug("<font color='"..color.."'>"..text.."</font>"); end end -- trace function tracerr(text, color) color = color or "red"; fibaro:debug("<font color='red'>ERROR! </font>".."<font color='"..color.."'>"..text.."</font>"); end -- tracerr function wakeOnLan() fibaro:call(wolVdId, "pressButton", wolVdBtnId); end -- wakeOnLan local sourceTrigger = fibaro:getSourceTrigger(); trace("sourceTrigger[type] = " .. sourceTrigger["type"], "deepskyblue"); if (sourceTrigger["type"] == "global") then if (sourceTrigger["name"] ~= globalVarName) then tracerr("unknown global "..sourceTrigger["name"].." exiting"); fibaro:abort(); end elseif (sourceTrigger["type"] == 'other') then trace("Scene triggered manually", "lightgreen"); -- inform user local upsStatus = fibaro:getGlobalValue(globalVarName); if (upsStatus ~= nil) then trace(globalVarName.." = "..upsStatus, "lightgreen"); fibaro:abort(); end else tracerr("unexpected trigger type ".. sourceTrigger["type"], "orange"); fibaro:abort(); end if (fibaro:countScenes() > 1) then trace("Script already running, exiting.", "green"); return; end local upsStatus = fibaro:getGlobalValue(globalVarName); if (upsStatus == nil) then tracerr("global "..globalVarName.." = nil"); fibaro:abort(); end if (upsStatus == "power-line") then local i = 0; for i = 1, (delayBeforeWakeUp * 6) do -- check every 10 seconds during delayBeforeWakeUp minutes fibaro:sleep(10 * 1000); -- ten seconds upsStatus = fibaro:getGlobalValue(globalVarName); if (upsStatus ~= "power-line") then trace("Still on battery, aborting", "orange"); fibaro:abort(); -- not stable end end -- Time to wake up devices trace("Waking up devices", "lightgreen"); wakeOnLan(); elseif (upsStatus == "battery") then local i = 0; for i = 1, (delayBeforePowerOff * 6) do -- check every 10 seconds during delayBeforePowerOff minutes fibaro:sleep(10*1000); -- ten seconds upsStatus = fibaro:getGlobalValue(globalVarName); if (upsStatus ~= "battery") then trace("Power is back, shut down aborted", "orange"); fibaro:abort(); end end -- shutdown HC2 gracefully trace("shutting down", "lightgreen"); fibaro:sleep(10*1000); HomeCenter.SystemService.shutdown(); else tracerr("global "..globalVarName.." unknown value: "..upsStatus); end Installation du VD : - Importer le VD, - Renseigner l’adresse IP du NAS connecté à l’onduleur, le port TCP 3493 est optionnel. - Les username et password présents dans le code du bouton Update fonctionnent pour un Synology. - Dans le code du bouton WOL, vous devrez préciser les adresses MAC des matériels que vous souhaitez réveiller. Il va de soi qu’ils devront être paramétrés pour accepter les "magic packets" afin d’être réveillés (pour les PC vérifier les paramètres de la carte réseau). - Pour les Nas Synology, il faut activer le WOL : "Panneau de configuration", "Matériel et alimentation", onglet "Général", cocher "Activer WOL sur le réseau local x". - Et ne pas oublier d’activer le serveur réseau UPS : "Panneau de configuration", "Matériel et alimentation", onglet "UPS", cocher "Activer la prise en "charge UPS" et "Activer le serveur réseau UPS"). - Enfin bien sûr, trouver une jolie icône pour les boutons du VD. Installation de la scène : - Préciser l’id du VD réalisant le WOL dans "wolVdId". - et le numéro du bouton à appuyer "wolVdBtnId". Pour ceux qui veulent personnaliser le VD, le code du bouton "Update" contient, à la fin, une description des principaux champs retournés par les serveurs UPS, Tous ne sont pas implémentés par Synology ou mon onduleur. Configuration utilisée pour les tests : - HC2 : 4.153 Beta - Onduleur : Eaton Ellipse PRO 1200 - NAS : Synology DS1010+ with DSM 5.2-5967 Update 6 Joyeux réveillon et bonne année à tous… UPS.vfib
×