Différences entre les versions de « Station météo Netatmo »
(22 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 6 : | Ligne 6 : | ||
| famille = Objets connectés | | famille = Objets connectés | ||
| date-create = 11/03/2018 | | date-create = 11/03/2018 | ||
| date-update = | | date-update = 27/03/2019 | ||
| auteur = fgtoul | | auteur = fgtoul | ||
}} | }} | ||
Ligne 76 : | Ligne 76 : | ||
Pour la compréhension et pour rendre le code plus facilement adaptable par un grand nombre parmi vous, j'ai vonlontairement programmé la récupération des données dans des variables au nom explicite, sans utiliser les tableaux. | Pour la compréhension et pour rendre le code plus facilement adaptable par un grand nombre parmi vous, j'ai vonlontairement programmé la récupération des données dans des variables au nom explicite, sans utiliser les tableaux. | ||
<source> | <source lang="php5"> | ||
<?php | <?php | ||
//renseignez vos identifiants ci-dessous | //renseignez vos identifiants ci-dessous | ||
Ligne 83 : | Ligne 83 : | ||
$app_id = "Votre_Client_ID"; | $app_id = "Votre_Client_ID"; | ||
$app_secret ="Votre_Client_Secret"; | $app_secret ="Votre_Client_Secret"; | ||
$IP_IPX800="Adresse_IP_IPX800:Port" | $IP_IPX800="Adresse_IP_IPX800:Port"; | ||
$API_key="Votre_Key_IPX800" | $API_key="Votre_Key_IPX800"; | ||
//---fin de paramétrage-- | //---fin de paramétrage-- | ||
//---Début procédure authentification--------------- | //---Début procédure authentification--------------- | ||
Ligne 145 : | Ligne 145 : | ||
//Module extérieur | //Module extérieur | ||
$ext_temp = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Temperature"]) * 10; | $ext_temp = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Temperature"]) * 10 +1000; | ||
$ext_temp_min = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["min_temp"]) * 10; | $ext_temp_min = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["min_temp"]) * 10+1000; | ||
$ext_temp_max = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["max_temp"]) * 10; | $ext_temp_max = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["max_temp"]) * 10+1000; | ||
$ext_humidite = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Humidity"]) * 10; | $ext_humidite = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Humidity"]) * 10+1000; | ||
$ext_battery = Batterie1(floatval($json_devices["body"]["modules"][0]["battery_vp"])); | $ext_battery = Batterie1(floatval($json_devices["body"]["modules"][0]["battery_vp"])); | ||
Ligne 179 : | Ligne 179 : | ||
$M5_Gust_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["GustAngle"]); //angle rafale | $M5_Gust_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["GustAngle"]); //angle rafale | ||
$M5_Wind_Max= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_str"]); //angle rafale | $M5_Wind_Max= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_str"]); //angle rafale | ||
$M5_Wind_Max_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_angle"]); // | $M5_Wind_Max_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_angle"]); //Vitesse max | ||
$M5_battery=Batterie2(floatval($json_devices["body"]["modules"][5]["battery_vp"])); | $M5_battery=Batterie2(floatval($json_devices["body"]["modules"][5]["battery_vp"])); | ||
Ligne 220 : | Ligne 220 : | ||
====Récupération des données==== | ====Récupération des données==== | ||
Le script se charge de récupérer les données de vos différents modules. | Le script se charge de récupérer les données de vos différents modules. | ||
Dans mon cas, les modules sont les suivant | Dans mon cas, les modules sont les suivant | ||
* ["modules"][0] correspond au module extérieur. | * ["modules"][0] correspond au module extérieur. | ||
Ligne 225 : | Ligne 226 : | ||
* ["modules"][2] correspond au 2nd module intérieur additionnel. | * ["modules"][2] correspond au 2nd module intérieur additionnel. | ||
* ["modules"][3] correspond au Pluviomètre. | * ["modules"][3] correspond au Pluviomètre. | ||
* ["modules"][5] correspond à l'anémomètre. | |||
* ["devices"][0] correspond au module principal de la station. | * ["devices"][0] correspond au module principal de la station. | ||
Ligne 276 : | Ligne 278 : | ||
Remarque : La station envoie ses mesures toutes les 10 minutes au serveur Netatmo. Si vous êtes équipés d'un anémomètre Netatmo, ne l'utilisez donc pas comme source de mesure afin que l'IPX800 rentre le store en fonction de la vitesse du vent. 10 minutes c'est long, votre store pourrait être détérioré en cas de vent fort. | Remarque : La station envoie ses mesures toutes les 10 minutes au serveur Netatmo. Si vous êtes équipés d'un anémomètre Netatmo, ne l'utilisez donc pas comme source de mesure afin que l'IPX800 rentre le store en fonction de la vitesse du vent. 10 minutes c'est long, votre store pourrait être détérioré en cas de vent fort. | ||
====hébergement du Php à l'extérieur==== | ====hébergement du Php à l'extérieur==== | ||
Ligne 318 : | Ligne 320 : | ||
L'IPX800 V4 recevra les mises à jour des données toutes les 10 minutes. | L'IPX800 V4 recevra les mises à jour des données toutes les 10 minutes. | ||
<u>'''Note :'''</u> Avec les différentes versions de DSM et les mises à jour, le chemin vers l'exécutable peut bouger. | |||
Si la planification avec l'URL précédente ne fonctionne pas, vous pouvez utiliser la fonction '''Curl''' avec l'Url de votre script PHP. | |||
Auparavant, vérifiez que la fonction Curl est activée sur votre serveur. | |||
Vérification sur le synology, ouvrez Web Station, puis vérifiez les paramètres PHP. Activez Curl si ce n'est pas déjà fait. | |||
[[Fichier:Netatmo_CurlPhp.png|500px]] | |||
Reprenons maintenant l'exemple de planification précédente : | |||
'''<nowiki>curl "http://adresseIP/Netatmo/netatmo2push.php"</nowiki>''' | |||
[[Fichier:Netatmo_Curl.png|500px]] | |||
==Sur IPX800== | ==Sur IPX800== | ||
Ligne 325 : | Ligne 337 : | ||
Voici la configuration et l'utilisation des entrées analogiques virtuelles sur votre IPX800 V4. | Voici la configuration et l'utilisation des entrées analogiques virtuelles sur votre IPX800 V4. | ||
[[Fichier: | [[Fichier:8dNetatmo_CreateAPP.png]] | ||
Vous pouvez les utiliser avec des widgets standards ainsi que dans vos scènes et vos notifications. | Vous pouvez les utiliser avec des widgets standards ainsi que dans vos scènes et vos notifications. | ||
===La source de données=== | ===La source de données=== | ||
Ligne 354 : | Ligne 365 : | ||
<source> | <source> | ||
//MODULE EXTERIEUR | //MODULE EXTERIEUR | ||
let T0=datasources["STATUS"]["response"]["analogV0"]/10; | let T0=(datasources["STATUS"]["response"]["analogV0"]-1000)/10; | ||
let Tmin0=datasources["STATUS"]["response"]["analogV1"]/10; | let Tmin0=(datasources["STATUS"]["response"]["analogV1"]-1000)/10; | ||
let Tmax0=datasources["STATUS"]["response"]["analogV2"]/10; | let Tmax0=(datasources["STATUS"]["response"]["analogV2"]-1000)/10; | ||
let H0=datasources["STATUS"]["response"]["analogV3"]/10; | let H0=datasources["STATUS"]["response"]["analogV3"]/10; | ||
let B0=datasources["STATUS"]["response"]["analogV4"]; | let B0=datasources["STATUS"]["response"]["analogV4"]; | ||
Ligne 448 : | Ligne 459 : | ||
<span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NBP}"></span> | <span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NBP}"></span> | ||
`; | |||
</source> | |||
====Le module Anémomètre==== | |||
[[Fichier:20cNetatmo.PNG]] | |||
<source> | |||
//MODULE ANEMOMETRE | |||
var BEARINGS = ["Nord", "N-N-E", "N-E", "E-N-E", "Est", "E-S-E", "S-E", "S-S-E", "Sud", "S-S-O", "S-O", "O-S-O", "Ouest", "O-N-O", "N-O", "N-N-O"]; | |||
function degreeToBearing(degree) { | |||
return BEARINGS[Math.floor((degree + 11.25) % 360 / 22.5)]; | |||
} | |||
let W=datasources["STATUS"]["response"]["analogV28"]; | |||
let W_A=Math.floor(datasources["STATUS"]["response"]["analogV29"]); | |||
//let P0_1=datasources["STATUS"]["response"]["analogV19"]/1000; | |||
let Gust=datasources["STATUS"]["response"]["analogV30"]; | |||
let WBP=datasources["STATUS"]["response"]["analogV31"]; | |||
var direction = degreeToBearing(W_A); | |||
let NBP=WBP; | |||
if (NBP==100){NBP='full'}; | |||
return ` | |||
<br> | |||
<span style="float:right;margin-right:15px;" class="glyphicons glyphicons-battery-${NBP}"></span> | |||
<span style="float:left;margin-left:10px;" class="glyphicons glyphicons-compass x2"></span> | |||
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${direction}</span> | |||
<br><br><br><br> | |||
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${W}</span> km/h | |||
<span style="float:right;margin-right:10px;">km/h</span> | |||
<span style="float:right;margin-right:15px;font-weight: bold; font-size: 2.5em;">${Gust}</span> | |||
<br><br><br> | |||
<span style="float:left;margin-left:20px;font-weight: bold;">Vent</span> | |||
<span style="float:right;margin-right:10px;font-weight: bold;">Rafale</span> | |||
`; | `; | ||
</source> | </source> | ||
Ligne 604 : | Ligne 655 : | ||
Cette sortie virtuelle pourrait alors être affichée sur le dashboard, vous indiquant lorsque l'aération d'une pièce est requise. | Cette sortie virtuelle pourrait alors être affichée sur le dashboard, vous indiquant lorsque l'aération d'une pièce est requise. | ||
Je vous laissse méditer là-dessus. | Je vous laissse méditer là-dessus. | ||
Ligne 620 : | Ligne 661 : | ||
sources : le code php est basé sur celui de Cédric « [http://www.maison-et-domotique.fr/ Maison et Domotique] » et de Zebk « http://www.eb-home.eu » | sources : le code php est basé sur celui de Cédric « [http://www.maison-et-domotique.fr/ Maison et Domotique] » et de Zebk « http://www.eb-home.eu » | ||
Je l'ai remodifié pour l'adaptation à l'IPX800. | Je l'ai remodifié pour l'adaptation à l'IPX800. | ||
== Historique des versions== | |||
11/03/2018 : version initiale | |||
27/03/2019 : modification des formules sur le module extérieur pour prise en compte des températures négatives |
Version actuelle datée du 22 décembre 2021 à 19:34
| |||
---|---|---|---|
Nom | WS NETATMO | ||
Famille | Objets connectés | ||
Wiki créé le | 11/03/2018 | ||
Wiki mis à jour le | 27/03/2019 | ||
Auteur | fgtoul |
Présentation
La station Netatmo peut être consultée à distance à l'aide de l'API. Nous allons voir comment récupérer les données afin d'interagir avec notre IPX800 V4.
Il sera nécessaire d'écrire un script qui aura pour tâche de
- se connecter à l'API de Netatmo,
- récupérer les données des différents modules (extérieur, intérieurs, pluviomètre, ...),
- envoyer les données à l'IPX800 V4.
J'ai choisi d'écrire un script en Php que j'hébergerai sur mon NAS Synology, mais vous pouvez tout à fait héberger ce script chez votre FAI si vous ne disposez ni de NAS, ni de serveur web.
Il y a deux méthodes possibles pour envoyer les données de la station vers l'IPX800.
- Créer une source de données Json ou Xml sur son serveur à partir du script.
Une datasource peut alors être ajoutée sur l'IPX800, les widget affichent les données.
Cette méthode présente plusieurs inconvénients :
- les données sont inutilisables dans les scenarii
- il est possible que l'IPX800 ne puisse pas récupérer les données à cause du "Cross-domain policy". C'est tout à fait contournable en utilisant un reverse proxy et en installant les entêtes CORS sur le serveur, mais pas à la portée de tout le monde. Pour information, le Synology ne dispose pas des entêtes CORS par défaut. Il faut les installer si vous souhaitez générer une source de données locale. - Utiliser l'API de l'IPX800 pour envoyer les données dans les entrées analogiques virtuelles. De cette manière, les données peuvent être utilisées dans les scènes, les notifications, etc.
J'ai donc choisi d'envoyer les données Netatmo via l'API.
Prérequis
- Vous devez avoir une station météo Netatmo en fonctionnement,
- vous devez avoir la possibilité d'héberger un script Php sur un serveur local ou sur votre site personnel (FAI, ...),
- vous devez avoir un compte créé chez Netatmo, pour visualiser les données de votre station,
- vous devez posséder une IPX800 V4 en fonctionnement,
- vous devez avoir un minimum de connaissance en développement,
- vous devez savoir créer une redirection de port sur votre box ou routeur dans le cas où vous hébergez votre script à l'extérieur.
Accès à l'API Netatmo
Vous allez d'abord créer une application sur le site de développement Netatmo afin d'obtenir vos identifiants pour l'API.
Connectez vous avec vos identifiants Netamo
cliquez sur le bouton de création d'une application
renseignez le nom et la description puis validez
notez les identifiants générés pour votre application
- Client ID
- Client secret
Ces informations seront utilisées dans le script Php
Le script PHP
Le script
Voici le code que vous devez copier et coller dans l'environnement Web de votre serveur.
Si vous avez un Synology comme moi, les paquets Webstation et Php doivent être installés et activés.
Pour ma part, j'ai créé un dossier Netatmo dans mon dossier Web, j'y ai sauvegardé le script sous le nom "netatmo2push.php".
Les données Json récupérées pourraient être apparentées à des tableaux de valeurs. Il aurait donc été logique de récupérer les données sous la forme de tableaux (Array) également. Le code aurait été plus léger, mais moins lisible.
Pour la compréhension et pour rendre le code plus facilement adaptable par un grand nombre parmi vous, j'ai vonlontairement programmé la récupération des données dans des variables au nom explicite, sans utiliser les tableaux.
<?php
//renseignez vos identifiants ci-dessous
$password="Votre_mot_de_passe_Netatmo";
$username="Votre_identifiant_Netatmo";
$app_id = "Votre_Client_ID";
$app_secret ="Votre_Client_Secret";
$IP_IPX800="Adresse_IP_IPX800:Port";
$API_key="Votre_Key_IPX800";
//---fin de paramétrage--
//---Début procédure authentification---------------
$token_url = "https://api.netatmo.net/oauth2/token";
$postdata = http_build_query(
array(
'grant_type' => "password",
'client_id' => $app_id,
'client_secret' => $app_secret,
'username' => $username,
'password' => $password
)
);
$options = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($options);
$response = file_get_contents($token_url, false, $context);
$params = null;
$params = json_decode($response, true);
$api_url = "https://api.netatmo.net/api/getuser?access_token=" . $params['access_token'];
$requete = file_get_contents($api_url);
//---Récupération des données JSON---------
$url_devices = "https://api.netatmo.net/api/devicelist?access_token=" . $params['access_token'];
$resultat_device = file_get_contents($url_devices);
//décommentez les 2 lignes suivantes pour voir les données JSON renvoyées par l'API Netatmo
//echo $resultat_device;
//exit();
$json_devices = json_decode($resultat_device,true);
function Batterie1($valeur){
$T1=array(0,10,25,50,75,100);
$valeur=intval(0.002*$valeur-6);
if ($valeur>=5){
$valeur= 5;
}else if ($valeur<1){
$valeur=1;
}
return $T1[$valeur];
}
function Batterie2($valeur){
$T2=array(0,10,25,50,75,100);
$valeur=intval(0.0024*$valeur-8.6341);
if ($valeur>=5){
$valeur= 5;
}else if ($valeur<1){
$valeur=1;
}
return $T2[$valeur];
}
//Module extérieur
$ext_temp = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Temperature"]) * 10 +1000;
$ext_temp_min = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["min_temp"]) * 10+1000;
$ext_temp_max = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["max_temp"]) * 10+1000;
$ext_humidite = floatval($json_devices["body"]["modules"][0]["dashboard_data"]["Humidity"]) * 10+1000;
$ext_battery = Batterie1(floatval($json_devices["body"]["modules"][0]["battery_vp"]));
//module 1
$M1_temp = floatval($json_devices["body"]["modules"][1]["dashboard_data"]["Temperature"]) * 10;
$M1_temp_min = floatval($json_devices["body"]["modules"][1]["dashboard_data"]["min_temp"]) * 10;
$M1_temp_max = floatval($json_devices["body"]["modules"][1]["dashboard_data"]["max_temp"]) * 10;
$M1_humidite = floatval($json_devices["body"]["modules"][1]["dashboard_data"]["Humidity"]) * 10;
$M1_battery = Batterie2(floatval($json_devices["body"]["modules"][1]["battery_vp"]));
$M1_CO2=floatval($json_devices["body"]["modules"][1]["dashboard_data"]["CO2"]);
//module 2
$M2_temp = floatval($json_devices["body"]["modules"][2]["dashboard_data"]["Temperature"]) * 10;
$M2_temp_min = floatval($json_devices["body"]["modules"][2]["dashboard_data"]["min_temp"]) * 10;
$M2_temp_max = floatval($json_devices["body"]["modules"][2]["dashboard_data"]["max_temp"]) * 10;
$M2_humidite = floatval($json_devices["body"]["modules"][2]["dashboard_data"]["Humidity"]) * 10;
$M2_battery = Batterie2(floatval($json_devices["body"]["modules"][2]["battery_vp"]));
$M2_CO2=floatval($json_devices["body"]["modules"][2]["dashboard_data"]["CO2"]);
//module 3 : Pluviomètre
$M3_Rain = floatval($json_devices["body"]["modules"][3]["dashboard_data"]["Rain"]) * 1000;
$M3_Rain_24 = floatval($json_devices["body"]["modules"][3]["dashboard_data"]["sum_rain_24"]) * 1000;
$M3_Rain_1 = floatval($json_devices["body"]["modules"][3]["dashboard_data"]["sum_rain_1"]) * 1000;
$M3_battery = Batterie1(floatval($json_devices["body"]["modules"][3]["battery_vp"]));
// module 5 : Anémomètre
$M5_Wind= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["WindStrength"]); //vitesse du vent
$M5_Wind_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["WindAngle"]); //angle du vent
$M5_Gust= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["GustStrength"]); //vitesse rafale
$M5_Gust_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["GustAngle"]); //angle rafale
$M5_Wind_Max= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_str"]); //angle rafale
$M5_Wind_Max_A= floatval($json_devices["body"]["modules"][5]["dashboard_data"]["max_wind_angle"]); //Vitesse max
$M5_battery=Batterie2(floatval($json_devices["body"]["modules"][5]["battery_vp"]));
if ($M5_Wind<0){$M5_Wind=0;}
if ($M5_Wind_A<0){$M5_Wind_A=0;}
//device Station
$MS_temp = floatval($json_devices["body"]["devices"][0]["dashboard_data"]["Temperature"]) * 10;
$MS_temp_min = floatval($json_devices["body"]["devices"][0]["dashboard_data"]["min_temp"]) * 10;
$MS_temp_max = floatval($json_devices["body"]["devices"][0]["dashboard_data"]["max_temp"]) * 10;
$MS_humidite = floatval($json_devices["body"]["devices"][0]["dashboard_data"]["Humidity"]) * 10;
$MS_CO2=floatval($json_devices["body"]["devices"][0]["dashboard_data"]["CO2"]);
$MS_Pressure=floatval($json_devices["body"]["devices"][0]["dashboard_data"]["Pressure"]) * 10;
$MS_Noise=floatval($json_devices["body"]["devices"][0]["dashboard_data"]["Noise"]) * 10;
$URL_Push="http://" . $IP_IPX800 . "/api/xdevices.json?key=" . $API_key . "&SetVA01=" . $ext_temp . "&SetVA02=" . $ext_temp_min . "&SetVA03=" . $ext_temp_max . "&SetVA04=" . $ext_humidite . "&SetVA05=" . $ext_battery . "&SetVA06=" . $M1_temp . "&SetVA07=" . $M1_temp_min . "&SetVA08=" . $M1_temp_max . "&SetVA09=" . $M1_humidite . "&SetVA10=" . $M1_battery . "&SetVA11=" . $M1_CO2 . "&SetVA12=" . $M2_temp ."&SetVA13=" . $M2_temp_min . "&SetVA14=" . $M2_temp_max . "&SetVA15=" . $M2_humidite . "&SetVA16=" . $M2_battery . "&SetVA17=" . $M2_CO2 . "&SetVA18=0" . $M3_rain ."&SetVA19=0" . $M3_rain_24 . "&SetVA20=0" . $M3_rain_1 . "&SetVA21=" . $M3_battery . "&SetVA22=" . $MS_temp . "&SetVA23=" . $MS_temp_min . "&SetVA24=" . $MS_temp_max . "&SetVA25=" . $MS_humidite . "&SetVA26=" . $MS_CO2 . "&SetVA27=" . $MS_Pressure . "&SetVA28=" . $MS_Noise . "&SetVA29=" . $M5_Wind . "&SetVA30=" . $M5_Wind_A . "&SetVA31=" . $M5_Gust . "&SetVA32=" . $M5_battery;
//-- Affichage de l'URL générée--------
echo $URL_Push . "<br>";
//----Envoi des données à l'API--------
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URL_Push);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);
curl_close($ch);
?>
Les identifiants
Renseignez vos identifiants dans les huit premières lignes du code, ainsi que l'adresse IP et la clé API de votre IPX800.
Si le script est hébergé chez vous, l'adresse locale de l'IPX800 doit être renseignée.
Si vous hébergez le script chez votre FAI, il faudra renseigner l'adresse publique et le port externe permettant l'accès à l'IPX800. Au préalable, vous aurez créé une redirection sur votre box ou routeur.
Récupération des données
Le script se charge de récupérer les données de vos différents modules.
Dans mon cas, les modules sont les suivant
- ["modules"][0] correspond au module extérieur.
- ["modules"][1] correspond au 1er module intérieur additionnel.
- ["modules"][2] correspond au 2nd module intérieur additionnel.
- ["modules"][3] correspond au Pluviomètre.
- ["modules"][5] correspond à l'anémomètre.
- ["devices"][0] correspond au module principal de la station.
Pour voir à quoi correspondent les données chez vous, faites comme suit
- décommentez les lignes 42 et 43 du code
- Exécutez le script dans votre navigateur. Vous devriez obtenir l'ensemble des données JSON servies par l'API.
Sélectionnez la totalité de ces données, copiez et collez dans un visualiseur de données Json.
Cliquez sur le bouton "Tree viewer" Vous devriez alors obtenir une arborescence bien lisible de vos données. Vous devriez y retouver les différents modules avec leur index ainsi que les relevés météorologiques (dashboard_data) pour chacun d'entre eux. Le module principal de la station se trouve en bas de l'arborescence, c'est un device qui en général est identifié ["devices"][0]
Pensez à rétablir les commentaires après la manip.
Préparation des données
- Les fonctions Batterie1 et Batterie2 permettent de convertir la valeur du niveau de charge en un taux de charge (10%, 25%, 50%, 75%, 100%).
Cela permettra l'affichage de l'icône adéquate sur l'interface de l'IPX800 tout en mettant le moins de code possible sur l'IPX800 afin de le charger au munimum.
Les formules ont été déterminées grâce aux seuils fournis par Netatmo sur la page référence de l'API.
- Les relevés de températures et de pression sont effectués sous forme de nombre décimal.
Si nous envoyons ces données dans une analogique virtuelle de l'IPX800, cette dernière ignorera la partie décimale.
Nous perdrons en précision.
Afin de ne pas perdre nos décimales tout en envoyant des nombres entiers, nous multiplions ces valeurs par 10.
Sur l'IPX800, nous mettrons alors une formule en place (x / 10) sur les entrées analogiques respectives afin de rétablir la valeur d'origine.
Les données concernant le pluviomètre ayant 3 décimales, elles sont multipliées par 1000.
Envoi des données à l'IPX800
Pour envoyer les données à l'IPX800, nous utilisons son API Http.
Toutes les données sont envoyées dans des entrées analogiques virtuelles, afin d'être affichables et utilisables dans les scenarii.
Nous utilisons la commande SetVAxx que nous assemblons sous forme d'URL. Celle-ci est alors exécutée par la fonction curl().
Dans notre script, nous récupérons toutes les valeurs importantes. Vous pouvez restreindre le nombre des valeurs afin d'utiliser moins d'entrées analogiques.
Test et planification du script
Après adaptation du code, vous pouvez le tester.
Vous devriez alors obtenir l'affichage de l'URL qui a été générée afin d'envoyer les données à l'IPX800 grâce à son API.
Si le fonctionnement est correct, vous pouvez planifier une tâche afin que le script soit exécuté à intervalle régulier.
La station Netatmo envoie ses données toutes les 10 minutes. Il est donc inutile de lancer le script toutes les minutes.
Vous occuperiez inutilement
- votre réseau
- votre serveur
- votre IPX800
Personnellement, j'exécute le script toutes les 10 minutes.
Remarque : La station envoie ses mesures toutes les 10 minutes au serveur Netatmo. Si vous êtes équipés d'un anémomètre Netatmo, ne l'utilisez donc pas comme source de mesure afin que l'IPX800 rentre le store en fonction de la vitesse du vent. 10 minutes c'est long, votre store pourrait être détérioré en cas de vent fort.
hébergement du Php à l'extérieur
Si vous hébergez votre script chez votre FAI par exemple, vous pourrez faire appel au script toutes les 10 minutes à partir de votre IPX800 V4, en utilisant une sortie virtuelle clignotante ayant un Tb=600 secondes (ou 6000 1/10 èmes de secondes si vous avez activé la division Tb).
Il suffira alors d'écrire une scène qui envoit un PUSH à chaque fois que la sortie virtuelle passe OFF puis la remet ON.
Soit SVx la sortie virtuelle, voici la scène :
Evènement : NON SVx Action : ON Résultat : SVx ; PUSH (GET ; http://monFAI.com/MonDossierDistant/MonScript.php)
Le PUSH à mettre en place sur l'IPX800 :
Rappel : dans le Php, l'IP de l'IPX800 devra être sous la forme IP publique suivie du port extérieur (IP_Publique:Port)
hébergement du Php en local
Si, comme moi, vous hébergez le script sur un Synology ce qui suit vous concerne :
Dans le panneau de configuration du Synology, créons une nouvelle tâche dans le planificateur :
Renseignez le chemin de /bin/php suivi de l'option -f puis le chemin absolu vers votre page php.
Exécutez la tâche planifiée pour en vérifier le bon fonctionnement.
L'IPX800 V4 recevra les mises à jour des données toutes les 10 minutes.
Note : Avec les différentes versions de DSM et les mises à jour, le chemin vers l'exécutable peut bouger. Si la planification avec l'URL précédente ne fonctionne pas, vous pouvez utiliser la fonction Curl avec l'Url de votre script PHP. Auparavant, vérifiez que la fonction Curl est activée sur votre serveur. Vérification sur le synology, ouvrez Web Station, puis vérifiez les paramètres PHP. Activez Curl si ce n'est pas déjà fait. Reprenons maintenant l'exemple de planification précédente : curl "http://adresseIP/Netatmo/netatmo2push.php"
Sur IPX800
Les sorties analogiques virtuelles
Voici la configuration et l'utilisation des entrées analogiques virtuelles sur votre IPX800 V4.
Vous pouvez les utiliser avec des widgets standards ainsi que dans vos scènes et vos notifications.
La source de données
Dans le menu administrateur de l'interface IPX800 V4, ajoutez une source de données afin d'accèder au fichier Status.xml.
Remarque : Notez son nom en majuscules. La casse devra être respectée lors de son appel dans le code JavaScript.
Les widgets HTML
Pour chaque module de la station Netatmo, vous pouvez ajouter un widget de type HTML sur l'interface de l'IPX800 V4.
La hauteur de chaque widget est de 2 blocs.
Vous trouverez le code Javascript à coller dans chaque widget.
remarque : Vous noterez que l'analogique virtuelle n°1 est nommée analogV0 dans Status.xml, et ainsi de suite jusqu'à analogV31 pour l'entrée analogique virtuelle 32.
Le module extérieur
//MODULE EXTERIEUR
let T0=(datasources["STATUS"]["response"]["analogV0"]-1000)/10;
let Tmin0=(datasources["STATUS"]["response"]["analogV1"]-1000)/10;
let Tmax0=(datasources["STATUS"]["response"]["analogV2"]-1000)/10;
let H0=datasources["STATUS"]["response"]["analogV3"]/10;
let B0=datasources["STATUS"]["response"]["analogV4"];
let NB0=B0;
if (B0==100){NB0='full'};
return `
<br>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${T0}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 2em;">${H0}%</span>
<br><br><br>
<span style="float:left; margin-left:10px;">⇩</span><span style="font-weight: bold;">${Tmin0}°</span> <span>⇧</span><span style="font-weight: bold;">${Tmax0}°</span>
<br><br>
<span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NB0}"></span>
`;
Le module additionnel 1
//MODULE INTERIEUR ADDITIONNEL 1
let T1=datasources["STATUS"]["response"]["analogV5"]/10;
let Tmin1=datasources["STATUS"]["response"]["analogV6"]/10;
let Tmax1=datasources["STATUS"]["response"]["analogV7"]/10;
let H1=datasources["STATUS"]["response"]["analogV8"]/10;
let B1=datasources["STATUS"]["response"]["analogV9"];
let CO2_1=datasources["STATUS"]["response"]["analogV10"];
let NB1=B1;
if (B1==100){NB1='full'};
return `
<br>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${T1}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 2em;">${H1}%</span>
<br><br><br>
<span style="float:left; margin-left:10px;">⇩</span><span style="font-weight: bold;">${Tmin1}°</span> <span>⇧</span><span style="font-weight: bold;">${Tmax1}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 1.5em;">${CO2_1}ppm</span>
<br><br>
<span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NB1}"></span>
`;
Le module additionnel 2
//MODULE INTERIEUR ADDITIONNEL 2
let T2=datasources["STATUS"]["response"]["analogV11"]/10;
let Tmin2=datasources["STATUS"]["response"]["analogV12"]/10;
let Tmax2=datasources["STATUS"]["response"]["analogV13"]/10;
let H2=datasources["STATUS"]["response"]["analogV14"]/10;
let B2=datasources["STATUS"]["response"]["analogV15"];
let CO2_2=datasources["STATUS"]["response"]["analogV16"];
let NB2=B2;
if (B2==100){NB2='full'};
return `
<br>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${T2}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 2em;">${H2}%</span>
<br><br><br>
<span style="float:left; margin-left:10px;">⇩</span><span style="font-weight: bold;">${Tmin2}°</span> <span>⇧</span><span style="font-weight: bold;">${Tmax2}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 1.5em;">${CO2_2}ppm</span>
<br><br>
<span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NB2}"></span>
`;
Le module Pluviomètre
//MODULE PLUVIOMETRE
let P0=datasources["STATUS"]["response"]["analogV19"]/1000;
let P0_24=datasources["STATUS"]["response"]["analogV18"]/1000;
//let P0_1=datasources["STATUS"]["response"]["analogV19"]/1000;
let BP=datasources["STATUS"]["response"]["analogV20"];
let NBP=BP;
if (BP==100){NBP='full'};
return `
<br>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${P0.toFixed(1)}</span> mm/h
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 2.5em;">${P0_24.toFixed(1)}</span>
<br><br><br>
<span style="float:left;margin-left:20px;font-weight: bold;font-size:10px;">dernière heure passée</span>
<span style="float:right;margin-right:10px;font-weight: bold;font-size:10px;">cumulé jour</span>
<br><br>
<span style="float:left; margin-left:15px;" class="glyphicons glyphicons-battery-${NBP}"></span>
`;
Le module Anémomètre
//MODULE ANEMOMETRE
var BEARINGS = ["Nord", "N-N-E", "N-E", "E-N-E", "Est", "E-S-E", "S-E", "S-S-E", "Sud", "S-S-O", "S-O", "O-S-O", "Ouest", "O-N-O", "N-O", "N-N-O"];
function degreeToBearing(degree) {
return BEARINGS[Math.floor((degree + 11.25) % 360 / 22.5)];
}
let W=datasources["STATUS"]["response"]["analogV28"];
let W_A=Math.floor(datasources["STATUS"]["response"]["analogV29"]);
//let P0_1=datasources["STATUS"]["response"]["analogV19"]/1000;
let Gust=datasources["STATUS"]["response"]["analogV30"];
let WBP=datasources["STATUS"]["response"]["analogV31"];
var direction = degreeToBearing(W_A);
let NBP=WBP;
if (NBP==100){NBP='full'};
return `
<br>
<span style="float:right;margin-right:15px;" class="glyphicons glyphicons-battery-${NBP}"></span>
<span style="float:left;margin-left:10px;" class="glyphicons glyphicons-compass x2"></span>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${direction}</span>
<br><br><br><br>
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${W}</span> km/h
<span style="float:right;margin-right:10px;">km/h</span>
<span style="float:right;margin-right:15px;font-weight: bold; font-size: 2.5em;">${Gust}</span>
<br><br><br>
<span style="float:left;margin-left:20px;font-weight: bold;">Vent</span>
<span style="float:right;margin-right:10px;font-weight: bold;">Rafale</span>
`;
Le module principal
//MODULE PRINCIPAL
let TS=datasources["STATUS"]["response"]["analogV21"]/10;
let TminS=datasources["STATUS"]["response"]["analogV22"]/10;
let TmaxS=datasources["STATUS"]["response"]["analogV23"]/10;
let HS=datasources["STATUS"]["response"]["analogV24"]/10;
let PS=datasources["STATUS"]["response"]["analogV26"]/10;
let CO2_S=datasources["STATUS"]["response"]["analogV25"];
let NOISE=datasources["STATUS"]["response"]["analogV27"]/10;
return `
<span style="float:left;margin-left:20px;font-weight: bold; font-size: 2.5em;">${TS}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 2em;">${HS}%</span>
<br><br><br>
<span style="float:left; margin-left:10px;">⇩</span><span style="font-weight: bold;">${TminS}°</span> <span>⇧</span><span style="font-weight: bold;">${TmaxS}°</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 1.5em;">${CO2_S} ppm</span>
<br><br>
<span style="float:left;margin-left:10px;font-weight: bold; font-size: 1.5em;">${PS.toFixed(0)} mbar</span>
<span style="float:right;margin-right:10px;font-weight: bold; font-size: 1.5em;">${NOISE} dB</span>
`;
Remarques : Si vos unités de mesure diffèrent de celles qui sont indiquées dans le code, vous devrez adapter les widgets. Pour vérifier les unitès en vigueur sur votre station, vous pouvez décommenter les lignes 42 et 43 du script PHP afin d'afficher les données Json. Dans la rubrique {User}, vous retrouverez ces différents paramètres
extrait de la doc Netatmo : Relevant user related information unit : 0 -> metric system, 1 -> imperial system windunit: 0 -> kph, 1 -> mph, 2 -> ms, 3 -> beaufort, 4 -> knot pressureunit: 0 -> mbar, 1 -> inHg, 2 -> mmHg lang: user locale reg_locale: user regional preferences (used for displaying date) country feel_like: algorithm used to compute feel like temperature, 0 -> humidex, 1 -> heat-index
Les scènes
Comme annoncé plus haut, nous pouvons utiliser les mesures dans nos scènes, afin d'interagir avec notre envrironnement domotique. Pour notre exemple, nous allons demander à l'IPX800 V4 de surveiller l'état des batteries de nos modules, ainsi que la qualité de l'air ambiant dans nos pièces.
Prérequis : vous devez avoir configuré les entrées analogiques conformément au tableau ci-dessus.
Surveillance des batteries
Le niveau de charge des batteries est envoyé avec les valeurs 10, 25, 50, 75 et 100.
Nous allons donc écrire une scène qui enverra une notification lorsque l'une des batteries atteindra la valeur 10 (Low battery).
Rappel de fonctionnement des seuils sur les analogiques : Dans une scène, l'action est exécutée si la condition est vraie; Par défaut, un périphérique analogique passe à l'état VRAI si le seuil haut est franchi, ce qui signifie que l'action est exécutée si le seuil haut est franchi.
Le fonctionnement demandé est donc le suivant :
Nous allons devoir inverser la logique afin que l'action soit exécutée lorsque la charge passe sous le seuil bas. Nous utiliserons le bloc NON.
Lorsque le niveau de charge atteint la valeur 10 (donc seuil bas réglé à 11 pour qu'il y ait franchissement), la notification est envoyée.
Au changement de la pile, le niveau de charge repassera à la valeur 100, et doit franchir un seuil haut, ce qui autorisera alors une autre notification lorsque la nouvelle pile sera usée à son tour.
Le seuil haut est réglé à 12, nous aurions pu mettre toute valeur comprise entre 10 et 75, mais surtout pas 100.
(100 étant la valeur maxi envoyée par le script, il n'y aurait jamais franchissement du seuil haut et donc jamais réinitialisation de la surveillance du niveau de charge. Nous recevrions alors une notification pour la première batterie usée, mais pas pour les suivantes.)
Dans les scènes, nous ne pouvons utiliser qu'un bloc d'entrée analogique virtuelle. Pour tester nos quatre batterie, nous devrons alors écrire quatre scènes.
Nous aurons alors recours aux sorties virtuelles afin de pouvoir écrire notre scène finale dont l'évènement doit dépendre de la charge des quatre batteries.
Voici les scènes :
Il suffit maintenant de vérifier l'état de nos sorties virtuelles pour déclencher ou non la notification.
Dans la scène précédente, nous utilisons le Preset n°1 des Emails. il ne reste plus qu'à Renseigner le message que nous souhaitons recevoir.
Dans le menu administrateur/périphériques, réglons le message à envoyer à chaque fois qu'au moins une des quatre sorties virtuelles sera ON.
Qualité de l'air
La station Netatmo effectue des mesures du taux de CO2 présent dans l'air ambiant (modules intérieurs).
Valeurs usuelles du CO2 :
- à l'extérieur, le CO2 est toujours de l'ordre de 400 ppm,
- une pièce aérée régulièrement maintient un niveau de CO2 inférieur à 1000
- dans une pièce fermée ou une chambre à coucher la nuit, le niveau peut dépasser 1000 ppm
- à partir de 2000 ppm, le CO2 peut provoquer somnolence et maux de tête.
Action à 1000 ppm
Pour maintenir un air d'une qualité satisfaisante, nous allons demander à l'IPX800 V4 de nous envoyer des notifications lorsque le niveau de CO2 dépasse 1000 ppm
Dans le menu administrateur/Périphériques, réglons le message à recevoir dans un preset Emails disponible. Dans mon cas, le Preset 1
Voici la scène relative au module principal :
Vous noterez la présence d'un seuil bas qui permet la réinitialisation de la surveillance après aération de la pièce (le niveau de CO2 passe sous 900 ppm)
Action à 2000 ppm
Cette fois ci, afin d'éviter les maux de tête, agissons lorsque le niveau atteint ou dépasse 2000 ppm
Le Preset (n°5 dans mon cas) :
La scène :
Vous noterez la présence d'un seuil bas qui permet la réinitialisation de la surveillance après aération de la pièce (le niveau de CO2 passe sous 1800 ppm)
Les autres modules intérieurs
Vous pouvez renseigner des presets Emails pour les autres modules.
En vous réferrant au tableau des analogiques virtuelles utilisées pour notre station météo, vous devrez créer deux scènes par module, sur le même principe que les scènes relatives au module principal.
Les notifications
Pour nos alertes CO2, nous avons utilisé les Emails.
Il est tout à fait possible d'envoyer les messages par SMS (si vous avez une extension X-GSM) ou par PUSH (vers un service comme PushingBox)
Il vous appartiendra de modifier les scènes en conséquence.
Pour aller plus loin
Dans les scènes, vous pourriez également activer une sortie virtuelle, qui passerait donc ON lorsque le seuil haut serait franchi, puis OFF après franchissement du seuil bas. Cette sortie virtuelle pourrait alors être affichée sur le dashboard, vous indiquant lorsque l'aération d'une pièce est requise. Je vous laissse méditer là-dessus.
sources : le code php est basé sur celui de Cédric « Maison et Domotique » et de Zebk « http://www.eb-home.eu » Je l'ai remodifié pour l'adaptation à l'IPX800.
Historique des versions
11/03/2018 : version initiale
27/03/2019 : modification des formules sur le module extérieur pour prise en compte des températures négatives