Welcome to Domotique-fibaro

 

Inscrivez-vous maintenant pour accéder à toutes nos fonctionnalités. Une fois inscrit et connecté, vous serez en mesure de contribuer à ce site en soumettant votre propre contenu ou en répondant au contenu existant. Vous serez en mesure de personnaliser votre profil, de recevoir des points de réputation comme une récompense pour la soumission de contenu, tout en communiquant avec d'autres membres via votre boîte de réception privée, et bien plus encore! Ce message sera supprimé une fois que vous vous êtes connecté.

 

Register now to gain access to all of our features. Once registered and logged in, you will be able to contribute to this site by submitting your own content or replying to existing content. You'll be able to customize your profile, receive reputation points as a reward for submitting content, while also communicating with other members via your own private inbox, plus much more! This message will be removed once you have signed in.

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
  • Fibaro's Awards
    • Membre du mois
    • Jeux concours & Cadeaux
  • Les bonnes affaires
    • Sites internet
    • Petites annonces

Calendriers

Aucun résultat à afficher.


129 résultats trouvés

  1. 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 :
  2. Tuto HC2

    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 !
  3. Tuto HC2

    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. 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 code V4.2 de ce post: http://www.domotique-fibaro.fr/index.php/topic/6446-yams-wu-yet-another-meteo-station-wunderground-version/page-6#entry138643 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
  5. Tuto HC2

    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
  6. Tuto HC2

    Bonjour à tous, Ma petite contribution pour pouvoir récupérer les films en cours de lecture sur le serveur Plex. Il y a encore beaucoup d'amélioration possible mais il modifie déjà une variable globale (1 = film en cours, 0 = aucun film) et affiche le film en cours. Note: Aucune gestion de la lecture de plusieurs films en même temps. Il manque aussi l'information sur la source du lecteur plex (tv, iphone, ...), ce sera pour une prochaine version ;-) Importez le virtual device PlexHC2.vfib.zip PlexHC2 modifiez ces lignes: -- !!! VOS PARAMETRES !!! PlexHC2.Plex_ip = '192.168.1.9' -- IP du serveur Plex PlexHC2.Plex_port = 32400 -- PlexHC2.globalvariable = "" L'image du VD Note2: Largement inspiré du script de Steven MétéoAlerte (un grand merci à lui pour son travail)
  7. 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...
  8. Gestion simple des Variables Globale en LUA Le script que je partage avec vous va vous permettre de gérer simplement les Variables globales et Variables globales prédéfinie en LUA. C'est une adaptation du code de STEVEN Avantage : Il permet de faire une sauvegarde des Variables globales ce qui est bien pratique lorsque l'on fait un recovery Il permet de créé des variables globales prédéfinie ou pas très simplement à partir d'une scène ou d'un VD sans avoir à sortir artillerie lourde. Voici le code a mettre dans une Scéne : --[[ %% properties %% globals GestionVG --]] local trigger = fibaro:getSourceTrigger() local variables = {} local variablesASupprimer ={} -- creation de ou des VG avec la variable GestionVG if (trigger['type'] == 'global') then fibaro:debug('Global variable source = ' .. trigger['name']) variables = json.decode((fibaro:getGlobal('GestionVG'))); if variables == nil then fibaro:abort() end -- creation de ou des VG manuellement ou par une autre scène ou un appel API elseif (trigger['type'] == 'other') then fibaro:debug('Global variable source = ' .. 'Other source.') variables = { {nom = "GestionVG", valeur = ""}, -- Gestion de VG -- Ex : Variable Globale predefini avec valeur1 pour valeur par default {nom = "Test1", valeur = "Valeur1", choix = {"Valeur2", "Valeur3"}}, -- Ex : Variable Globale qui à pour valeur 0 {nom = "Test2", valeur = "0"}, } variablesASupprimer = { {nom = "Test1"}, {nom = "Test2"} } end ------------------------------------------------- ---- Merci a STEVEN pour ce code -- ----------------------------------------------- -- Supprime une variable -- ----------------------------------------------- function supprimer(nom) local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables/"..nom, { options = { method = 'DELETE' } , success = function(response) fibaro:debug(nom .. " supprimée avec succès") end, error = function(response) fibaro:debug(nom .. " ERROR !!!") end, }) end -- ----------------------------------------------- -- Modifie une variable -- ----------------------------------------------- function modifier(nom, valeur, choix) local variable = {} variable.value = valeur variable.isEnum = false if (type(choix) ~= "nil") then variable.isEnum = true table.insert(choix, 1, valeur) variable.enumValues = choix end local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables/"..nom, { options = { method = 'PUT', data = json.encode(variable) }, success = function(response) fibaro:debug(nom .. " modifiée avec succès") end, error = function(response) fibaro:debug(nom .. " ERROR !!!") end, }) end -- ----------------------------------------------- -- Ajoute une variable -- ----------------------------------------------- function ajouter(nom, valeur, choix) local enum = 0 if (type(choix) ~= "nil") then enum = 1 end local http = net.HTTPClient() http:request("http://127.0.0.1:11111/api/globalVariables", { options = { method = "POST", data = json.encode({name=nom, isEnum=enum}) }, success = function(response) fibaro:debug(nom .. " créé avec succès") modifier(nom, valeur, choix) end, error = function(response) fibaro:debug(nom .. " ERROR !!!") end, }) end -- ----------------------------------------------- -- Voir si une variable existe ou non -- et la modifier ou créer -- ----------------------------------------------- function traiter(nom, valeur, choix) if (fibaro:getGlobalValue(nom) == nil) then ajouter(nom, valeur, choix) else -- modifier(nom, valeur, choix) end end ---------------------------------------------------- -- Execution du programme ---------------------------------------------------- for _,v in ipairs(variables) do traiter(v.nom, v.valeur, v.choix) end for _,v in ipairs(variablesASupprimer) do supprimer(v.nom) end Dans un premier temps il va falloir exécuter le script manuellement afin qu'il crée la VG GestionVG cette VG va être utiliser pour crée les variables globale à partir de n'importe quel script Lua Exemple d'utilisation : Création d'une variables globales "Test2" avec la valeur 0 local variables = { {nom = "Test2", valeur = "0"}, } fibaro:setGlobal('GestionVG',json.encode(variables)) Création d'une variables globales prédéfinie "Test1" avec Valeur1 , Valeur2 et Valeur3, vValeur1 sera la valeur par défaut dans cette exemple local variables = { {nom = "Test1", valeur = "Valeur1", choix = {"Valeur2", "Valeur3"}}, } fibaro:setGlobal('GestionVG',json.encode(variables)) Création de plusieurs variable globales prédéfinie ou pas en une seul fois local variables = { {nom = "Test1", valeur = "Valeur1", choix = {"Valeur2", "Valeur3"}}, {nom = "Test2", valeur = "0"}, } fibaro:setGlobal('GestionVG',json.encode(variables)) Création et suppression de variables via la scéne il faut modifier le code suivant, la méthode est la même que les exemples si dessus. Lors de l'exécution de la scene en mode manuel les variables seront créés si elle n'existe pas. elseif (trigger['type'] == 'other') then fibaro:debug('Global variable source = ' .. 'Other source.') variables = { {nom = "GestionVG", valeur = ""}, -- Gestion de VG -- Ex : Variable Globale predefini avec valeur1 pour valeur par default {nom = "Test1", valeur = "Valeur1", choix = {"Valeur2", "Valeur3"}}, -- Ex : Variable Globale qui à pour valeur 0 {nom = "Test2", valeur = "0"}, } variablesASupprimer = { {nom = "Test1"}, {nom = "Test2"}, } Ce code est fonctionnel chez moi, par manque de temps je ne pourrais vous aidez si vous avez des soucis de compréhension sur la création des VG ou leurs suppression
  9. 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
  10. Voici un périphérique virtuel qui a pour utilité de détecter et de notifier un utilisateur lorsqu’une nouvelle mise à jour est disponible en téléchargement pour le HC2 de Fibaro. (Publié sur le blog de Pascal le 21-03-2014) Version 1.0.8 – Mise à jour : 13/01/2015 Vous pouvez télécharger la dernière version ici et sur le blog consulter la notice d'installation et d'utilisation bien que tout soit simplifié au maximum Version 1.0.8 – Mise à jour : 13/01/2015 (Pour HC2 >= V4.031) Aucunes configuration nécessaire dorénavant, il faut importer le vd et c'est tout. Compatible API REST de la V4 L'unique paramétrage restant à faire par l'utilisateur est de préciser dans le code (dans le mainloop) l' ID du smartphone et de l' utilisateur pour les notifications. local userID = 2; local smartphoneID = 844; Version 1.0.6 – Mise à jour : 08/09/2014 (Pour HC2 <= V3.600) L'image principale du Virtual Device réapparaît maintenant automatiquement après l'appui sur un bouton Notification de mise à jour disponible sur la home du périphérique virtual. Remise en forme et révision du code Version 1.0.5 – Mise à jour : 04/09/2014 Amélioration: Récupération automatique de la variable en cas de données corrompues (suggéré par Lazer) Mise à jour des traductions Version 1.0.4 – Mise à jour : 03/09/2014 Nouveau: Affichage du numéro de version dans l'interface utilisateur et ajouté à la notification (mail & push) Nouveau: Icône d'un membre du forum domotique-fibaro.fr, merci Lazer Amélioration: Envoyer une notification si une nouvelle mise à jour est détectée et ne pas répéter les envois. Corrections mineures. Version 1.0.2 – Mise à jour : 21/02/2014 Corrections mineures.Version 1.0.1 – Mise à jour : 14/02/2014 Installation automatisée pour faciliter la mise en place des variables globales et du paramétrage de l’application. Possibilité de choisir le type de notification avec un bouton à trois états depuis l’interface graphique: Email, Push ou les deux. Possibilité de choisir le type de mise à jour devant être notifié avec un bouton à trois états depuis l’interface graphique : Bêta, stable ou les deux. Multilingue : Français, Anglais. Téléchargements: UpdateNotifier_v1.0.6.zip pour HC2 en V3.xxx UpdateNotifier_1.0.8.zip pour HC2 en V4.xxx
  11. Clé Usb Recovery Explication en image de la FAT32 Je vais vous expliquer ce que contient la partition FAT32 de la clé USB Recovery Je précise que ni moi ni le forum de peux être tenu responsable en car d'une mauvaise utilisation de ce TUTO Je ne ferai aucun support sur ce tuto 1 - Il faut eteindre ca box FIBARO via le bouton. 2 - Retirer la clé USB Recovery de la box (je passe le démontage des plaques pour y avoir accés ) 3 - Brancher la clé USB Recovery sur un PC Windows (Pour mac je sais pas si il lit les fat32) 4 - Accéder à la clé USB Recovery via l'explorateur de fichier Windows 5 - Voici ce que vous allez voir : 3 Répertoires et 1 Fichier le fichier network.conf contient la configuration réseau de votre HC2 Passons au répertoire Backups On retrouve ici toutes nos sauvegardes Regardons d'un peu plus prêt une sauvegarde On y trouve 4 fichiers et un dossier scenes checksum = Il contient le numero MD5 pour la vérification de la sauvegarde Info = fichier contenant les infos de la sauvegarde (date, heures, nombres de pièce etc...) sql = base de données sql Regardons de plus prêt le dossier scenes dans le dossier on retrouve tout les scripts de nos scènes ainsi qu'un fichier html par scéne Passons au répertoire log Ce répertoire est vide Le répertoire system checksum : stock le MD5 de l'image (image.gz) image.gz : c'est l'image qui sera restauré lors d'un recovey les fichiers version3 et version4 sont vide Mettre a jour l'image qui sert au recovery Pour cela il suffit de télécharger l'une des images partager par @jojo est de copier les fichiers dans le dossier system https://drive.google.com/drive/folders/0B1AXBMQhZAKAWlpsWk1FTEhlMHM Donc on s' aperçoit qu'il n'est pas très compliquer de faire une copie de ces sauvegardes sur notre PC Pour ceux qui aurait l'idée de modifier la base sql, il faudra recalculer le MD5, mais je dé-conseil de faire cela car en cas d'erreur c'est recovery obligatoirement
  12. 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
  13. Tuto HC2

    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
  14. VERIFICATEUR D'ID Très souvent, trop souvent, notre HC2 plante car nous utilisons des IDs (identifiants) qui n'existent pas/plus. Ces identifiants ont tendance à changer lors : d'une mise à jour de la box de la reconfiguration d'un device Parfois, même un simple changement de pile Bref, il est difficile de contrôler périodiquement tous nos scènarios, VD, ... Voici donc un scénario qui va "tenter" de faire cette vérification pour vous. Ce scénario N'EST PAS intelligent, il analyse votre code sans le comprendre et vous affiche des éléments qui méritent d'être vérifiés. Ce scénario peut vous envoyer un push en cas d'avertissement rencontré, peux tourner à intervalle régulier et vous envoyer un rapport par email. Lorsque ce scénario rencontre quelque chose d'étrange, il vous affiche la ligne suivante : [DEBUG] 09:57:24: checking scene : [425] Graphs pull [DEBUG] 09:57:24: code --> contient une référence erronée dans fibaro:call(81, "pressButton", "1") [ignored = {id=425, field="81"}] Vous allez donc vérifier le code de votre scène (Graphs pull) dans cet exemple. Si effectivement l'ID n'existe plus, il vous suffit de corriger votre code. Inversement, si cet avertissement n'a pas de sens, il vous suffit de copier le code commencant par ignored [ignored = {id=425, field="81"}] situé en fin de ligne et de le copier entre les deux lignes suivantes local ignored = { -- {id=425, field="81"}, -- Graph pull - Ligne en commentaire } Ainsi cette scène ignorera cet avertissement pour les prochaines fois. Cette scène nécessite un petit effort de mise en place mais permet de corriger et prévenir des erreurs d'ID qui peuvent être désagréable. Courage et n'hésitez pas si vous avez des questions. Ci-joint la scène en question et l'icone créé par @sebcbien. Historique : 1.0 -> Initialisaton 2.0 -> vérifie ou non les scènes et VDs désactivés (voir local checkDisabled = false) 2.0 -> corrige l'analyse de l'entête des scènes (du mois, je crois) 2.0 -> permet d'ignorer certaines erreurs (voir local ignored = {}) 2.1 -> optimisation du code 2.2 -> lors de la recherche de la valeur d'une variable, prend en compte la position dans le code 2.3 -> Vérifie les variables courantes : "id", "deviceid", ... (voir local mostUseVariables = {}) 3.0 -> Auto-détection de GEA 3.1 -> Ignore les warnings liés à cette propre scène 3.2 -> Autostart et envoi de push + notification en cas de problème 3.3 -> Envoi de mail + relancement automatique toutes les X heures 3.4 -> Mise à disposition des utilisateurs 3.5 -> Affichage du nom du bouton en cas d'avertissement 3.6 -> Ne confond plus les variables contenant caractères et chiffres (Windows5, Radiateur_4) avec des IDs de module 3.6 -> Ne confond plus le numéro du CentralSceneEvent avec un ID de module CheckAll_v3.6.lua
  15. Tuto HC2

    Notification Center Le centre de notifications à pour objectif de centraliser au mieux les besoins en communication en mettant à disposition une interface (lua) permettant d’accéder à divers services (HC2 Push & Mail, Pushover, passerelle personnalisée etc.) afin de pousser des messages dynamiques et informations diverses vers l’ extérieur. Version: 1.0.1 Phase du projet : Bêta Actuellement « Notification Center » est capable de gérer de manière automatique des demandes de notifications (concurrentes ou non) en utilisant les services suivants : HC2 Push (Mobile ID) HC2 Email (User ID) Pushover: Simple Notifications for Android, iOS, and Desktop (https://pushover.net/) Pushingbox (http://www.pushingbox.com) Prowl (http://www.prowlapp.com/) En cours d' intégration: Passerelle personnalisée (Ex : script php free sms, etc.) LiveNotifier (http://www.livenotifier.net) Roadmap: SMS Gateway & PAW Notification XBMC (Popup) TTS (support tiers) Messages prédéfinis (avec "template" ou non) Périphérique virtuel avec retour visuel : Nombre d’envois (Jours/mois), état du moteur de notification etc. Table de correspondance Mobile ID / User ID <-> Périphérique / Utilisateur par réflexion de l’API Panic Mode: routage automatique de tous les messages (prioritaires) vers une passerelle GSM (PAW, SMS Gateway) en cas de défaillance de fourniture Internet (ADSL/Fibre/Etc) En cours d'enrichissement...
  16. Bonjour Pour mon premier tuto, je vous propose un Module Virtuel pour interfacer la Livebox d'Orange et je vais vous détailler la mise en Å“uvre de l'intégration avec la HC2. Le module rassemble les informations importantes sur l'état des interfaces, le débit, les statistiques et les différents compteurs d'erreurs. Il permet aussi d'exécuter des commandes simples comme l'activation du Wifi ou le redémarrage de la Livebox. Prérequis Une Livebox 2 (Sagem) DSL note: pas pu tester la fibre. J'aimerais bien mais dans moin coin c'est pas avant 2022 ). Une HC2 (code lua testé avec v3.600 et v4.031) Installation Télécharger et ajouter le VD (lien en bas de post) Sur la page de configuration du module, saisir l'adresse ip et le port (80) de la Livebox Ensuite, il faut paramtètrer le VD, editez le code en debut de page (pour chaque bouttons): -- Nom d'utilisateur et mot de passe de la livebox local USER ="admin" local PASSWORD = "admin" Le VD retourne trois états possibles: Inconnu, OK et Not OK. Editez les variables pour adapter l'ID des icones: -- ID des icônes icon_ok = 1004 icon_nok = 1005 icon_unknown = 1006 Par défault, l'execution du module toutes les 5 minutes est confié à la mainloop du VD qui simule un appui sur le bouton Rafraichir. Simple, mais pour plus de fléxibilité et surtout de plus stabilté je recommande d'utiliser l'excellent GEA avec la ligne ci-dessous (à adapter). Dans ce cas, noubliez pas de supprimer le code dans le mainloop du VD. -- Mise à jour état connexion Internet GEA.add(true , 5*60, "",{{"VirtualDevice", id["VD_LIVEBOX"], "1"},{"VirtualDevice", id["VD_LIVEBOX"], "7"},{"Repeat"}}) Le VD n'utilise pas de Variable Globale car je n'ai pas de scénario qui necessite un retour sur l'état de la connexion internet mais c'est juste une ligne de code à ajouter: fibaro:setGlobal('test', Livebox.WANStatus.LinkState) Comment ca marche ? c'est la section pour les geeks. Je partage ici le resultat de mes bidouilles (et saut d'humeur) à propos de l'API Livebox Fonctionnement de l'API Orange/Sagem: En regardant d'un peu plus près les paquets échangés dans une session d'admin avec la livebox on peut voir des réponses de POST en json . à‡a commence plutôt pas mal, la livebox a donc une API ! Comme souvent avec Orange, ça commence bien, c'est après que les choses se gâtent ! Impossible de mettre la main sur une doc publique de l'API. En fouillant un peu sur les forums d'Orange j'ai trouvé quelques pistes mais mes vrais amis ont été Wireshark et les dev tools InternetExplorer ou Chrome (F12) pour comprendre un peu comment l'appli mobile d'Orange (version IOS) utilisait l'API… En inspectant le déroulé d'un login, je manque de m'étrangler en constatant que le nom d'utilisateur et le mot de passe sont balancés en clair; ben voyons les gars faut pas se gêner hein… la requête login retourne un "ContextID" qui est utilisé comme identifiant pour les appels aux fonctions de l'API (X-Context dans les headers). Donc au menu nous avons des custom headers et une authentification super basique, fastoche! où est le problème? Bah ça marche pô! - > "permission denied" le voilà le problème Bah surement qu'ils ont été pris de remords chez Orange avec cette authentification de mickey avec password en clair et histoire de faire bonne figure (et pas se faire défoncer tous les mercredi par des pré-ados qui voudraient passer outre le contrôle parental) ils ont semble-t-il cherché à compliquer un peu les choses… mais en faisant du gros n'importe quoi! Pour aller à l'enssentiel, en plus d'un ContextID, le Login renvoie une autre clé mais planquée dans un cookie cette fois. La sécurité n'y a pas gagné grand chose mais en revanche c'est une vraie prise de tête à intégrer sur la hc2. Hmm.. Net.FHttp avec des custom headers et un cookie, ça va pas le faire… Pour contourner le problème et récupérer le cookie, je me suis servi du génialissime ToolKit v1.0.4 de Krikroff. Une toute petite modif de 4 lignes dans httpClient:request et nous voila prêts à nous goinfrer de cookies. J'ai modifié (à l'arrache, sorry Krikroff) la fonction request(...) dans le fichier Toolkit.net.lua (commence ligne 165). on cherche la chaine "cookie" dans les response headers renvoyés par le serveur et le cas échéant on extrait avec un string.sub() en partant du douzième char. la fonction retourne le cookie en plus des classiques response, status et err. request = (function(self, method, uri, headers, body) ... for k, v in pairs(__headers) do --Toolkit.Net.__trace("raw #"..k..":"..v) if (string.find(string.lower( v or ""), "chunked")) then self.__isChunked = true; Toolkit.Net.__trace("%s.%s::receive > Transfer-Encoding: chunked", Toolkit.Net.__header, Toolkit.Net.__Http.__header, string.len(result)); -- Modification pour récupérer le cookie. Ofwood Janvier 2015 elseif (string.find(string.lower( v or ""), "cookie")) then cookie = string.sub(v, 12) Toolkit.Net.__trace("%s.%s::receive > Cookie: %s", Toolkit.Net.__header, Toolkit.Net.__Http.__header, cookie); end end ... -- return budy response & cookie return response, status, err, cookie; Voyons maintenant avec un exemple comment tirer profit de cette modification et mangeons des cookies! La fonction login() authentifie l'utilisateur et retourne le contextID (dans la réponse json) et le cookie associé. function login() local httpClient = Toolkit.Net.HttpRequest(ip, port) httpClient:setReadTimeout(Livebox.commandTimeOut) local uri = string.format("/authenticate?username=%s&password=%s", utilisateur, mot_de_passe) local response, status, errorCode, cookie = httpClient:request("POST", uri, {"User-Agent: FibaroHC2/1.0", "Content-Type: application/json"}, "" ) if (errorCode == 0) and tonumber(status) == 200 then local jsonTable = json.decode(response); ContextID = jsonTable.data.contextID; return ContextID, cookie end end l'exemple suivant utilise le contextID et notre cookie pour une requête (l'état de l'interface WAN sur la LiveBox) function getWANStatus(contextID, cookie) local httpClient = Toolkit.Net.HttpRequest(ip, port) httpClient:setReadTimeout(Livebox.commandTimeOut) local uri = "/sysbus/NMC:getWANStatus" local params = [[ {"parameters":{}} ]]; -- Injection de X-Context et du Cookie dans les headers local response, status, errorCode, cookie = httpClient:request("POST", uri, {"User-Agent: FibaroHC2/1.0", "Content-Type: application/json", "X-Context: "..contextID, "Cookie: "..cookie }, params); if (errorCode == 0) and (status == 200) then local jsonTable = json.decode(response) Return jsonTable.result.data end end Voici la liste des fonctions implémentées dans la version 1.0 du module. Il en existe d'autres, je n'ai pas encore tout recensé. Livebox.login() Authentification session utilisateur Livebox.logout() Fermeture session Livebox.listTrunks() Information téléphonie IP Livebox.getIPTVStatus() Etat IP TV Livebox.getDSLStats() Stats DSL (Erreurs) Livebox.getMIBs() Information lien dsl Livebox.getWifiMIBs() Information Wifi Livebox.getWANStatus() Etat de la connexion WAN Livebox.reboot() Redémarrage la livebox Livebox.setwifi(mode) Active/désactive le Wifi Livebox.filtreMAC(flag) Active/Désactive filtrage MAC address Livebox.getWificomStatus() Information Wifi public Orange Voilà , ça donne l'idée générale et Orange n'ayant pas le monopole sur les APIs bien pourries, je me suis dit que ça pourrait peut-être en aider d'autres qui se prennent la tête sur des intégrations nécessitant le support des cookies. Enjoy! merci pour vos retours (et votre indulgence) Historique 13/01/2015 - v1.0 : version initiale Livebox_VD.zip
  17. Hello Faisant suite au VD de Krikroff avec Waze, je me suis dit que cela sera sympa d'avoir un VD 'info trafic transport' J'ai donc regarder les api de dispo J'ai trouvé un API d'un mec bien sympa qui récupère les infos RATP (Metro et RER partie RATP) Avec mes très faibles connaissances, j'ai donc bricolé un petit VD pour récupérer l’état du trafic et aussi l'horaire d'un prochain train ... (merci à Lazer également) à‡a doit être très perfectible, donc si vous avez des idées d’optimisation, en ce jours de HC2 surchargé c'est toujours bien de partager :-) C'est pas un VD "universel", dans le sens ou vous allez avoir besoin de modifier 2/3 choses dans le code pour l'adapter à vos stations/lignes habituelles. si vraiment il y a un besoin, on pourrait faire quelque chose de plus propre. Avec l’état du trafic je push des nofifs avec GEA, on pourrait aussi le mettre ce push dans le main loop avec un sleep. Dans mon cas perso, je remonte l’état du RER A et du metro1 et je push toutes les 15Mn l’état trafic du RER si trafic perturbé Je remonte aussi l'horaire temps réel du prochain RER, qui part de la Défense à destination de la maison :-) Avant d'importer le VD, vous allez devoir créer un variable : EtatTrafic , sans valeur particulière. Dans le code il faut modifier : 1/les IDs de vos icônes (merci à Did) local TraficOk = 1121 local TraficNok = 1122 2/pour la partie RER, si vous voulez le A mettre un 1 si vous voulez le B un 2 local LineRer = jsonTable.response.rers[1].line local EtatRer = jsonTable.response.rers[1].title local EtatLongRer = jsonTable.response.rers[1].message 3/pour le metro, idem suivant votre ligne 1,2 etc... local LineMetro = jsonTable.response.metros[1].line local EtatMetro = jsonTable.response.metros[1].title si vous voulez faire un push plutôt sur le métro que sur le RER, suffit de remplacer la ligne local EtatLongRer = jsonTable.response.rers[1].message par local EtatLongRer = jsonTable.response.metros[1].message avec bien sur le paramètre [1] qui vous correspond et aussi d'ajuster les labels ... (je pourrais aider si besoin c'est pas compliqué) 3/Pour la partie horaire un poil plus compliqué (faudrait créer des variables locales pour faire plus simple ...) mais grosso modo allez ici http://api-ratp.pierre-grimaud.fr/v2/rers/a ou ici http://api-ratp.pierre-grimaud.fr/v2/metros/1 en modifiant bien sur le N° de la ligne qui vous intéresse. et récupérer le 'slug' de votre ligne et la destination et modifier l'appel API en conséquence local response ,status, err = TRAFIC:GET("/v2/rers/a/stations/grande+arche+la+defense?destination=st+germain+en+laye+poissy+cergy") ensuite la boucle for i=1, Max do if jsonTable.response.schedules[i].destination == "Poissy" then ProchainRer = jsonTable.response.schedules[i].message break elseif jsonTable.response.schedules[i].destination == "Cergy-Le Haut" then ProchainRer = jsonTable.response.schedules[i].message break else ProchainRer = 0 end end est pour mon cas particulier car j'ai 2 possibilités de desitnations pour rentrer. A adapter suivant vos cas. Ensuite je rafraichi le VD et push l'état du trafic avec GEA -- Push Trafic GEA.add(true, 2*60, "", {{"VirtualDevice", id["ETAT_TRAFIC"], 1},{"Repeat"}}) -- Refresh toutes les 2mn l'etat du trafi GEA.add ({"Global!", "EtatTrafic", "OK"}, 15*60, "#value#",{{"Repeat"}}) -- Push Etat toutes les 15mn si NOK Voilà en gros, je suis désolé c'est pas plug en play, mais c'est pas très compliqué à modifier, car moi même j'ai réussi lol Si il y a un intérêt plus important, je pourrai regarder pour faire quelque chose de plus facile à intégrer chez vous. J'essai de regarder maintenant la partie TRANSCILIEN, ça fonctionne de la même façon avec l'API Transicilien, sauf que je récupérer un XML et pas un JSON, donc je sais pas trop comment le lire ... idem si intérêt, on peut regarder ensemble. Etat_Trafic.vfib
  18. Bonjour, Sur le post du script pour le contrôle du niveau des piles j'ai abordé le sujet nÅ“uds morts pour les détecter et voici un script tip top qui/ - Contrôle les nÅ“uds morts, - Chercher a les réveiller, - Envoie des notifications pour avertir --[[ %% autostart %% properties %% globals --]] local sourceTrigger = fibaro:getSourceTrigger(); if (sourceTrigger["type"] == "autostart") then while true do local currentDate = os.date("*t"); local startSource = fibaro:getSourceTrigger(); if ( ( (tonumber(os.date("%H%M")) >= tonumber(string.format("%02d%02d", "07", "00")) and tonumber(os.date("%H%M")) <= tonumber(string.format("%02d%02d", "23", "00"))) and (math.floor(os.time()/60)-math.floor(1369026000/60))%2 == 0 ) ) then local i = 1 local TotalDevices = 156 + 1 while i < TotalDevices do local status = fibaro:getValue(i, 'dead'); if status == "1" then fibaro:setGlobal('lastDeadNode', i); -- fibaro:call(30, "pressButton", "6"); fibaro:call(1, "wakeUpDeadDevice",i); fibaro:debug("Try to wake up node "..i); fibaro:call(68, "sendPush", "Try to wake up node "..i); fibaro:sleep(5*1000); local status = fibaro:getValue(i, 'dead'); if status == "1" then fibaro:debug("Device "..i.." still dead"); fibaro:call(68, "sendPush", "Device "..i.." still dead"); -- fibaro:call(30, "pressButton", "6"); -- fibaro:call(65, "sendDefinedPushNotification", "9"); -- fibaro:call(2, "sendEmail", "DEAD "..i); else -- fibaro:call(30, "pressButton", "7"); fibaro:debug("Device "..i.." fixed"); fibaro:call(68, "sendPush", "Device "..i.." fixed"); end else end i = i + 1 end end fibaro:sleep(60*1000); end else local currentDate = os.date("*t"); local startSource = fibaro:getSourceTrigger(); if ( startSource["type"] == "other" ) then fibaro:debug("send notification"); fibaro:call(68, "sendPush", "start check dead node"); local i = 1 local TotalDevices = 156 + 1 while i < TotalDevices do local status = fibaro:getValue(i, 'dead'); if status == "1" then fibaro:setGlobal('lastDeadNode', i); -- fibaro:call(30, "pressButton", "6"); fibaro:call(1, "wakeUpDeadDevice",i); fibaro:debug("Try to wake up node "..i); fibaro:call(68, "sendPush", "Try to wake up node "..i); fibaro:sleep(5*1000); local status = fibaro:getValue(i, 'dead'); if status == "1" then fibaro:debug("Device "..i.." still dead"); fibaro:call(68, "sendPush", "Device "..i.." still dead"); -- fibaro:call(30, "pressButton", "6"); -- fibaro:call(65, "sendDefinedPushNotification", "9"); -- fibaro:call(2, "sendEmail", "DEAD "..i); else -- fibaro:call(30, "pressButton", "7"); fibaro:debug("Device "..i.." fixed"); fibaro:call(68, "sendPush", "Device "..i.." fixed"); end else end i = i + 1 end end end Voici le script,son auteur est Olivier MALE. Il faut l'adapter pour le N° d'ID pour le push. Son auteur a aussi mis des "--" devant certaines lignes de notifications push et de virtual device, perso j'ai supprimé ces lignes. Le script fonctionne nickel chez moi.
  19. Faire un RECOVERY en moins de 30 mn By MPRInfo Tout en Image Comment on passe la box en mode recovery ? (éteindre la box, puis appuyer sur les deux boutons simultanément) Petite précision avant de commencer : J'ai modifié l'image recovery sur ma clef usb, j'ai aussi modifié la taille de la partition fat32 de ma clef recovery de 8go Donc lors de ce recovery je ne vais donc pas passer par la 3.60 mais directement en 4.031 Cela ne change rien au principe pour les box anciennes comme la mienne il faudra passer par la V3 je suis donc en 4.031 pour ceux qui on une image recovery ancienne on doit arrivé en 3.60 si mais souvenir sont bon il faut donc faire la mise a jours pour passer en V4 On passe ensuite en 4.054 Stable On accepte de prendre pleins des risque sans rien dire ou râler Après acceptation il faut parfois re saisir l'adresse de la box pour avoir l'image suivante On ferme le navigateur est on vide le cache comme a chaque mise à jours Ensuite si on veut on peut installer la 4.055B la procédure est la même On oublie pas de nouveau a vider le cache du navigateur une fois la mise a jour faite On ferme le navigateur est on vide le cache comme a chaque mise à jours Pour la clef ou j'ai augmenté la taille voici un aperçu : Liens utiles : Images Clé Usb : https://www.domotique-fibaro.fr/topic/6824-images-clã©-usb/ Clé Usb Recovery Explication En Image De La Fat32 : https://www.domotique-fibaro.fr/topic/5534-clé-usb-recovery-explication-en-image-de-la-fat32/ The END
  20. Pluviométrie Avec WeatherUnderground Bonjour, Sur une idée originale de Steven, qui remonte les données d'un pluviomètre Netatmo et récupère les previsions depuis le site de WU, j'ai crée ce VD qui permet de s'affranchir de l'achat d'un pluviomètre et de faire appel uniquement à WU pour récupérer les précipitations (de la dernière heure, du jour, d'hier, des 5 derniers jours et des 10 derniers jours) d'une station WU proche de chez vous; Suite à ca on fait un rapide calcul (à affiner selon vos besoins) pour mettre à jour une variable globale. (credit Steven aussi - je n'ai pas encore affiner ce calcul avec les datas que je remonte - ca sera une V2) Cette variable sert ensuite chez moi à déclencher l'arrosage automatique. HC2 en V4 (et 3.6 après le test de Jojo) 1ère étape - Creation des clefs WU à l'adresse ici Pour crée un compte : http://www.wundergro...pi/d/login.html Pour trouver sa "station ID" : http://www.wundergro...dCountry=France La création du compte va vous permettre d'obtenir une "cle api" Et la recherche de la station la plus proche de chez vous, une station ID (attention à bien choisir une station qui mesure à les precipitations .. ;-) Important Les clés gratuites permettent 500 appels par jour et 10appels par minutes. Dans le VD vous avez 4 boutons - Today qui fait 1 appel - Last Days, qui fait 10 appels - Next 2 days, qui fait 1 appel il faut donc faire attention à vos clicks :-) si vous dépasser la limite, c'est le carton jaune, au bout de 3 carton jaune, c'est le rouge et la clé est HS. (Perso ce que j'ai fait c'est créer une clé pour les 10jours. et une autre pour les 2 autres boutons, et j'utilise GEA pour cliquer à intervalle régulier sur les boutons, sans dépasser les 500 appels jours / clef.) -- Arrosage GEA.add(true, 10*60, "", {{"VirtualDevice", id["CALCUL_ARROSAGE"], 2},{"Repeat"}}) -- Historique Pluie du Jour et derniere heure GEA.add(true, 30, "", {{"Time", "02:06", "02:07"},{"VirtualDevice", id["CALCUL_ARROSAGE"], 5}}) -- Historique Pluie jusqu'à 10jours GEA.add(true, 10*60, "", {{"VirtualDevice", id["CALCUL_ARROSAGE"], 9},{"Repeat"}}) -- Prévisions à 2 jours ce qui donne 300 appels par jour et max 10appels /mn - donc ok pour 1clef, sauf si l'appel 10jours passe la meme minutes qu'un autre appel ... Pour ceux qui n'ont pas GEA, voici ce que vous pouvez mettre dans le main loop (j'ai pas testé donc merci pour vos retours si ça fonctionne pas) while true do local Var_Heure = os.date("%H:%M") local Var_Min = os.date("%M") --fibaro:debug("heure OS : " ..Var_Heure) if Var_Heure == "02:06" then fibaro:call(fibaro:getSelfId(), "pressButton", "5") fibaro:debug("heure OS : " ..Var_Heure .."Historique des derniers jours récupéré") end if Var_Min =="00" or Var_Min == "15" or Var_Min == "30" or Var_Min == "45" then fibaro:call(fibaro:getSelfId(), "pressButton", "2") fibaro:debug("heure OS : " ..Var_Heure .."Historique du jour récupéré") fibaro:call(fibaro:getSelfId(), "pressButton", "9") fibaro:debug("heure OS : " ..Var_Heure .."Prévisions récupérées") end fibaro:sleep(60*1000) -- sleep 1 min end 2eme étape - Importer le VD - Modifier la clé (ou les clefs) API et la Station ID dans tous les boutons (sauf calcul) - Modifier l'id de votre smartphone dans le bouton calcul arrosage - Modifier les ID de vos icones dans la bouton calcul arrosage 3eme étape - Créer une variable "Arrosage" avec 3 valeurs Non, Leger, Important J'utilise les icônes de Couillerot merci à lui. Merci. Mon 1er VD partagé sur le forum. En remerciement pour tout ce que je prends/deja pris et ce que j'apprends ! V.1.0 V.1.1: optimisation sur conseil de jojo V.1.2: integration des icônes en fonction de l'arrosage nécessaire (toujours sur idée de jojo) V.1.3: meilleure gestion des appels et 1clé WU peut suffire V.1.4: fine tuning V.1.5: optimisation des appels historiques sur 1 bouton (merci jojo) -- 15 Mai 2015 -- V2.1 : ici Calcul_Arrosage V1.5.vfib
  21. Faire une copie de la clef usb RECOVERY sous windows Ceci est un complément a ce tuto : http://www.domotique-fibaro.fr/index.php/topic/2364-hc2-usb-recovery-tweaks/ !!! Attention !!! ce tuto n'est pas sans risque si vous ne le suivez pas a la lettre vous risquez de corrompre votre clef USB RECOVERY Il faut télécharger : Win32 Disk Imager : http://sourceforge.net/projects/win32diskimager/ HashMyFiles v2.11 : http://www.nirsoft.net/utils/hash_my_files.html Il faut éteindre la box Retirer la clef USB Recovery pour cela il faut dévissé les 4 vis pour et retirer le cache afin d'avoir accès a la clef Brancher la clef USB RECOVERY sur votre PC Installer Win32 Disk Imager sur votre PC Voici un aperçu des partitions de la clef Lancer Win32 Disk Imager ATTENTION bien cliquer sur READ sinon on risque de détruire la clef usb Notre clef USB et Cloner dans un fichier IMG. Nous allons récupérer le MD5 On copie cette clef MD5 dans un fichier TXT cela nous servira a vérifié si notre fichier IMG n'est pas corrompu lorsque l'on voudra la restaurer. La clef MD5 controler l'intégrité de notre sauvegarde. Cette clef ne changera pas temps que l'on ne modifie pas notre sauvegarde voici un lien qui explique ce qu'est le MD5 : http://fr.wikipedia.org/wiki/MD5 Verification du fichier IMG avec le MD5 On vérifie que la clef MD5 et bien identique a la clef que l'on a copié dans le fichier TXT On copie les fichiers qui ce trouvent sur la partition Fat32 de notre clef USB recovery dans un répertoire de notre PC Répertoires : Backups (contient toutes nos sauvegardes) logs (ce répertoire est vide chez moi system (Contient l'image qui sera restauré lors d'un recovery) network.conf (le fichier contient seulement l'info permettant au réseau de fonctionner en DHCP lorsqu'on boot en recovery) Ce qui nous donne ceci : Avant de faire quoi que ce soit sur votre HC2 Solutions en cas de probléme : Contacter le support FIBARO (surtout si ils peuvent avoir accès à la box) Brancher un écran sur votre HC2 pour voir ce qui ce passent Je précise que le clonage de la clef ne peut normalement être utilisé sur une autre clef USB il faut absolument la clef USB RECOVERY fourni par fibaro
  22. Tuto HC2

    Bonjour à tous, Voici un petit tutoriel sur comment piloter son nas QNAP avec la HC2. Je ne suis pas dévelopeur LUA sous HC2 donc il y a surement moyen d'optimiser tout ça (notamment les variables login/pass). Les 3 exemples sont basés sur mes besoins actuels, j'arrête mon nas le soir avec l'armement de mon alarme et rallume avec le désarmement de mon alarme grace au WOL (plugin fibaro). Avec les nouvelles génération de nas X51, il est possible de lancer la commande sleep et non shutdown, ce qui permet au NAS d'être réveillé en 5 secondes (RAM sauvegardée) Configuration QNAP Vous devez autoriser la connexion sans SSL (la HC2 ne supporte pas le ssl) HC2 voici un exemple de quelques fonctions que j'ai utilisé pour commander mon NAS - arrêter le nas proprement - démarrer l'enregistrement des caméras de la station de surveillance - arrêter l'enregistrement des caméras de la station de surveillance si vous voulez obtenir l'API complet des fonctions des NAS qnap, envoyez un petit mail à developer@qnap.com (anglais) --> Je ne suis pas dévelopeur et/ou je ne veux pas comprendre Voici alors le virtuel device déjà prêt avec les 3 fonctions vous devez configurer l'IP et le port dans la configuration du virtuel device et adapter le login/pass dans le code des 3 boutons (remplacez LOGIN_NAS et PASSWORD_NAS) QNAP.vfib.zip --> Je suis dévelopeur et/ou je veux comprendre démarrer l'enregistrement: local ip_module = fibaro:get(fibaro:getSelfId(), "IPAddress") local port = fibaro:get(fibaro:getSelfId(), "TCPPort") surveillance_Station = Net.FHttp(ip_module, port) surveillance_Station:setBasicAuthentication("LOGIN_NAS", "PASSWORD_NAS") response = surveillance_Station:GET("/cgi-bin/mrec.cgi?ch=1&act=1") if (string.find(response, "OK")) then fibaro:log("Starting Recording") else fibaro:log("ERROR") end arrêter l'enregistrement local ip_module = fibaro:get(fibaro:getSelfId(), "IPAddress") local port = fibaro:get(fibaro:getSelfId(), "TCPPort") surveillance_Station = Net.FHttp(ip_module, port) surveillance_Station:setBasicAuthentication("LOGIN_NAS", "PASSWORD_NAS") response = surveillance_Station:GET("/cgi-bin/mrec.cgi?ch=1&act=0") if (string.find(response, "OK")) then fibaro:log("Stop Recording") else fibaro:log("ERROR") end la partie plus complexe qui nécessite un parseur XML, l'arret du NAS if (not QNAP) then QNAP = {} QNAP.qnap_ip = fibaro:get(fibaro:getSelfId(), "IPAddress"); QNAP.port = fibaro:get(fibaro:getSelfId(), "TCPPort"); QNAP.globalvariable = "" -- -------------------------------------------------------------------------------------------------------------- -- Obtient le XML et le retourne sous forme de table LUA -- -------------------------------------------------------------------------------------------------------------- QNAP.getTokenFromXml = function() local QNAP2URL = Net.FHttp(QNAP.qnap_ip,QNAP.port); response = QNAP2URL:GET("/cgi-bin/authLogin.cgi?user=LOGIN_NAS&plain_pwd=PASSWORD_NAS&remme=1"); xmlTable = QNAP.iif(response ~= nil, QNAP.newParser().ParseXmlText(response), ""); if (xmlTable.QDocRoot ~= nil) then qsidstr = xmlTable.QDocRoot.authSid:value(); if (string.len(qsidstr)>0) then fibaro:debug("Qtoken founded"); qsidstr = qsidstr:gsub("[".."<![CDATA[".."]", ''); qsidstr = qsidstr:gsub("[".."]".."]", ''); qsidstr = qsidstr:gsub("["..">".."]", ''); fibaro:debug(qsidstr); response = QNAP2URL:GET("/cgi-bin/sys/sysRequest.cgi?subfunc=power_mgmt&count=0.1234&sid="..qsidstr.."&apply=shutdown"); if (string.find(response, "OK")) then fibaro:log("Power Off Server") else fibaro:log("ERROR") end end end end -- ------------------------------------------------------------------------------------------------------------- -- Teste la condition et retourne la valeur true ou false -- ------------------------------------------------------------------------------------------------------------- QNAP.iif = function(condition, iftrue, iffalse) if (condition) then return iftrue end return iffalse end -- ------------------------------------------------------------------------------------------------------------- -- Ceci est une version modifiée par Steven de Corona-XML-Module par Jonathan Beebe qui a son tour -- est basée sur Alexander Makeev's Lua-only XML parser . -- see https://github.com/Cluain/Lua-Simple-XML-Parser -- ------------------------------------------------------------------------------------------------------------- QNAP.newParser = function() parseXml = {} parseXml.FromXmlString = function(value) value = string.gsub(value, "([%x]+)%;", function(h) return string.char(tonumber(h, 16)) end); value = string.gsub(value, "([0-9]+)%;", function(h) return string.char(tonumber(h, 10)) end); value = string.gsub(value, "'", "'"); value = string.gsub(value, ">", ">"); value = string.gsub(value, "<", "<"); value = string.gsub(value, "&", "&"); return value; end parseXml.ParseArgs = function(node, s) string.gsub(s, "(%w+)=([\"'])(.-)%2", function(w, _, a) node:addProperty(w, parseXml.FromXmlString(a)) end) end parseXml.ParseXmlText = function(xmlText) local stack = {} local top = parseXml.newNode() table.insert(stack, top) local ni, c, label, xarg, empty local i, j = 1, 1 while true do ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i) if not ni then break end local text = string.sub(xmlText, i, ni - 1); if not string.find(text, "^%s*$") then local lVal = (top:value() or "") .. parseXml.FromXmlString(text) stack[#stack]:setValue(lVal) end if empty == "/" then -- empty element tag local lNode = parseXml.newNode(label) parseXml.ParseArgs(lNode, xarg) top:addChild(lNode) elseif c == "" then -- start tag local lNode = parseXml.newNode(label) parseXml.ParseArgs(lNode, xarg) table.insert(stack, lNode) top = lNode else -- end tag local toclose = table.remove(stack) -- remove top top = stack[#stack] if #stack < 1 then error("XmlParser: nothing to close with " .. label) end if toclose:name() ~= label then error("XmlParser: trying to close " .. toclose.name .. " with " .. label) end top:addChild(toclose) end i = j + 1 end local text = string.sub(xmlText, i); if #stack > 1 then error("XmlParser: unclosed " .. stack[#stack]:name()) end return top end parseXml.newNode = function(name) local node = {} node.___value = nil node.___name = name node.___children = {} node.___props = {} function node:value() return self.___value end function node:setValue(val) self.___value = val end function node:name() return self.___name end function node:setName(name) self.___name = name end function node:children() return self.___children end function node:numChildren() return #self.___children end function node:addChild(child) if self[child:name()] ~= nil then if type(self[child:name()].name) == "function" then local tempTable = {} table.insert(tempTable, self[child:name()]) self[child:name()] = tempTable end table.insert(self[child:name()], child) else self[child:name()] = child end table.insert(self.___children, child) end function node:properties() return self.___props end function node:numProperties() return #self.___props end function node:addProperty(name, value) local lName = "@" .. name if self[lName] ~= nil then if type(self[lName]) == "string" then local tempTable = {} table.insert(tempTable, self[lName]) self[lName] = tempTable end table.insert(self[lName], value) else self[lName] = value end table.insert(self.___props, { name = name, value = self[name] }) end return node end return parseXml; end end QNAP.getTokenFromXml();
  23. Toutes lumières Ce module virtuel vérifie périodiquement l'état des modules lumière de la maison, et change d'icône en fonction de leur état (au moins une allumée, aucune allumée). Son bouton permet d'éteindre en un clic toutes les lumières de la maison. Contexte Je cherchais à savoir d'un coup d'oeil s'il restait une lumière allumée dans la maison, et à pouvoir y remédier sans chercher le module dans l'interface. Je prévoit également de me servir du bouton d'extinction généralisée de ce module virtuel dans d'autres modules virtuels ou scènes, afin de centraliser les bouts de code intéressants et d'éviter de les dupliquer, cela facilitera la maintenance. J'ai créé les icônes moi-même pour éviter tout problème de droits. Installation - Importez le module virtuel - Ajoutez les icônes fournies - Adaptez les Id d'icônes au début du code de la boucle principale - Si l'intervalle par défaut (10 secondes) ne vous convient pas, vous pouvez le modifier au début du code de la boucle principale Note : incompatible avec les systèmes inférieurs à 4.x Changelog 1.2 : Correction du test d'état prenant en charge les modules variateurs et rétablissement de la condition pour l'extinction 1.1 : Extinction inconditionnelle et prise en charge des modules variateurs Téléchargement Toutes_Lumières-1.2.vfib
  24. 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();
  25. 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