Aller au contenu

Rechercher dans la communauté

Affichage des résultats pour les étiquettes 'NetAtmo'.



Plus d’options de recherche

  • Rechercher par étiquettes

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

Type du contenu


Forums

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

Rechercher les résultats dans…

Rechercher les résultats qui…


Date de création

  • Début

    Fin


Dernière mise à jour

  • Début

    Fin


Filtrer par nombre de…

Inscription

  • Début

    Fin


Groupe


Jabber


Skype


Ville :


Intéret :


Version

11 résultats trouvés

  1. J3R3M

    [VD+Scène] Netatmo Welcome

    Bonjour à tous, Jusqu'à peu, j'utilisais uniquement des requêtes fing (ping) pour détecter les différents téléphones de mon téléphone et ainsi en déduire la présence de quelqu'un ou non à mon domicile. Seulement, ce n'était pas assez fiable et j'ai décidé de combiner cette solution à la Netatmo Welcome. Après quelques recherches, je suis tombé sur ce topic du site Siio (également et heureusement disponible en anglais ici). C'est exactement ce que je recherchais! Seulement, je l'ai modifié pour qu'il soit plus simple à à mettre en place et à utiliser au quotidien. Ainsi, il n'y a rien à faire à part modifier les variables vous concernant. Pour utiliser le script original, il faut créer deux Variables Globales par personne identifiée dans la base de données de la Welcome, ce que je ne trouve pas très ergonomique et lourd. Je précise qu'une très grande partie du script provient du lien précédent et je ne cherche pas à tirer la gloire de l'auteur original (BOOMX) de celui-ci malgré mes modifications. Je l'ai modifiée comme je le souhaitais et ai traduit les debugs. J'espère que cette scène vous sera utile et suis disponible pour répondre à vos éventuelles questions! Exemple d'utilisation Pour savoir si quelqu'un est présent d'après la Netatmo Welcome, il suffit d'utiliser un code comme-ci dans vos scènes et VD : local pseudo = "Jérémy"; local VGNetatmo = "NETATMO_Welcome"; local table = json.decode(fibaro:getGlobalValue(VGNetatmo)); local presence = tonumber(table[pseudo].status); if presence == 1 then fibaro:debug(pseudo.." est présent."); else fibaro:debug(pseudo.." est absent."); end Réglages de la Scène Netatmo Welcome Toutes les variables permettant de régler la scène sont au début de celle-ci. Après avoir saisi les bonnes informations, enregistrez et démarrez la scène manuellement. La scène est fonctionnelle ! NB : Ces paramètres étant envoyés via une requête HTTP, merci d'encoder les caractères spéciaux. Pour rappel : @ = %40 -- Informations de compte Netatmo local client_id = 'Client_id'; local client_secret = 'Client_secret'; local username = 'Netatmo_username'; local password = 'Netatmo_pass'; -- Informations du VD associé local vd_ID = 304; -- ID du VD associé local vd_refresh = 9; -- ID du bouton refresh du VD. 9 Par défaut -- Réglages de la scène local refresh = 10; -- Script executé toutes les x secondes. Pas moins de 8s! local debug = 0; -- Faut-il vraiment l'expliquer ? -- Nom de la Variable Globale qui sera créée et utilisée par la scène et le VD local VGNetatmo = "NETATMO_Welcome"; Trouver ses Client ID & Client Secret Pour obtenir vos client_id et client_secret, rendez-vous sur dev.netatmo.com et connectez-vous. Cliquez sur CREATE YOUR APP et remplissez rapidement le formulaire. Les informations saisies importent peu! Une fois que vous aurez validé en cliquant sur le bouton SAVE, d'autres fenêtres apparaîtront en-dessous. Celle qui nous intéresse et celle juste en-dessous. En effet, les informations Client id et Client secret sont dans la section Technical Parameters. Faites un copier/coller de ces informations dans les variables correspondantes et le tour est joué! J'ai tellement ramé à les trouver que je me devais de vous dire où ces informations étaient dissimulées! Limitations de l'API Netatmo En ce qui concerne la variable refresh, il s'agit du délai entre chaque mise à jour des informations par la scène. L'auteur explique très bien pourquoi il ne faut pas descendre en dessous des 8 secondes et je vais me contenter de traduire son explication. VD Netatmo Welcome Pour personnaliser celui-ci, rendez-vous au début du code du bouton refresh : -- Les pseudos doivent être exactement les mêmes que dans l'application Netatmo, séparés par une virgule local pseudos = {"Jérémy","Emilie","Maman"}; -- Nombre de personnes à afficher dans le VD -- Si modification, conserver la même structure de VD ! -- Et penser à modifier la variable "vd_refresh" de la scène Netatmo local NbPersonnes = 3; -- Variable Globale local VGNetatmo = "NETATMO_Welcome"; Si vous souhaitez conserver seulement les informations de 3 personnes, il vous suffit de modifier uniquement les valeurs de la variable pseudos. Attention, les pseudos doivent être rigoureusement les mêmes que ceux enregistrés dans Netatmo! Si vous souhaitez afficher plus de 3 personnes, conservez obligatoirement la même structure du VD, c'est-à-dire en ajoutant 3 étiquettes dont les IDs seront incrémentés de +1 pour chaque nouvelle personne. Pour information, le VD d'origine est beaucoup moins optimisé puisque vous devez modifier tout le code du bouton pour qu'il soit fonctionnel. Scène Netatmo Welcome Une seule instance autorisée. Démarrage Automatique --[[ %% autostart --]] -- Informations de compte Netatmo local client_id = 'Client_id'; local client_secret = 'Client_secret'; local username = 'Netatmo_username'; local password = 'Netatmo_pass'; -- Informations du VD associé local vd_ID = 304; -- ID du VD associé local vd_refresh = 9; -- ID du bouton refresh du VD. 9 Par défaut -- Réglages de la scène local refresh = 10; -- Script executé toutes les x secondes. Pas moins de 8s! local debug = 0; -- Faut-il vraiment l'expliquer ? -- Nom de la Variable Globale qui sera créée et utilisée par la scène et le VD local VGNetatmo = "NETATMO_Welcome"; -------------------------------------------------------------- -------- Ne rien modifier à partir de cette ligne ------------ -------------------------------------------------------------- local token = ''; local request_body = ''; Debug = function (color, message) if (debug == 1) then fibaro:debug(string.format('<%s style="color:%s;">%s', "span", color, message, "span")); elseif (debug == 0) then end end DebugChange = function (color, message) fibaro:debug(string.format('<%s style="color:%s;">%s', "span", color, message, "span")); end DebugError = function (color, message) fibaro:debug(string.format('<%s style="color:%s;">%s', "span", color, message, "span")); end fibaro:debug('Démarrage du script Netatmo welcome Integration v.1.0'); if (debug == 0) then fibaro:debug("Debug = 0. Seuls les messages d'information apparaîtront dans les logs."); else fibaro:debug('Debug = 1. Messages de Debug activés.'); end fibaro:debug('Cette scène sera executée toutes les ' ..refresh.. ' secondes.'); -- Début - Ajout pour gestion indépendante des VG function CreerVG(VGNom, VGValeur) local data = {name = VGNom, value=VGValeur}; response, status = api.post("/globalVariables", data); if (status == 201) then DebugError("white", "Variable Globale " .. VGNom .. " créée."); else DebugError("red", "Impossible de créer la Variable Globale " .. VGNom .. "!"); end end function MajEntree(Nom, Statut, Lastseen) local table = json.decode(fibaro:getGlobalValue(VGNetatmo)); -- Tout est à mettre à jour if Nom ~= nil and Statut ~= nil and Lastseen ~= nil then table[Nom] = {status=Statut, lastseen=Lastseen}; fibaro:setGlobal(VGNetatmo,json.encode(table)); DebugError("yellow", "L'entrée " .. Nom .. " a été automatiquement créée."); -- Mise à jour du Statut elseif Nom ~= nil and Statut ~= nil and Lastseen == nil then table[Nom].status = Statut; fibaro:setGlobal(VGNetatmo,json.encode(table)); Debug("yellow", "Le statut de " .. Nom .. " a été mis sur la valeur ".. Statut); -- Mise à jour de la dernière vue de la personne elseif Nom ~= nil and Statut == nil and Lastseen ~= nil then table[Nom].lastseen = Lastseen; fibaro:setGlobal(VGNetatmo,json.encode(table)); Debug("yellow", "L'information 'lastseen' de " .. Nom .. " a été mise sur la valeur ".. Lastseen); else DebugError("red", "Erreur lors de l'utilisation de la fonction MajEntree"); if Nom == nil then DebugError("white", "Champ 'Nom' vide !"); end if Statut == nil then DebugError("white", "Champ 'Statut' vide !"); end if Lastseen == nil then DebugError("white", "Champ 'Lastseen' vide !"); end end end if fibaro:getGlobalValue(VGNetatmo) == nil then CreerVG(VGNetatmo,json.encode({})); end -- Fin - Ajout pour gestion indépendante des VG function oAuth(nextFunction) local request_body = 'grant_type=password&client_id=' .. client_id .. '&client_secret=' .. client_secret .. '&username=' .. username .. '&password=' .. password .. '&scope=read_camera'; getResponseData('https://api.netatmo.net/oauth2/token', request_body, function(data) if (data.access_token ~= nil) then token = data.access_token gethomedata() else DebugError( "red", "Impossible de joindre l'API!"); end end ) setTimeout(oAuth, refresh*1000); end function getResponseData(url, body, func) local http = net.HTTPClient(); http:request(url, { options = { method = 'POST', headers = {['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'}, data = body, checkCertificate = false }, success = function(response); func(json.decode(response.data)); end }) end function gethomedata() request_body_cam = 'access_token=' ..token.. ''; getResponseData('https://api.netatmo.net/api/gethomedata', request_body_cam, function(getData) if (getData.body ~= nil) then for w, v in pairs(getData.body.homes) do for a, b in pairs(v.persons) do local INFOS = json.decode(fibaro:getGlobalValue(VGNetatmo)); if (b.pseudo ~= nil) then if (b.out_of_sight == false) then if INFOS[b.pseudo] ~= nil then MajEntree(b.pseudo,nil,b.last_seen); local change_var = tonumber(INFOS[b.pseudo].status); if (change_var == 0) then DebugChange("green", b.pseudo.. ' est présent.') MajEntree(b.pseudo,1,nil); else Debug("white", b.pseudo.. ' est toujours présent.'); end else Debug("red", "L'entrée pour " ..b.pseudo.. " de la table "..VGNetatmo.." n'éxiste pas."); MajEntree(b.pseudo,0,0); end else if INFOS[b.pseudo] ~= nil then MajEntree(b.pseudo,nil,b.last_seen); local change_var2 = tonumber(INFOS[b.pseudo].status); if (change_var2 == 1) then DebugChange( "orange", b.pseudo.. ' est absent.'); MajEntree(b.pseudo,0,nil); else Debug( "white", b.pseudo.. ' est toujours absent.'); end else Debug("red", "L'entrée pour " ..b.pseudo.. " de la table "..VGNetatmo.." n'éxiste pas."); MajEntree(b.pseudo,0,0); end end end end end else Debug("red", "Impossible de joindre l'API! Vérifier le taux de rafraichissemment!"); end if tonumber(vd_ID) ~= nil then fibaro:call(vd_ID, "pressButton", vd_refresh); end end ) end local sourceTrigger = fibaro:getSourceTrigger(); if (sourceTrigger["type"] == "autostart") then oAuth(); end Icones Téléchargement du VD Netatmo_Welcome.vfib
  2. Quelqu'un a déjàjoué avec ça ? j'en ai une en commande qui ne devrait pas tarder àarriver ...
  3. Steven

    Pluviométrie Avec Netatmo

    PLUVIOMETRIE (ET ARROSAGE) AVEC NETATMO firmware 4.x seulement Partie 1 : récupérer l'historique Netatmo est une station météo sur laquelle vous pouvez brancher un "pluviomètre" de la même marque. Afin d'exploiter les données de ce pluviomètre et vous pouvez utiliser l'application Netatmo ou son site web. Vous pouvez aussi installer le plugin Netatmo fourni par Fibaro. Ce dernier vous affichera uniquement les données à l'instant précis ou vous être entrain de le regarder. Nous, nous voulons allez plus loin, nous voulons connaitre les quantités de pluie ayant eu lieu depuis : 1 jour, 1 semaine, 1 mois, cela dans l'optique de pouvoir gérer correctement notre arrosage. Pour ce faire, il existe un grand nombre de script PHP, Google Script qui permet de gérer cela .. mais ... depuis la v4.x, Fibaro nous fait bénéficier de la librairie net.httpClient dans une scène et cette librairie nous permet de récupérer des données via HTTPS, ce qui auparavant n'était pas possible depuis notre HC2. Alors vu que nous avons, aujourd'hui, tout le nécessaire pour attaquer notre Netatmo directement depuis notre HC2, pourquoi s'en priver Les données recueillies par votre Netatmo sont mis à diposition via des API que vous pouvez interroger quand bon vous semble à la seul condition d'avoir un compte Développeur Netatmo (ne vous inquiéter pas, vous n'aurez pas beson de développer, ni de répondre à des questions étranges). Pour vous inscrire, c'est donc ici : https://auth.netatmo.com/fr-FR/access/signup Suite à votre enregistrement, vous allez obtenir : un id (exemple : 45b1931d19665803515b571c) un code secret (exemple : lyRkJXZLIM8xShACtmQjsCQV4U3djL08Zq1hUStbUJ4) Ces informations + votre login et mot de passe vont permettre d'accéder à vos informations. Voici donc le script nécessaire, à vous de l'importer dans une nouvelle scène et de modifier les 4 premières lignes. local n_client_id = "45b1931d19665803515b571c" local n_client_secret = "lyRkJXZLIM8xShACtmQjsCQV4U3djL08Zq1hUStbUJ4" local n_username = "______________@_____.com" local n_password = "password" local hc2_module_virtuel = 139 -- le module virtuel "Pluie" local debug = true -- affiche ou non les message dans la console local long_lat_adjust = 0.1 -- ajustement de la distance pour trouvé un pluviomètre local version = 2.0 -- ------------------------------------------------------------------------ -- NE PAS TOUCHER -- ------------------------------------------------------------------------ local force_use_rain_public = false local loc = api.get("/settings/location") local lat_ne = loc.latitude + long_lat_adjust local lon_ne = loc.longitude + long_lat_adjust local lat_sw = loc.latitude - long_lat_adjust local lon_sw = loc.longitude - long_lat_adjust local token = "" local int_id = "" local ext_id = "" local ext_bat = 0 local rain_id = "" local rain_bat = 0 local temperature_interieure = -1000 local temperature_exterieure = -1000 local co2 = -1000 local humidite_interne = -1000 local humidite_externe = -1000 local pression = -1000 local bruit = -1000 local rains = {hour = -1000, day = -1000, week = -1000, month = -1000} -- ------------------------------------------------------------------------ -- Exécuté après chaque requète HTTP -- ------------------------------------------------------------------------ function afterHttpRequest() if (temperature_interieure > -1000) then end if (temperature_exterieure > -1000) then end if (co2 > -1000) then end if (humidite_interne > -1000) then end if (humidite_externe > -1000) then end if (pression > -1000) then end if (bruit > -1000) then end if (rains["hour"] > -1000) then if (rains["hour"] == -1) then fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblHeure.value", "n/a") else fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblHeure.value", " "..rains["hour"]) end end if (rains["day"] > -1000) then if (rains["day"] == -1) then fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblJour.value", "n/a") else fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblJour.value", " "..rains["day"]) end end if (rains["week"] > -1000) then if (rains["week"] == -1) then fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblSemaine.value", "n/a") else fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblSemaine.value", " "..rains["week"]) end end if (rains["month"] > -1000) then if (rains["month"] == -1) then fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblMois.value", "n/a") else fibaro:call(hc2_module_virtuel, "setProperty", "ui.lblMois.value", " "..rains["month"]) end end end -- ------------------------------------------------------------------------ -- Affichage dans la console -- ------------------------------------------------------------------------ function log(message, force) force = force or false if (debug or force) then print(__convertToString(message)) end end -- ------------------------------------------------------------------------ -- Retourne le niveau de batterie en pourcent -- ------------------------------------------------------------------------ function calcBat(bat, ext) local max = 6000 local min = 4200 if (ext) then max = 6000 min = 3600 end if (bat > max) then bat = max end return math.floor(bat * 100 / max) end -- ------------------------------------------------------------------------ -- Arrondi -- ------------------------------------------------------------------------ local function roundToNthDecimal(num, n) local mult = 10^(n or 0) return math.floor(num * mult + 0.5) / mult end -- ------------------------------------------------------------------------ -- Interrogation de l'API -- ------------------------------------------------------------------------ function getResponseData(url, body, func) local http = net.HTTPClient() http:request(url, { options = { method = 'POST', headers = { ["Content-Type"] = "application/x-www-form-urlencoded;charset=UTF-8" }, data = body }, success = function(response) func(json.decode(response.data)) afterHttpRequest() end, error = function(response) log(" ERROR !!! " .. url, true) end, }) end -- ------------------------------------------------------------------------ -- Mesures de l'unité interne -- ------------------------------------------------------------------------ function getMesuresInt() getResponseData("https://api.netatmo.net/api/getmeasure","access_token="..token.."&device_id="..int_id.."&scale=max&type=Temperature,CO2,Humidity,Pressure,Noise&date_end=last", function(data) log("----------========== Module intérieur ==========----------") temperature_interieure = data.body[1].value[1][1] co2 = data.body[1].value[1][2] humidite_interne = data.body[1].value[1][3] pression = data.body[1].value[1][4] bruit = data.body[1].value[1][5] log("temperature_interieure = " .. temperature_interieure) log("co2 = " .. co2) log("humidite_interne = " .. humidite_interne) log("pression = " .. pression) log("bruit = " .. bruit) end ) end -- ------------------------------------------------------------------------ -- Mesure de l'unité externe -- ------------------------------------------------------------------------ function getMesuresExt() getResponseData("https://api.netatmo.net/api/getmeasure","access_token="..token.."&device_id="..int_id.."&module_id="..ext_id.."&scale=max&type=Temperature,Humidity&date_end=last", function(data) log("----------========== Module extérieur ==========----------") temperature_exterieure = data.body[1].value[1][1] humidite_externe = data.body[1].value[1][2] log("temperature_exterieure = " .. temperature_exterieure) log("humidite_externe = " .. humidite_externe) end ) end -- ------------------------------------------------------------------------ -- Obtention des informations sur un pluviomètre proche -- ------------------------------------------------------------------------ function getRainNear() getResponseData("https://api.netatmo.net/api/getpublicdata","access_token="..token .. "&lat_ne="..lat_ne.."&lon_ne="..lon_ne.."&lat_sw="..lat_sw.."&lon_sw="..lon_sw, function(data) --log(data) rains["week"] = -1 rains["month"] = -1 rains["hour"] = -1 rains["day"] = -1 log("----------========== D e v i c e s =========----------") for _, v in pairs(data.body) do for l, w in pairs(v.measures) do if (type(w.rain_24h) ~= "nil") then rains["day"] = w.rain_24h rains["hour"] = w.rain_60min end end end if (rains["day"] == -1000) then log("Impossible de trouver un pluviomètre à proximité, augmentez [long_lat_adjust]", true) else log("Pluie jour : " .. rains["day"]) log("Pluie heure : " .. rains["hour"]) end end ) end -- ------------------------------------------------------------------------ -- Mesure du détecteur de pluie historique -- ------------------------------------------------------------------------ function getMesuresRain(duree, variable) local now = os.time(); getResponseData("https://api.netatmo.net/api/getmeasure","access_token="..token.."&device_id="..int_id.."&module_id="..rain_id.."&scale=1hour&type=sum_rain&real_time=true&date_begin="..os.date("!%c", (now - duree)), function(data) log("----------========== Pluie histo ==========----------") local cumul = 0 for k, v in pairs(data.body) do for l, w in pairs(v.value) do cumul = cumul + w[1] end end cumul = roundToNthDecimal(cumul, 2) rains[variable] = cumul log("rain["..variable.."] = " .. rains[variable]) end ) end -- ------------------------------------------------------------------------ -- Obtention des informations sur les devices -- ------------------------------------------------------------------------ function getDevices() getResponseData("https://api.netatmo.net/api/devicelist","access_token="..token, function(data) log("----------========== D e v i c e s =========----------") for _, v in pairs(data.body.modules) do if (v.data_type[1] == "Rain") then rain_id = v._id rain_bat = calcBat(v.battery_vp, true) else ext_id = v._id ext_bat = calcBat(v.battery_vp, true) end end int_id = data.body.devices[1]._id getMesuresInt() getMesuresExt() if (rain_id ~= "" and not force_use_rain_public) then getMesuresRain(60 * 60, "hour") getMesuresRain(60 * 60 * 24, "day") getMesuresRain(60 * 60 * 24 * 7, "week") getMesuresRain(60 * 60 * 24 * 30, "month") else getRainNear() end end ) end -- ------------------------------------------------------------------------ -- Authentification -- ------------------------------------------------------------------------ function auth(nextFunction) local request_body = "grant_type=password&client_id=" .. n_client_id .. "&client_secret=" .. n_client_secret .. "&username=" .. n_username .. "&password=" .. n_password .. "&scope=read_station" getResponseData("https://api.netatmo.net/oauth2/token", request_body, function(data) token = data.access_token log(token) nextFunction() end ) end auth(getDevices) log("Last request : " .. os.date("%x - %X"), true) si vous avez l'âme d'un développeur ou d'un aventurier, la méthode à modifier est afterHttpRequest() sinon, rendez-vous au post suivant. P.S. Merci à @PITP2 pour son support. Edit : nouvelle version du script. Si ce dernier détecte que vous n'avez pas de pluviomètre, il va rechercher un pluviomètre à proximité de chez vous (uniquement les relevés de la dernière heure et jour). La distance de recherche peux être adaptée en ajustant la variable long_lat_adjust (0.1 par défaut). Il s'agit du cercle de recherche en latitude/longitude autour de chez vous.
  4. Bonjour, Voilà un moment que je cherchais le moyen de piloter les projecteurs de mes caméras « Présence » (j'en ai une côté cour et une autre côté jardin). C'est chose faite et je partage ma solution si cela peut aider quelqu'un. Tout d'abord merci à @KiboOst, qui « sévit » sur le forum jeedom, pour son excellent « php-simpleNetatmoAPI ». D'après ce que j'ai compris il s'agit d'un travail de reverse engineering qui s'est terminé par un retour aux API Netatmo ... sauf, qu'en fouillant dans les API officielles de Netatmo, je n'ai trouvé nulle part le moyen de piloter l'allumage du projecteur et encore moins de gérer sa luminosité ! Donc ma solution : - Côté Serveur (mon Raspberry) installation des composants de « php-simpleNetatmoAPI » sur mon Raspberry création d'un fichier TXT de paramétrage de l'API et des projecteurs écriture d'un script PHP destiné à exécuter une action sur un projecteur - Côté Home Center création d'un VD pour piloter mes 2 projecteurs simultanément ... outil prêt pour une utilisation future, ex : allumer tous les extérieurs de la maison en cas de fête et/ou d'intrusion Un peu de contenu si cela vous intéresse : Côté HC2, le VD et ses icônes Côté Raspberry, le fichier TXT et le script PHP Et voilou ... enjoy Cordialement - Jean-Paul Le VD L'export du VD est disponible en fichier joint. Sur le Raspberry 1 - Fichier texte de paramètrages User=.......... Password=.......... ClientId=.......... ClientSecret=.......... Projo1Home=3 Projo1Name=Présence avant Projo2Home=1 Projo2Name=Présence arrière 2 - Script PHP <?php //-------------------------------------------------------------------------------------------------- // // Script de commande du projecteur d'une caméra Presence Netatmo // // Inspiration : https://github.com/KiboOst/php-simpleNetatmoAPI // // Principe : // 1 - Les infos de connexion sont enregistrées dans un fichier texte sur ce serveur // . les 4 premières lignes sont dédiées à la connexion à l'API Netatmo // . puis une paire de lignes par caméra (ligne 1 = code 'Maison', ligne 2 = nom 'Présence') // 2 - Pour connaître les 'Home' et 'Name' des projecteurs : // . ne saisir que les 4 premières lignes dans le fichier texte // . lancer le script comme ceci : /ProjoAutoOnOff.php?projo=1&action=on // . lire ce qui s'affiche // . rechercher "Si le nombre de projecteurs est égal à zéro" dans le code // . débloquer/dupliquer les lignes en commentaires en remplacant 'xx' par le/les codes 'Maison' // 3 - En entrée : // . le numéro du projecteur à piloter (1 ou 2 ... ou plus) // . la commande à envoyer au projecteur ('auto', 'on' et 'off') // 4 - En sortie : // . commande OK // . commande non effectuée car le projo est déjà à l'état demandé // . autre (erreur) // //-------------------------------------------------------------------------------------------------- $Verbose = false; /* Validation du code action */ $Action = $_GET["action"]; if (strlen($Action) == 0) { exit('Missing action code'); } else { if ($Action != 'auto' and $Action != 'on' and $Action != 'off') { exit('Invalid action code'); } } if ($Verbose) {echo 'Code action ----> ', $Action, '<br>';} /* Récupération du numéro de projecteur */ $NumProjo = $_GET["projo"]; if (strlen($NumProjo) == 0) { exit('Missing floodlight number'); } if ($Verbose) {echo 'Numéro de projecteur ----> ', $NumProjo, '<br>';} /* Ouverture du fichier des infos de connexion au routeur et retourne un tableau contenant une ligne par élément */ $lines = file('ProjosCredentials.txt'); $NbLines = count($lines); if ($Verbose) { foreach ($lines as $lineNumber => $lineContent) { echo $lineNumber,' ',$lineContent, '<br>'; } echo 'Nombre de lignes : ', $NbLines, '<br>'; } /* Vérification du nombre de lignes */ if (($NbLines % 2) == 1) { exit('Invalid line number (odd)'); } /* Chargement des variables de connexion */ $Netatmo_User = ""; $Netatmo_Psw = ""; $Netatmo_ClientID = ""; $Netatmo_ClientSecret = ""; /* ----> Netatmo User */ $mystring = trim($lines[0]); $findme = 'User='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Netatmo User'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Netatmo User'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $Netatmo_User = substr($mystring, strlen($findme)); } } /* ----> Netatmo Password */ $mystring = trim($lines[1]); $findme = 'Password='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Netatmo Password'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Netatmo Password'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $Netatmo_Psw = substr($mystring, strlen($findme)); } } /* ----> Netatmo Client ID */ $mystring = trim($lines[2]); $findme = 'ClientId='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Netatmo Client ID'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Netatmo Client ID'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $Netatmo_ClientID = substr($mystring, strlen($findme)); } } /* ----> Netatmo Client Secret */ $mystring = trim($lines[3]); $findme = 'ClientSecret='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Netatmo Client Secret'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Netatmo Client Secret'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $Netatmo_ClientSecret = substr($mystring, strlen($findme)); } } /* Chargement des numéros de projecteurs */ $i = 4; $NbProjo = 0; $TabProjo = array(); while ($i < $NbLines) { $NbProjo = $NbProjo + 1; $mystring = trim($lines[$i]); $findme = 'Projo' . $NbProjo . 'Home='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Floodlight' . $NbProjo . ' Home'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Floodlight' . $NbProjo . ' Home'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $TabProjo[$NbProjo][1] = substr($mystring, strlen($findme)); } } $i = $i + 1; $mystring = trim($lines[$i]); $findme = 'Projo' . $NbProjo . 'Name='; $pos = strpos($mystring, $findme); if ($pos === false) { echo "La chaîne '$findme' ne se trouve pas dans la chaîne '$mystring'", '<br>'; exit('Error retrieving Floodlight' . $NbProjo . ' Name'); } else { if ($pos <> 0) { echo 'La chaîne ', $findme, ' n\'est pas au début de ', $mystring, '<br>'; exit('Error retrieving Floodlight' . $NbProjo . ' Name'); } else { if ($Verbose) {echo "La chaine '$findme' a été trouvée dans la chaîne '$mystring' et débute à la position $pos", '<br>';} $TabProjo[$NbProjo][2] = substr($mystring, strlen($findme)); } } $i = $i + 1; } if ($Verbose) { echo 'Netatmo User = ', $Netatmo_User, '<br>'; echo 'Netatmo Password = ', $Netatmo_Psw, '<br>'; echo 'Client ID = ', $Netatmo_ClientID, '<br>'; echo 'Client Secret = ', $Netatmo_ClientSecret, '<br>'; echo 'Nombre de projecteurs = ', $NbProjo, '<br>'; echo 'Table des projecteurs :', '<br>'; for ($i=1; $i<=$NbProjo; $i++) { echo 'Presence', $i, ' Home = ', $TabProjo[$i][1], ' - Presence', $i, ' Name = ', $TabProjo[$i][2], '<br/>'; }; } // Si le nombre de projecteurs est égal à zéro on récupère les infos "Homes" if ($NbProjo == 0) { require($_SERVER['DOCUMENT_ROOT']."/php-simpleNetatmoAPI/class/splNetatmoAPI.php"); $_splNetatmo = new splNetatmoAPI($Netatmo_User, $Netatmo_Psw, $Netatmo_ClientID, $Netatmo_ClientSecret); if (isset($_splNetatmo->error)) die($_splNetatmo->error); // Liste des maisons avec le nombre de caméras rattachées $homes = $_splNetatmo->getHomes(); echo "<pre><br>homes:<br>".json_encode($homes, JSON_PRETTY_PRINT)."</pre><br>"; // -------------------------------------------------------------------------------------------------------------------------------- // Remplacer 'xx' dans l'instruction suivante par le code maison obtenu et décommenter les lignes pour obtenir les infos 'Présence' // // $_splNetatmo = new splNetatmoAPI($Netatmo_User, $Netatmo_Psw, $Netatmo_ClientID, $Netatmo_ClientSecret, xx); // $Cameras = $_splNetatmo->getPresenceCameras(); // echo "<pre>Cameras:<br>".json_encode($Cameras, JSON_PRETTY_PRINT)."</pre><br>"; // --------------------------------------------------------------------------------------------------------------------------------- exit ('Please enter the projectors codes (House and Name)'); } /* Validation du numéro de projecteur */ if ($NumProjo < 1 or $NumProjo > $NbProjo) { exit('Invalid floodlight number'); } // C'est parti /* Récupération du statut du projecteur */ require($_SERVER['DOCUMENT_ROOT']."/php-simpleNetatmoAPI/class/splNetatmoAPI.php"); $ProjoHome = $TabProjo[$NumProjo][1]; $ProjoName = $TabProjo[$NumProjo][2]; $_splNetatmo = new splNetatmoAPI($Netatmo_User, $Netatmo_Psw, $Netatmo_ClientID, $Netatmo_ClientSecret, $ProjoHome); $Cameras = $_splNetatmo->getPresenceCameras(); $StatusProjo = $Cameras[$ProjoName]['light_mode_status']; if ($Verbose) { echo "<pre>Cameras :<br>".json_encode($Cameras, JSON_PRETTY_PRINT)."</pre><br>"; echo "Status du projo '", $ProjoName, "' de la maison '", $ProjoHome, "' = ", $StatusProjo, '<br>'; } /* Si le projo est déjà à l'état demandé on ne fait rien */ if ($Action == $StatusProjo) { if ($Verbose) {echo 'Changement du status du projecteur inutile - On arrête', '<br>';} exit('Floodlight already set'); } /* On passe le projo à l'état demandé */ $_splNetatmo->setLightMode($ProjoName, $Action); if ($Verbose) {echo "Projecteur passé à '", $Action, "'", '<br>';} exit('Floodlight set'); ?> Projecteurs_Caméras.vfib.json
  5. 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();
  6. cboubou

    Module Virtuel "smartvmc"

    Bonjour la communauté, Je vous propose aujourd'hui mon module virtuel "SmartVMC". Ce dernier me permet de piloter de manière automatique ma VMC en fonction de la qualité de l'air de ma maison : On allume la VMC si le taux moyen d'humidité relative est supérieur à 60% OU si la concentration moyenne de CO2 est supérieure à 1000 ppm. Le traitement s'arrêtera si le taux moyen d'humidité relative est inférieur ou égal à 55% ET si la concentration moyenne de CO2 est inférieure ou égale à 900 ppm. Le but étant de ne pas allumer/éteindre la VMC dès que l'on atteint la limite de 60% ou de 1000 ppm. Les données sur la qualité de l'air (humidité relative et concentration de CO2) sont extraites de ma Netatmo par le biais du plugin idoine disponible dans la V4. Ma configuration matérielle est la suivante : VMC simple flux, hygroréglable, Aldès, MicroWatt. Home Center 2 en version v4.033. WallPlug Fibaro pour piloter la VMC. Station Netatmo avec modules additionnels. Le module virtuel se présente de la sorte : Un visuel des moyennes d'humidité relative et de concentration de CO2. Un bouton permettant d'analyser à l'instant "t" l'air de la maison. Un visuel de l'état actuel de la VMC. Un bouton de marche forcée de la VMC. Un bouton d'arrêt complet de la VMC. Un bouton pour basculer la VMC en mode automatique. La date de la dernière analyse de l'air. Les 4 états différents de la VMC sont les suivants : Marche Forcée Arrêt Complet Auto (En cours...) Auto (Pause) Il est nécessaire de créer 2 variables globales : Une première variable globale "VMC" est utilisée afin de savoir si la VMC est : en marche automatique, en pause, en marche forcée ou arrêtée (Auto, Pause, Forcée, Arrêtée). Une seconde variable globale "RecyclAir" est utilisée afin de savoir si la VMC est déjà en train d'assainir l'air, par le biais de ce traitement (Oui, Non). J'ai commenté le code afin d'en faciliter la compréhension. NB : Il peut être envisageable pour les personnes possédant une VMC à 2 vitesses que le mode "Auto (En cours...)" corresponde à la grande vitesse et que le mode "Auto (Pause)" corresponde à la petite vitesse. Voici les icônes (2 variantes) : Orange => Marche Forcée Rouge => Arrêt Complet Vert => Auto (En cours...) Bleu => Auto (Pause) Les originaux qui m'ont servi de base sont ici : http://www.domotique...zibase/?p=25155 Vous trouverez également de magnifiques icônes pour la Netatmo ici (merci Stef). ChangeLog => v1.0 : Création du module. v1.1 : Ajout du push lors du passage "En cours" <=> "Pause". Modification des conditions du passage au mode "Auto". Ajout d'un contrôle sur l'état du plugin Netatmo pour mode "Auto". SmartVMC.vfib
  7. Netatmo Vannes connectées pour radiateurs By Starck Économisez 37 % d'énergie pour chauffer votre maison https://www.netatmo.com/product/energy/valves Annoncé à l'IFA le 1er septembre 2016 69,99 € l’unité pack de démarrage incluant deux vannes et un relais : 179,99 € Pas encore disponible à ce jour.
  8. Je vous propose ce tuto pour créer un Virtual Device HCL afin de contrôler un thermostat Netatmo. C'est très utile dans l'optique d'un tableau de bord unifié, regroupant tous les objets connectés au niveau de la box domotique. C'est pratique aussi lorsqu'il s'agit de créer des scènes intégrant des informations provenant du thermostat (température mesurée, température de consigne de la chaudière, mode de chauffage...). Il existe bien un plugin Netatmo sur HCL mais je n'ai jamais pu le faire marcher, du moins pour le thermostat (ça marche peut-être pour la station meteo Netatmo). Par ailleurs, du fait des limitations de la HCL en termes de programmation (pas de LUA comme la HC2), il a fallu développer un web service HTTP (et non HTTPS) jouant le rôle d'intermédiaire entre le virtual device et le thermostat. En marge de ce tuto, je propose donc aussi un web service pour piloter le thermostat Netatmo. Principe L'objectif est donc de "fabriquer" un virtual device HCL pour le thermostat Netatmo permettant de: Récupérer la température mesurée Définir une température de consigne Définir le temps de validité de la température de consigne Switcher entre les modes : manual, program, away Voilààquoi cela ressemble visuellement Prérequis - Savoir créer un virtual device HCL. Ce tuto est très bien pour ça. - Quelques connaissances Linux pourraient être utiles pour l'installation du software, la copie et la modification de fichiers... - Quelques connaissances http et web services pourraient aider àcomprendre le principe de fonctionnement (optionnel) Matériel - Une HCL - Un thermostat Netatmo - un PC ou un Raspberry Pi (ou équivalent) qui jouera le rôle de serveur hébergeant le web service Pour ceux qui voudraient installer le software sur un Linux autre que celui du Raspberry (Raspbian), il faudrait s'informer sur la manière de rajouter un service (deamon) qui pourrait être différente de celle présentée ici. Logiciel Le code (Python) du web service que je fais tourner sur Raspberry Pi et que j'ai appelé "restatmo" est disponible dans Github sur ce lien. Un descriptif d'installation et de configuration y est décrit ici. Il s'agit d'une première version avec surement quelques bugs. Voici quelques caractéristiques du logiciel: - Pour ceux qui connaissent un peu les web services, voici un aperçu de l'interface http de "restatmo": GET /tempSP : récuperer la température de consigne courante POST /tempSP/valeur_entiere : définir une nouvelle température de consigne (durée par défaut : 15mn). Cette requête permet aussi de définir les modes away et program POST /tempDur/duration : définir la durée de validité de la température de consigne courante GET /tempMeas : récupérer la température mesurée par le thermostat - Pour la mise àjour du "slider" de la température mesurée, j'ai prévu un second service (tempupdate.py) se trouvant dans le même répertoire "restatmo". Lorsqu'il est lancé sur la machine passerelle (raspi ou autre), ce service met àjour la température mesurée du virtual device àintervalles réguliers. Des paramètres d'identification de la HCL et l'intervalle de mise àjour sont des données requises par ce service et sont paramétrables dans ce fichier tempupdate.py. Cette manière de mettre àjour la température est la seule que j'ai trouvée. En effet, les requêtes HTTP d'un virtual device sur HCL ne permettent pas d'aller chercher des valeurs. Le virtual device il faut d'abord définir le "host" et le "port" du Virtual Device qui sont respectivement l'adresse IP de machine sur laquelle tourne le service "restatmo" et le port de ce même service (par défaut 5000) Ce virtual device est composé de 3 sliders et de 3 boutons: 1) Slider 1 : la température mesurée par netatmo Il n'y rien àconfigurer au niveau de la chaine de caractères àenvoyer par ce slider. En effet, il est mis àjour automatiquement par le service "tempupdate" décrit précédemment. 2) Slider 2 : la température de consigne Chaine àenvoyer: POST /tempSP/_sliderValue_ HTTP/1.10x0D0x0AHost:192.168.0.28:5000 0x0D0x0AAuthorization: Basic xxxxxxxxxxxxxxxxxxx 0x0D0x0A0x0D0x0A NB: _sliderValue_ est la valeur indiquée par le slider en question (très pratique comme variable) xxxxxxxxxx: "user:password" en base 64 (voir tuto de création de Virtual Device) 3) Slider 3 : la durée de validité de la température de consigne Chaine àenvoyer: POST /tempDur/_sliderValue_ HTTP/1.10x0D0x0AHost:192.168.0.28:5000 0x0D0x0AAuthorization: Basic xxxxxxxxxxxxxxxxxxx 0x0D0x0A0x0D0x0A 4) Bouton1 : mode program Chaine àenvoyer: POST /tempSP/0 HTTP/1.10x0D0x0AHost:192.168.0.28:5000 0x0D0x0AAuthorization: Basic xxxxxxxxxxxxxxxxxxx 0x0D0x0A0x0D0x0A 5) Bouton2 : mode manual (ce n'est rien d'autre qu'une température de consigne à20°) Chaine àenvoyer: POST /tempSP/20 HTTP/1.10x0D0x0AHost:192.168.0.28:5000 0x0D0x0AAuthorization: Basic xxxxxxxxxxxxxxxxxxx 0x0D0x0A0x0D0x0A 6) Bouton3 : mode away POST /tempSP/101 HTTP/1.10x0D0x0AHost:192.168.0.28:5000 0x0D0x0AAuthorization: Basic xxxxxxxxxxxxxxxxxxx 0x0D0x0A0x0D0x0A enfin, pensez àtélécharger l'icone (ci-joint) àassocier au virtual device. La suite je n'ai peut-être pas suffisamment détaillé ce tuto, notamment concernant la partie paramétrage et installation du service web. N'hésitez pas àme solliciter si vous êtes intéressés ou si vous avez des questions. Vous pouvez aussi jeter un coup d'oeil sur mon autre tuto dont le but est de piloter l'alarme HCL/HC2 avec une passerelle NFC. A++
  9. Bonjour à tous, J'ai un soucis depuis peu avec le VD de ma station Netatmo. Le script ne fonctionne plus : Erreur 404 dans le débug local selfId = fibaro:getSelfId(); local icon = fibaro:get (selfId, "deviceIcon"); local HC2 = Net.FHttp("192.168.0.46"); HC2:setBasicAuthentication("XXXXXX", "xxxxx"); local response, status, errorCode = HC2:GET("/Web_Scripts/netatmo.php?intext=ext"); if tonumber(status) == 200 then -- decoding json string to table -- if (response ~= nil) then local result = json.decode(response); fibaro:debug(response); local NetTempExt = result.body[1].value[1][1]; local NetHumExt = result.body[1].value[1][2]; fibaro:setGlobal("NetTempExt", NetTempExt); fibaro:setGlobal("NetHumExt", NetHumExt ); fibaro:log(fibaro:getGlobalValue("NetTempExt").. " °C " ..fibaro:getGlobalValue("NetHumExt").. " % " ) fibaro:debug(fibaro:getValue(83, "ui.status.value")); fibaro:call(83, "setProperty", "ui.status.value", (fibaro:getGlobalValue("NetTempExt").. " °C " ..fibaro:getGlobalValue("NetHumExt").. " % " )); fibaro:sleep(3*1000); fibaro:call(selfId, "setProperty", "currentIcon", icon); fibaro:call(83, "setProperty", "ui.status.value", ""); else -- oups il y a un problème... fibaro:debug("Impossible de décoder la réponse, pas de données pour le traitement..."); end else -- oups il y a un problème... fibaro:debug("Err: " .. status); end Si une âme charitable pouvait me filer un coup de main ... D'avance merci pour votre aide.
  10. La gestion du chauffage sur la HC2 nécessite au minimum : Une sonde de température Des plages horaires et température souhaitées Un ou plusieurs modules déclencheurs pour activer/désactiver l'appareil de chauffe. Malheureusement, pas tout le monde est équipé de sonde de température et dans ce cas là , il est impossible de chauffer son habitat à travers sa HC2. Pour remédier à ce soucis, il est possible d'utiliser un module virtuel qui va piloter vos déclencheurs selon une autre source de température* tout en tenant compte de vos souhaits en terme de températures/pages horaires. Vous pouvez aussi utiliser ce module pour utiliser comme référence une moyenne de vos sondes ou tout autre calcul. Exemple, je pilote ma chaudière en fonction de la température intérieur ET extérieur. Une seul condition à l'usage de ce module ... vous allez devoir programmer vous même la fonction qui va renvoyer la température que vous souhaiter exploiter. Mais la bonne nouvelle est que vous êtes sur un site communautaire et qu'il y a plein de personne pour vous aider si besoin. * sonde Orégon connecté à une box RFXCom, une sonde renvoyant du json comme la Netatmo. Voici la démarche à suivre : 1) Règler votre panneau de chauffage selon vosdésires (notez son ID) : 2) Importer le module virtuel "Chauffage_-_Salon.vfib 3) Modifier les premières lignes de codes qui sont dans le bouton rafraîchir Heating.hysteresis = 0.7 --- +/- de chauffage Heating.holidays = 8 -- température souhaitée du mode vacances Heating.stefa = 1 -- id du panneau de chauffage Heating.admin = "admin" Heating.password = "admin" -- Retourne la température courante Heating.getActualTemp = function() -- Ici vous pouvez mettre votre code qui doit renvoyer un nombre -- correspondant à la température en cours -- Dans mon cas, je reprend la valeur contenu dans le slider "tempSalon" du module 43 return tonumber(fibaro:getValue(43, "ui.tempSalon.value"))/10 end Heating.switch = function(choice) -- Choice est soit "turnOn", soit "turnOff" -- cela permet d'activer/désactiver plusieurs modules en même temps ou de faire -- divers traitement que le système allume/éteint les modules fibaro:call(33, choice) --fibaro:call(34, choice) --fibaro:call(35, choice) end ... L’hystérésis est utilisée pour temporiser l'allumage/extinction du système. Exemple, j'ai défini 21° dans le panneau de chauffage pour le mardi matin. Le système va prendre 21°, soustraire l’hystérésis (0.7°) et va donc ce mettre en chauffe à 20.3°. De même dans l'autre sens, ou il va attendre qu'il fasse 21° + 0.7° pour s'éteindre soit 21.7°. Cela permet d'éviter que le système s'active à 20.9 et se désactive à 21. Ce qui peut être très dérangeant pour un poêle à pellet comme le mien. 4) Variable globale : Il faut créer un variable globale "Chauffage" qui peux prendre les valeurs : ON, OFF et VACANCES 5) Scénario qui temporise tous cela : Créer un scénario qui "appuie" sur le bouton "Rafraichir" toutes les X minutes (5 minutes dans mon cas). Usage : Etat : Indique [Température actuel] / [Température souhaitée] [[hystérésis]] (correction appliquée) Rafraichir : rafraichi manuellement les calculs Automatic : met le système en mode automatique (allumé) Eteindre : stoppe le système jusqu'au prochain appuie sur "Automatic" Vacances : Bascule en mode vacances (Utilise Heating.holidays comme température souhaitée) -1, -0.5, +0.5, +1 : Permet d'ajouter une "correction" de température souhaitée. Cette correction est annulée dès le prochain changement de mode. Exemple mardi matin, je ne souhaite plus 21° mais 22°. J'appuie donc sur +1. Quand le panneau de chauffage m'indiquera que nous somme en "mardi après-midi" la correction de +1 sera automatiquement annulée. Cela correspond au mode Jour ou Nuit temp. Correction : indique la différence de correction souhaitée Mode : indique le mode en cours En Chauffe : indique si le système est en chauffe (actif) ou non En gras sont les éléments nécessaires au module pour fonctionner, si tu les enlèves, il va planter. En prime, dans le code, il y a une méthode Heating.keepOn = function(). Je l'utilise pour ralentir le chauffage de mon poêle lorsque la température souhaitée est presque atteinte. Je l'ai mise en commentaire mais tu peux l'utiliser. Dans me cas, cela donne de 20.3° à 20.7° .. On chauffe à fond de 20.8° à 21.7° .. On chauffe en douceur en ralentissant la chauffe à 21.8° on coupe tout Conclusion. Voici un module virtuel qui accepte comme température de référence n'importe quoi : la température d'un module z-wave un code json (Netamo) ... et qui va piloter vos modules selon les températures indiquées dans votre panneau de chauffage. Ce module est testé chez moi depuis plus d'un mois avec succès sur un poêle à pellet qui, par définition, est bien plus pénible que des radiateurs P.S. Joint les icônes que j'utilise pour l'affichage. Chauffage_-_Salon.vfib
  11. Bonjour, Je me suis lancé le défi de rendre z-wave un pluviomètre Oregon PCR800. En effet, l'offre de pluviomètre compatible nativement avec la HC2, ou plus particulièrement la HCL, ne cours pas les rues. Je n'ai repéré que deux pluviomètre "compatible" : Netatmo en wifi : tout le monde le connait mais pour ne faire que pluviomètre, ça fait très cher ! Hydreon RG-11 : un capteur de pluie optique qui doit être associé à un Fibaro FGS pour "compter" la pluie qui tombe. Ce capteur doit être alimenté en 12/24V et bien sur le FGS doit également être alimenté. Comme je suis un peu fainéant, je ne choisirai pas cette solution non plus (trop de câble à passer) Vous me direz aussi : tu prends un raspberry, Jeedom (ou autre) avec le récepteur RF433 et hop avec ton Oregon tu auras ton pluvio ! Oui mais non, Cela fait toujours trop cher et sa multiplie les plateformes. Du coup, je me suis tourné vers du "fait le toi-même". En fait, je connaissais les stations météo Oregon et Lacrosse depuis longtemps et j'avais vu que c'était plutôt basique à l'intérieur. Un système de balance avec deux béchers et un aimant au milieu avec, en face, un interrupteur à lames souples (similaire au Fibaro FGK d'ailleurs). De plus, j'ai une formation électronique à la base... donc quand même ! Ma première approche a été de me dire que j'allais utiliser l'entrée binaire du Fibaro FGK pour récupérer les infos de l'Oregon. J'ai donc cherché avec le multimètre l'endroit où je pourrai récupérer les infos de basculement des réservoirs. Sans succès ! En effet, il y un vernis sur toute la carte qui empêche toutes mesures (et protège de l'eau par la même occasion). J'ai donc soudé deux fils directement sur ILS pour avoir son état… à‡a marche ! Du moins au multimètre… Car une fois connecté au FGK, il ne voit rien du tout. Je ne sais pas pourquoi. Enfin je ne sais plus pourquoi (je suis censé le savoir à la base ). De là , je vois que j'ai démonté tout mon pluvio, la carte, le compartiment de pile, la bascule… Je me rends compte que la solution est là ! Toute conne ! Il suffit que j'utilise le FGK directement avec un aimant sur la bascule. Gros coup de chance, le FGK passe couché dans le pluvio à la hauteur de la bascule (il y a des petits ergots dans le support qui l'empêche de descendre). Voici les ergots J'ai quand même mis le FGK dans une petite pochette histoire qu'il soit protégé de l'humidité. J'ai récupéré des aimants de reste que j'avais acheté pour ma baie et hop après quelques essais voilà le travail ! Comme vous pouvez voir sur la photo ci-dessus, le FGK repose sur les ergots et je le tiens pour ne pas qu'il tombe. Il restera en place en replaçant le couvercle (ça passe pile poil). à‡a permet de ne pas utiliser de colle. Bien sà»r, il ne faudra peut être pas le secouer après ! Tadaaaa ! Du coup, j'ai inclus le FGK à ma HCL et j'ai maintenant un pluviomètre dans mon interface (merci la galerie d'icône de notre cher forum) ! A partir de là , je vais laisser le soin au possesseur de HC2 de faire des choses bien chiadées car moi avec la HCL je ne peux pas faire grand-chose. Avant ce pluviomètre et depuis trois ans, je remplissais un fichier excel à la main avec les données de mon pluviomètre manuel. Maintenant, j'ai une scène qui m'envoie par mail chaque basculement (correspondant à 1 mm) et je n'ai plus qu'à reporter cette quantité dans mon fichier. Par exemple, s'il tombe 11mm, j'ai 11 mails (ne vous inquiétez pas, j'ai fait un filtre dans ma boite mail, je me suis pas spamé !). Après les orages de ces derniers jours, la résolution donnée de 1 mm par bascule à l'air correcte en comparaison de la quantité que j'obtiens dans le pluvio manuel. Voilà , c'est une solution "alternative" aux pluviomètres du marché. Personnellement j'en suis content !
×