Différences entre les versions de « Boitier Fil Pilote a base d ESP8266 »

De GCE Electronics
Aller à la navigation Aller à la recherche
Ligne 841 : Ligne 841 :
Si cette fonction a été activée via l'API "RTRN_TH" précédemment décrite, les valeurs de température et/ou d'humidité seront régulièrement reportées dans les entrées analogiques virtuelles choisies.  
Si cette fonction a été activée via l'API "RTRN_TH" précédemment décrite, les valeurs de température et/ou d'humidité seront régulièrement reportées dans les entrées analogiques virtuelles choisies.  


Pour pouvoir exploiter les valeurs en °C et en %, il faut juste déclarer les formules de conversion pour les entrées correspondantes. Pour cela il faut choisir le type "Personnalisé" et entrer les formules indiquées dans la copie d'écran ci-dessous.
Pour pouvoir exploiter les valeurs en °C et en %, il faut juste déclarer les formules de conversion pour les entrées correspondantes.
 
Pour cela il faut choisir le type "Personnalisé" et entrer les formules indiquées dans la copie d'écran ci-dessous.


[[Fichier:Entrées_analogiques.png|center]]
[[Fichier:Entrées_analogiques.png|center]]

Version du 21 février 2019 à 15:02

Boitier Fil Pilote Wifi

IMG 20181225 151243.jpg
Nom Boitier Fil Pilote Wifi
Famille Objets connectés
Wiki créé le 12/02/2019
Wiki mis à jour le 20/02/2019
Auteur Patrice Le Graverend
alias PatLeHibou

Doc v.1.7

Introduction

Les solutions de pilotage sans fil de radiateurs électrique depuis un IPX800 sont peu nombreuses. Il est possible de le faire :

Ces deux solutions présentent certaines limites :

  • portée et stabilité du pilotage et des retours d’information pour la solution Enocean ;
  • complexité d’intégration, dépendance par rapport à une société tierce pour la solution Heatzy et ouverture d’un canal de communication entre les serveurs de cette dernière et le boitier et donc le réseau local de la maison (failles de sécurité possibles).

J’ai donc décidé de créer mes propres boitiers, complètement autonomes et intégrés avec mon IPX800 v.4.

Je remercie vivement @fgtoul qui m’a mis sur le chemin de cette fabrication avec ses tutos sur l’ESP8266, pour ses précieux conseils lors de nos échanges au cours de la mise au point de ces boitiers et pour son aide dans la mise en forme de ce wiki. Merci aussi à @grocrabe avec lequel les échanges à propos des alimentations ont été riches. Je remercie également, sans pouvoir les citer tant ils sont nombreux et parfois anonymes, ceux qui partagent leur expérience sur des sites et forums divers et variés, et qui m’ont permis d’acquérir les connaissances nécessaires à la conception et la fabrication de ces petits modules.

Le principe, les objectifs

L’idée de base était d’avoir un dispositif complètement autonome permettant :

  • de commander un radiateur avec les 4 ordres de base : Confort, Eco, Hors Gel et Arrêt ;
  • de pouvoir lui intégrer un capteur de mesure de température et d’humidité ;
  • de pouvoir l’interroger pour avoir des retours de différentes informations : état du fil pilote, nom du dispositif, température et humidité si le capteur est présent ;
  • de pouvoir lui faire envoyer des requêtes vers l’IPX800 :
    • pour remonter les valeurs température et d'humidité dans des entrées virtuelles analogiques de l'IPX ;
    • pour changer d’état des sorties virtuelles en fonction de seuils de température et d’humidité, et donc de pouvoir déclencher des actions via l’IPX ;
  • de pouvoir complètement le paramétrer sans avoir besoin d’intervenir dans le code et devoir faire une version spécifique à chaque boitier, plus complexe à maintenir et à faire évoluer ;
  • de conserver les informations en cas de coupure de courant et de redémarrer dans l’état précédent la coupure.
 NB : l'humidité dont il est question dans cet article est, bien entendu, l'humidité relative parfois appelée hygrométrie ou hygrométrie relative. Elle mesure le pourcentage de saturation de l'air en vapeur d'eau. Cette humidité relative dépend de la température : avec la même quantité de vapeur d'eau par volume d'air, un air froid est plus humide qu'un air chaud. La température n'étant pas uniforme dans une pièce (existence de points chauds et de points froids), un taux d'humidité trop élevé va permettre la condensation sur les points froids et donc l'apparition de moisissures en ces points, même en l'absence d'infiltrations d'eau. Il est donc utile, pour conserver un logement sain de limiter ce taux d'humidité. Outre l'isolation sur ces points froids (pose de doubles vitrages, huisseries avec pont thermique, isolation des murs…), un bon renouvellement de l'air grâce à une ventilation naturelle ou mécanique et en dernier lieu le chauffage (coûteux en énergie), permet de limiter ces désagréments.

L’article

Ce wiki aborde :

  1. dans une première partie, accessible à des débutants, la fabrication du dispositif sous forme d’un ensemble prêt à monter et à utiliser directement depuis un IPX800. Il faut juste être en mesure de réaliser soi-même un circuit imprimé ou bien le faire fabriquer via une entreprise spécialisée. Les composants peuvent être achetés dans des boutiques d’électronique ou via des sites sur Internet. Il est donc également nécessaire de savoir monter et souder des composants sur une carte pour assembler le dispositif. Les schémas, typons et codes sources sont téléchargeables à partir du wiki. Je donnerai également, à titre d’exemple, la façon dont j’ai réalisé la mise en boitier.
  2. Une deuxième partie détaille les commandes http qui peuvent être envoyées au boitier pour le configurer plus finement et pouvoir exploiter toutes ses fonctionnalités (mesure de température et d’humidité), remontée d’infos sur des dépassements de seuils de température et/ou d’humidité…
  3. Une troisième partie, plus technique, pour les plus curieux et les plus initiés, détaille un peu plus le fonctionnement du programme écrit directement en C++, et non via un générateur de code comme Tuniot présenté par @fgtoul dans ses tutos.
  4. Une section en fin du Wiki, regroupe les liens vers tous les éléments nécessaires pour réaliser le dispositif (typon, code source pour Arduino IDE…)

Licence d’utilisation et de modification

Les schémas, typons et codes sources sont fournis sous licence Creative Commons BY NC SA de la part de Patrice Le Graverend ce qui signifie qu’ils peuvent être utilisés, communiqués, modifiés :

  • BY : en faisant clairement apparaître mon nom « Patrice Le Graverend » ou mon pseudo utilisé sur le forum de l’entreprise GCE Electronics « PatLeHibou » (sur le typon et dans le code source) ;
  • NC : sans en faire d’utilisation commerciale ;
  • SA : et en les repartageant dans les mêmes conditions en cas d’adaptation ou de modification.

Fichier:CC-BY-NC-SA-88x31.png

Mise en garde préalable, décharge de responsabilité

Piloter un radiateur via son fil pilote, nécessite de brancher le montage sur le secteur 220 V. Il convient donc d’adopter la plus grande prudence dans sa manipulation, son test, sa mise au point, ainsi que sa protection par rapport à l’humidité ou d’éventuels éléments conducteurs qui pourraient tomber sur le circuit.

L’auteur décline toute responsabilité en cas de dysfonctionnement du montage proposé dans ces pages ainsi que de tout dommage, matériel ou humain, pouvant survenir à l’occasion de la fabrication ou de l’utilisation de celui-ci.

Le montage électronique

L’architecture globale

Le cœur du montage repose sur un ESP8266. J’ai choisi, pour ma part, son intégration sous forme d’une carte WeMos D1 mini, plus petite que la NodeMCU LUA Lolin v.3 proposée par @fgtoul dans ses tutos et donc plus facile à intégrer dans un boitier de petite taille. Cette carte présente le même avantage d’une programmation facile via le port USB. Les pré-requis d’installation sont donc les mêmes que ceux décrits dans le tuto de @fgtoul : ESP8266 : ENVIRONNEMENT. La carte à choisir dans Arduino IDE est toutefois WeMos D1 R2 & mini au lieu de NodeMCU 1.0. Personnellement, je suis resté sur la version 2.4.1 du gestionnaire de cartes ESP8266 ayant rencontré quelques soucis avec la version 2.4.2 (recompilation systématique de tout). Je n'ai pas fait de test avec des version plus récentes (2.5.0 ou ultérieures).

Une petite carte d’alimentation autonome 230Vac / 5Vdc assure l’alimentation électrique du circuit.100px

Deux poussoirs permettent :

  • l’un, accessible depuis l’extérieur du boitier, de faire changer le radiateur d’état dans un cycle (Confort -> Eco -> Hors Gel -> Arrêt -> Confort) ;
  • l’autre, accessible uniquement en ouvrant le boitier, pour forcer un « Hard Reset » du dispositif (en cas de changement de réseau WiFi par exemple, ou de modification de la clé WPA).

Deux LEDs permettent :

  • l’une, bleue, de voir que le dispositif est en fonctionnement et d’avoir des retours d’informations sur la connexion WiFi ;
  • l’autre, bicolore rouge/vert, pour indiquer l’état du pilote : rouge = Confort, orange (rouge+vert) = Eco, Vert = Hors Gel, Eteint = Arrêt.

Un capteur DHT22 (optionnel) permet la mesure de température et d’humidité. S’il est absent, la résistance de pull-up peut être omise.

Deux optocoupleurs MOC3041 en série avec des diodes 1N4007 assurent quant à eux la délivrance des alternances positives et/ou négatives (ou leur non-délivrance) sur le fil pilote pour générer les 4 états. Merci à Pierre-Henri pour son article sur le sujet qui m’a mis sur la voie de cette intégration, plutôt qu’avec un système à relais.

Rappel sur le fonctionnement d’un fil pilote de radiateur électrique

Les 4 états de base de fonctionnement d’un radiateur muni d’un fil pilote sont liés aux états suivants sur ce fil :

  • Confort : absence de tension (c’est ce qui se passe quand le fil est « en l’air » en l’absence de pilotage, les états « Confort » et « Commandé par fil pilote » au niveau du radiateur reviennent donc au même en ce cas) ;
  • Eco : phase complète et fixe de la tension secteur sur le fil pilote (selon les radiateurs, la température de consigne peut être celle de « Confort » diminuée de quelques degrés, 3,5° bien souvent, ou une autre température, réglable sur le radiateur) ;
  • Hors Gel : demi alternance négative de la tension secteur (la température de consigne est en général descendue à 7°) ;
  • Arrêt ou Délestage : demi alternance positive de la tension secteur (le radiateur est complètement arrêté).
NB : pour recevoir les ordres du fil pilote, il faut bien entendu que le radiateur soit configuré pour les accepter. Sur certains modèles de radiateurs, même s’il n’est pas configuré pour être géré par le fil pilote, l’ordre HG et/ou AR peut primer sur le comportement demandé via le panneau de contrôle du radiateur (voir pour cela la notice technique du radiateur).

Le schéma électronique

Le schéma ci-dessous détaille le circuit électronique :

Les composants nécessaires

Les composants nécessaires pour le montage sont donc :

  • une carte WeMos D1 mini,
  • une carte d’alimentation 230Vac / 5Vdc,
  • 3 résistances de 220 Ω (pour les LEDs),
  • 2 résistances de 560 Ω (pour les optocoupleurs),
  • 2 résistances de 5,1 KΩ (pull-up pour les poussoirs),
  • 1 résistance de 4,7 KΩ (pull-up pour le capteur DHT22),
  • 1 LED bleue (de 3 mm),
  • 1 LED bicolore rouge/vert à cathode commune (de 3 mm),
  • 2 optocoupleurs MOC3041,
  • 2 diodes 1N4007,
  • un capteur DHT22 (optionnel),
  • un micro-poussoir à plat (pour le « Hard Reset »),
  • un micro-poussoir à angle droit (pour le changement d’état),
  • un bornier à 3 plots pour le raccordement au secteur et du fil pilote.

Pour rendre le DHT22 optionnel et amovible, j’ai choisi d’implanter sur la carte une prise femelle mini-jack 3,5 mm et de monter le capteur sur un connecteur jack A/V 4 bornes comme celui ci-contre.


NB : pour le câble d’alimentation, ne trouvant pas de câble 3 fils marron/bleu/noir dans le commerce, j’utilise un câble 3 x 0,75 mm² marron/bleu/jaune-vert et je noircis le fil de terre avec un marqueur pour indiquer qu’il s’agit d’un pilote et non d’une terre.

Le typon de la carte électronique en JPEG (original à 600 dpi) est présenté ci-dessous. Il est accessible, en PDF, via ce lien. Bien penser à l'imprimer en miroir pour le tirer sur transparent (un transparent tiré en mode haute qualité sur une bonne imprimante jet d'encre fonctionne très bien à l'insolation).

« Mise en boite »

Fichier:Boitier ouvert.jpg
Boitier pour pilote

Trouver un boitier adapté à l’intégration d’un circuit électronique est souvent une gageure.

Pour ma part, j’ai trouvé et choisi celui-ci, vendu par lot de 5 boitiers. Il mesure 100 mm x 60 mm x 23 mm sans son couvercle.

La carte électronique a été dimensionnée pour s’ajuster au mieux dans ce boitier.

Les percements à réaliser sont :

  • sur le dessus : 3 trous pour faire passer les 2 LEDs et le poussoir de changement d’état ;
  • sur le côté droit : 1 trou pour faire passer l’orifice de la prise jack (facultatif si le capteur DHT22 n’est pas utilisé et la prise femelle donc non montée) ;
  • sur le dessous : à gauche, un trou pour faire passer le câble d’alimentation, à droite un trou oblong pour permettre de brancher une prise micro-USB pour connecter le dispositif sur un ordinateur (pour une modification de logiciel par exemple, bien penser en ce cas à couper l’alimentation du radiateur pour ne pas avoir de conflit d’alimentations et d’endommagement possible, de la carte, ou, pire, de l’ordinateur).
NB : pour le passage de la prise micro-USB, je n’ai pas trouvé de solution plus « propre » que de percer une première succession de trous alignés de 1 mm puis de les rejoindre entre eux avec un forêt de 3 mm utilisé comme une fraise. Le trou n’a donc pas la forme trapézoïdale de ce type de prise et n’est pas très régulier. Pour obstruer au mieux la prise, j’ai placé un cache pour prise micro-USB trouvé dans le commerce.

Le positionnement des trous, dans ce boitier, est indiqué dans les schémas ci-dessous.

Dessus du boitier
passage des LEDs et du poussoir de changement d’état


Dessous du boitier
passage du fil d’alimentation et accès à la prise micro-USB


Côté droit du boitier
passage de la prise jack 3,5 mm


L’entrée de la carte se fait un peu « en force », surtout quand la prise jack est présente, ce qui permet toutefois à la carte de bien tenir dans le boitier et de ne pas avoir besoin de la visser sur les entretoises présentes au fond de la boîte. Mais cela peut être fait en perçant les trous ad-hoc dans la carte. Attention toutefois à vérifier leur positionnement par rapport aux pastilles prévues sur le circuit imprimé.

Selon les cartes WeMos, la position de la prise micro-USB peut varier légèrement, ce qui amène à revoir précisément le positionnement du passage prévu pour ce branchement lors de chaque assemblage.

Je « bloque » le fil d’alimentation à l’intérieur du boitier avec un collier autobloquant très fortement serré, afin d’éviter que le fil ne puisse ressortir du boitier et tirer sur le bornier. Mais un percement juste à la bonne dimension par rapport au câble permet de le faire passer en force, ce qui limite déjà les risques.

Pour la fixation au mur, j’utilise du double-face.

Pour ceux que cela intéresserait, je peux envoyer par message privé (MP) les références précises et les liens vers les composants et éléments utilisés. Contactez-moi pour cela en MP via le forum de GCE Electronics sur mon pseudo @PatLeHibou.

Le chargement du programme

Le code est relativement long, vu le nombre de fonctions implémentées, mais largement commenté pour en permettre une lecture et une modification facile en cas de besoin. Nous ne le détaillerons pas, mais expliquerons en fin d’article son principe dans les grandes lignes pour ceux que ces aspects intéressent. Nous nous contenterons dans cette partie de voir comment le charger sur la carte WeMos du montage pour rendre celui-ci opérationnel.

Des messages sont envoyés via le port USB et peuvent donc être visualisés via le moniteur série (à 9600 bauds) d’Arduino IDE pour suivre le déroulement précis des opérations et observer le fonctionnement du dispositif, voire le dépanner.

Le code source dans sa version la plus récente est disponible via ce lien.

Compilation et téléchargement via Arduino IDE

Comme dans les tutos proposés par @fgtoul, la compilation et le téléchargement du logiciel sur la carte peut se faire via l’application Arduino IDE. Celle-ci nécessite cependant, en plus du gestionnaire de cartes ESP8266 indiquées dans le tuto précédemment mentionné, d’installer la librairie supplémentaire « DHT sensor library for ESPx ».

NB : la librairie d’Adafruit « DHT sensor library » semble mal adaptée à l’ESP8266 et peut conduire à des dysfonctionnements concernant en particulier la bonne lecture de la température et de l’humidité. C’est, en tout cas, ce que j’ai personnellement constaté. Je l’ai donc abandonnée au profit de celle indiquée ci-dessus.

Le rattachement simplifié du boitier au réseau WiFi du logement nécessite quant à lui l'installation de la bibliothèque « WiFiManager ».

Avec ces librairies supplémentaires installées, la compilation et le téléchargement du programme sur la carte WeMos ne devraient, normalement, pas poser de problème. Et la carte devrait démarrer d’elle-même en mode « initialisation ». Si ce n’est pas le cas (LED bleue faisant un double clignotement permanent, signe qu’elle cherche à se connecter à un réseau WiFi sans y parvenir), l’appui sur le bouton de « Hard Reset » permettra de la forcer à redémarrer en mode « initialisation ». Cela peut venir d’une configuration WiFi précédente gardée en mémoire par la carte.

Initialisation du boitier

Une fois le dispositif assemblé et le programme chargé, il va être nécessaire de l’initialiser pour lui permettre de se raccorder au réseau WiFi du domicile. Cela nécessite de disposer d’un ordinateur, une tablette voire un smartphone équipé du WiFi et d’un navigateur pour pouvoir effectuer ce rattachement au réseau WiFi. Le boitier sera ensuite pleinement opérationnel pour commencer à fonctionner de manière autonome et être piloté depuis le dashboard d’un IPX800.

NB : je conseille fortement de faire cette initialisation en étant branché via le port USB pour pouvoir contrôler ce qui se passe sur le moniteur série d’Arduino IDE.

Attention : pour ne pas risquer de conflit d’alimentations, ne pas brancher le boitier sur le port USB d’un ordinateur et sur le secteur simultanément, ce qui pourrait peut-être avoir des répercussions graves (griller des composants du montage, voire le port USB de l’ordinateur).

Rattachement au réseau WiFi

Lors du premier démarrage ou après un appui sur le bouton « Hard Reset » la carte WeMos doit démarrer en mode « initialisation ». Si ce n’est pas le cas (LED bleue faisant un double clignotement permanent toutes les 0,3 s, signe que la carte croit avoir une configuration valide enregistrée), un appui sur le bouton de « Hard Reset » corrigera la chose en effaçant une éventuelle configuration WiFi précédemment enregistrée sur la carte. En mode « initialisation », le programme tire parti de la librairie « WiFiManager » qui va permettre d'obtenir des informations sur la carte (notamment l'adresse MAC) et de simplifier le rattachement au réseau. Pour cela :

  • Il place le dispositif en « Access Point WiFi » avec pour SSID (nom sous lequel le réseau est vu par les appareils) « Pilote_ » suivi des 3 derniers octets en hexadécimal de l’adresse MAC de la carte, sans clé de protection ;
  • Il donne à la carte l’adresse IP 192.168.4.1, active la fonction DHCP et attend qu'une station se connecte à ce réseau (les LEDs Link et Rouge sont allumées à pleine puissance pendant ce processus) ;
  • Il faut alors se connecter à ce « réseau » WiFi à partir d’un ordinateur, d’une tablette, ou d’un smartphone pour pouvoir configurer la carte ;
  • Une fenêtre telle que celle ci-dessous doit normalement directement s'ouvrir pour permettre l'opération. Si ce n'est pas le cas, accéder, via un navigateur, à l'adresse http://192.168.4.1
  • Le bouton « Info », permet d'obtenir les informations de la carte et notamment l'adresse MAC sous laquelle le boitier sera vu par le réseau (« Station MAC ») pour pouvoir lui affecter une adresse IP fixe via une Box par exemple et éventuellement autoriser sa connexion si une telle protection a été activée ;
  • Le bouton « Configure WiFi », va lancer un scan des réseaux WiFi accessibles et en présenter la liste avec le pourcentage de fiabilité de la connexion. Cela permet de choisir le réseau à rejoindre et d'entrer le mot de passe (un lien « Scan » permet de relancer le scan si le réseau voulu n'est pas trouvé) ;
  • Le bouton « Configure WiFi (No Scan) », permet d'entrer manuellement le SSID voulu et le mot de passe (un lien « Scan » lance un scan si besoin et ramène à la fenêtre précédente) ;
  • Si l’accès au réseau WiFi fonctionne, la LED bleue clignote lentement 5 fois pour acquitter cet accès correct, comme elle le fera à chaque mise sous tension après quelques doubles clignotements rapides pendant la connexion au réseau. Si ce n'est pas le cas, les LEDs restent éteintes (erreur par exemple dans le mot de passe entré), revenir alors en arrière pour recommencer l'opération (les messages envoyés sur le Moniteur Série d'Arduino IDE permettront d'avoir quelques informations sur ce qui se passe).
NB : la première connexion peut demander quelques dizaines de secondes avant de s'établir. Patienter 30' environ avant de conclure que le réseau n'est pas joignable, ou voir les messages renvoyés par WiFiManager (lignes commençant par « WM ») pour comprendre ce qui se passe.

Une fois cette étape passée, la carte entre dans son fonctionnement « normal », de la même façon qu’après une extinction et un allumage où elle va recharger les paramètres précédemment enregistrés et commencer par rattacher le boitier au réseau WiFi et passer en mode « pilotage de radiateur » (mode « normal »).

NB : la LED bleue (Link) fixe indique que le boitier est bien connecté à un réseau WiFi. Si cette connexion est perdue, la LED bleue s'éteint. Le boitier maintiendra l'état du Fil Pilote et on pourra faire changer celui-ci via le bouton, mais il ne pourra plus être interrogé, ni remonter de lui-même des infos et son état ne pourra pas non plus être changé via le réseau, jusqu'au rétablissement de ce dernier. Le boitier se reconnectera au réseau WiFi de lui-même dès que celui-ci sera de nouveau disponible et la LED bleue se rallumera dans ce cas.

Interfaçage avec l’IPX800

Parvenu à ce stade, le boitier est opérationnel et le mode de fonctionnement du radiateur peut être changé en appuyant sur le bouton de changement d’état (ce qui se voit au changement de couleur de la LED bicolore). Il est donc déjà possible de contrôler que le radiateur reçoit bien les ordres et les prend en compte correctement.

NB : de nombreux modèles de radiateurs disposant des ordres « Confort -1° » et « Confort -2° » peuvent mettre plusieurs secondes (jusqu’à une dizaine) avant de basculer en mode « Eco ». Cela est tout à fait normal et lié au mode de pilotage de ces états. Voir cet article pour plus de détails sur le « protocole fil pilote ».

De par sa connexion au réseau WiFi du logement, le boitier est également capable de recevoir des ordres par le réseau (sous forme de requêtes http passées sur l’adresse IP du boitier). Cela permet donc de l’interfacer avec un IPX800 sous forme d’un widget dans un dashboard.

Le widget pour un radiateur

Comme toujours en pareil cas, c’est un widget HTML contenant du code JavaScript qui va permettre l’affichage de l’état et le pilotage du radiateur via l’interface graphique de l’IPX. Ce premier widget n’affiche pas les informations de température et d’humidité, car à ce stade, la présence du capteur, si elle est effective, n’a pas encore été déclarée. Nous verrons dans le chapitre suivant comment activer le capteur et donc la remontée de ces informations, et plus loin sera donné un exemple de widget pour 4 radiateurs dotés chacun d’un capteur DHT22.

Le code JavaScript à correspondant à l’exemple ci-contre est donné ci-dessous :

<script>
const IoT_Device_Name='Radiateur Local';
const IoT_Widget_Version='(v.1.1)';
const IP_IoT='http://IP_du_boitier';
var etatFP = ['Confort', 'Eco', 'Hors Gel', 'Arrêt'];
var cdeFP = ['CF', 'EC', 'HG', 'AR'];

function status_IoT () {
	url_IoT=IP_IoT+'/?';
	headers={
		'Accept': 'application/json',
		};
	fetch(url_IoT, {headers}).then(r => r.json()).then(data_state => {
		let status=data_state.status;
		for(let i=0; i < 4; i++) {
			if (i==status) {document.getElementById('fp_IoT'+i).style.color='#3FB740'} else {document.getElementById('fp_IoT'+i).style.color='#C9C5C5'};
			};
		document.getElementById('fp_IoTText').value=etatFP[status];
		document.getElementById('fp_name0').innerHTML=IoT_Device_Name+' '+IoT_Widget_Version;
		document.getElementById('fp_name0').style.color='#C9C5C5';
		});
	};

function cmd_IoT (status) {
	let url_IoT=IP_IoT+"/"+cdeFP[status];
	let headers={
		'Accept': 'application/json',
		};
	fetch(url_IoT, {headers});
    status_IoT();
	};

status_IoT();
setInterval(status_IoT, 5000);

</script>
<div id="fp_IoT0" style="margin-left:12px; margin-right:12px; margin-top:6px">
	<h2 id="fp_name0" class="section-title" style="color: '#C9C5C5'">Recherche boitier</h2>
	<p></p>
	<input value='----' id="fp_IoTText" class="bouton2" style="margin-bottom: 15px; width: 110px; background-color: rgb(68, 68, 68);" type="button"></input>
	<br>
	<span id="fp_IoT3" onclick='cmd_IoT(3);' class="police-switch" style="font-size: 25px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT2" onclick='cmd_IoT(2);' class="police-snowflake-alt2" style="font-size: 30px; position: relative; top: 3px; left: 10px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT1" onclick='cmd_IoT(1);' class="police-moon_fill" style="font-size: 25px; width: 40px; position: relative; left: 22px; color: '#C9C5C5';"></span>
	<span id="fp_IoT0" onclick='cmd_IoT(0);' class="pol-sunny18" style="font-size: 35px; width: 40px; position: relative; top: 5px; left: 30px; color: '#C9C5C5';"></span>
    <br>
    <br>
    <hr />
</div>

La seule modification à apporter dans ce code est de remplacer « IP_du_boitier » (4ème ligne) par l’adresse IP du boitier à piloter.

NB : au cas où l’on voudrait placer plusieurs widgets de ce type sur le même dashboard (correspondant à différentes zones de la maison par exemple), il y aurait lieu de modifier les Id des balises <div> et des balises <span> et tous les paramètres associés afin qu’il n’y ait pas de conflits au niveau de l’affichage. Je déconseille néanmoins cet usage qui peut être délicat à mettre au point pour ne garder qu’un widget de ce type par dashboard, en utilisant si besoin la version permettant de visualiser et piloter plusieurs boitiers qui sera donnée ci-après.

Pilotage du boitier par les scenarii

Ce pilotage est particulièrement simple puisque les changements d’état d’un boitier peuvent être pilotés par un « Push » depuis l’IPX. Il suffit d’indiquer l’adresse IP du boitier et une des commandes /CF, /EC, /HG ou /AR sur les actions « URL ON » ou « URL OFF ». En fonction des besoins, des combinaisons astucieuses de commandes sur le « On » et le « Off » d’un même push va permettre de gérer en un seul scénario 2 actions. Un exemple de « Push » permettant la bascule entre le mode Confort et le mode Eco est donné ci-dessous. Celui-ci peut être envoyé selon des horaires définis dans des plages.

Pour aller plus loin

A ce stade nous avons :

  • assemblé le montage dans son boitier ;
  • fait sa configuration initiale pour l’attacher au réseau WiFi du logement ;
  • utilisé le boitier de manière autonome par appui sur le bouton de changement d’état ;
  • intégré dans un dashboard de l’IPX800 un widget permettant de visualiser l’état du pilote et de le faire changer via l’interface graphique ;
  • paramétré un ou plusieurs « Push » pour pouvoir piloter le boitier via des scenarii.


Nous n’avons cependant pas encore exploité :

  • les remontées de température et d’humidité possibles si un capteur DHT22 a été branché ;
  • la modification de certains paramètres (luminosité des LEDs, nom du boitier sur le réseau…) ;
  • les possibilités de remontées d’informations du boitier vers l’IPX en cas de dépassement de certains seuils pour que celui-ci puisse déclencher de lui-même certaines actions.

Objet des API en fonctionnement « normal » du boitier

En fonctionnement « normal », c’est à dire hors du cycle « initialisation », le programme tourne en permanence dans une boucle qui attend des événements (appui sur un bouton, requête http, mesure périodique de température et d’humidité), ce qui va permettre de :

  • consulter les paramètres du dispositif et l’état du fil pilote ;
  • faire changer l’état du fil pilote (par le bouton ou par requête http) ;
  • provoquer un « Hard Reset » du boitier pour qu’il repasse en mode « initialisation » (par exemple en vue d’un changement de SSID ou de clé WPA sur le réseau WiFi) ;
  • renseigner ou modifier certains paramètres parmi lesquels :
    • la luminosité des LEDs ;
    • le nom du boitier ;
    • l’activation ou la désactivation du capteur DHT (il n’y a pas de détection automatique de la présence de celui-ci et il peut être installé sans que l’on veuille pour autant l’exploiter) ;
    • les paramètres de l’IPX à joindre pour remonter la température et l’humidité ou des alertes sur dépassements de certains seuils (adresse IP de l’IPX et son APIkey si celle-ci est activée) ;
    • les seuils de température et d’humidité ainsi que les sorties virtuelles que la détection de ces seuils doit faire changer d’état ;
    • les entrées analogiques virtuelles réceptrices des informations remontées ;
NB :
- activer le capteur DHT alors qu’il n’est pas installé ne générera pas d’erreur mais du retard dans l’affichage de l’état du dispositif puisqu’une vingtaine de tentatives de lecture de la température et de l’humidité vont être faites sans aboutir.
- les seuils de température sont obligatoires, mais ceux d’humidité ne le sont pas, si on ne souhaite pas surveiller ce paramètre.
- les sorties virtuelles passent à 1 quand la température descend en dessous du seuil mini et quand l’humidité passe au dessus du seuil maxi, elles passent à 0 quand la température monte au dessus du seuil maxi et quand l’humidité passe en dessous du seuil mini. Cela permet, si la même sortie virtuelle est configurée pour les 2 paramètres d’avoir la même action, par exemple allumer le chauffage pour monter la température et donc baisser l’humidité, au niveau de l’IPX qui ignorera lequel des 2 la déclenche (simplification des scéranii).
- une sortie virtuelle ou entrée analogique virtuelle peut être fixée à 0, ce qui désactive la surveillance ou la remontée du paramètre concerné. Cela peut permettre de ne surveiller que l'humidité. Par contre avoir les 2 à 0 avec la fonction activée n'a pas de sens, pour cela surveillance, même si cela ne générera pas d'erreur et ne sera pas possible pour les remontées car les entrées doivent être différentes.
  • si cette fonction a été activée lors de la compilation du programme, faire afficher (via l’USB et le moniteur série d’Arduino IDE) le contenu de l’EEPROM et la remettre complètement à 0 ou à 0xFF si besoin.

Les commandes http associées à ces API

En fonctionnement normal, différentes commandes, éventuellement associées à des paramètres, vont donc permettre de déclencher certaines actions, obtenir des informations ou régler des valeurs, comme décrit ci-dessus. La commande se passe, depuis un navigateur Web, avec la syntaxe suivante :

http://adresse_IP_du_boitier/commande_et_paramètres_éventuels

Les commandes possibles et leur syntaxe sont détaillées ci-dessous. Elles peuvent aussi, bien évidemment, être envoyées via des « Push » depuis l’IPX (par exemple pour augmenter la luminosité des LEDs dans la journée et les réduire la nuit, en fonction d’horaires ou d’un capteur de luminosité ambiante).

NB :
- les commandes et les paramètres ne sont pas sensibles à la casse et peuvent donc indifféremment être entrés en Majuscules ou minuscules ou un mélange des deux.
- afin de retrouver facilement quel boitier porte quelle adresse IP, il est fortement conseillé de fixer l’adresse IP du boitier via le service DHCP d’une Box ou d’un routeur présent sur le réseau en associant une adresse IP à l’adresse MAC de la carte. Se référer au manuel de sa Box ou du routeur pour cela. C'est même indispensable de le faire, et risqué sinon, pour l'interfaçage avec l'IPX

Toutes les commandes renvoient une réponse en JSON ce qui permet de les exploiter dans des widgets HTML via du JavaScript (c’est ce qui est fait dans le widget proposé ci-dessus).

? : status

http://adresse_IP_du_boitier/?

Cette commande retourne, sous forme d’un fichier JSON, l’état du boitier et ses paramètres sous la forme :

{
     "device" : "Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 10.10,
     "humi" : 75.60,
     "IP_IPX" : "XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key=Mon_API_Key&",
     "th_control" : {
       "status" : "On",
       "periodicity" : "10",
       "t_min" : "10",
       "t_max" : "12",
       "sv_te" : "39",
       "h_min" : "70",
       "h_max" : "80",
       "sv_hu" : "40"
     },
     "th_return" : {
       "status" : "On",
       "va_te" : "1",
       "va_hu" : "2"
     },
     "luminosity" : "10",
     "RSSI" : "-62"
}

Les paramètres sont relativement évidents à interpréter vu les noms choisis.

Le chiffre en regard de « status » s’interprète de la fonction suivante :

  • 0 = Confort
  • 1 = Eco
  • 2 = Hors Gel
  • 3 = Arrêt

La valeur de DHT est à « 0 » si le capteur est absent ou n’est pas utilisé (les valeurs « temp » et « humi » ne sont alors pas indiquées) et à « 1 » s’il est utilisé et présent (c’est ici que l’absence de capteur se traduira par un délai d’affichage plus long et l’indication « nan » en regard des valeurs, indiquant que la température et l’humidité n’ont pas pu être mesurés).

Le sous-paramètre « status » de « th_control » est à « Off » s’il n’y a pas de surveillance du climat, ce qui se programme en choisissant une périodicité de surveillance à 0. Les autres sous-paramètres ne sont, dans ce cas, pas affichés. Quand il est à « On » les seuils et sorties virtuelles sont indiqués.

Le paramètre « luminosity » est en « pour 1000 tours de boucle ». La valeur 10 permet d’avoir une visibilité suffisante dans des conditions d’éclairage normal. La monter sensiblement risque d’avoir un effet d’éclairage fort dans le noir. Réglé à 0 les LEDs sont complètement éteintes, ce qui est possible, mais ne permet plus aucun retour visuel sur l’état du boitier.

Le paramètre « RSSI » indique, en dBm, la puissance du signal reçu par le boitier. Une puissance inférieure à -70 dBm pourra conduire à des dysfonctionnements dus à des pertes de paquets de données.

CF : confort

Passe le pilote en mode « Confort »

EC : éco

Passe le pilote en mode « Eco »

HG : hors gel

Passe le pilote en mode « Hors Gel »

AR : arrêt

Passe le pilote en mode « Arrêt » ou « Délestage »

Dans ces 4 cas une réponse en JSON est renvoyée. Par exemple pour un ordre HG :

http://adresse_IP_du_boitier/HG

La réponse retournée est :

{
     "device" : "Nom_boitier",
     "command" : "HG",
     "status" : "2"
}

VE : version

http://adresse_IP_du_boitier/VE

Affiche en JSON, la version du boitier et du code source utilisé. Exemple :

{
     "device" : " Nom_boitier",
     "command" : "VE",
     "version" : "PatLeHibou's WiFi Heater Pilot v.2",
     "source" : "WiFi_Heater_Pilot_v.2.2c"
}

LU=valeur : réglage de la luminosité

http://adresse_IP_du_boitier/LU=valeur

Avec une valeur comprise entre 0 (extinction complète) et 1000 (allumage permanent), ce paramètre permet de fixer la luminosité des LEDs comme indiqué précédemment, afin de ne pas générer un éclairage trop fort au niveau du boitier et pouvant être gênant (la nuit dans une chambre par exemple). Toute valeur supérieur à 1000 sera ramenée à 1000. La réponse est affichée en JSON sous la forme :

{
     "device" : " Nom_boitier",
     "command" : "LU=10",
     "luminosity" : "10"
}

NM=Nom_boitier : renommage du boitier

Par défaut, le boitier est nommé « Pilote_ » suivi des 3 derniers octets de l'adresse MAC en hexadécimal, la commmande NM permet donc de donner un nom plus explicite au boitier (ex. « Rad_Chambre1 »).

http://adresse_IP_du_boitier/NM=Nouveau_nom

Change donc le nom du boitier tel qu’il est vu sur le réseau et peut être lu par l’IPX. La réponse est affichée en JSON sous la forme :

{
     "device" : "Nom_boitier",
     "command" : "NM=Nouveau_nom",
     "newname" : "Nouveau_nom"
}
NB : le nom doit avoir 16 caractères au maximum.

TH=On/Off : activation/désactivation du capteur DHT

http://adresse_IP_du_boitier/TH=[On|Off]

TH=On active le capteur DHT. Le système répond :

{
     "device" : "Nom_boitier",
     "command" : "TH=On",
     "dht" : "1"
}

TH=Off, ou n’importe quoi d’autre, le désactive. Le système répond :

{
     "device" : " Nom_boitier",
     "command" : "TH=abcd",
     "dht" : "0"
}

EP=Dump/Wipe/Fill : affichage, mise à 0 ou à 0xFF du contenu de l’EEPROM

Cette commande peut être utilisée à des fins de mise au point et de visualisation ou de suppression d'informations qui auraient pu être enregistrées précédemment dans l'EEPROM de la carte.

NB : les options « Wipe » et « Fill » doivent être utisées avec prudence, car la carte sera ensuite nommée « Pilote_fin_adresse_MAC » ou « ESP_fin_adresse_MAC » et, dans le cas d'un « Wipe », les LEDs ne s'allumeront plus, jusqu'à ce que ces paramètres aient été remodifiés.

Pour avoir accès à cette commande, il faut que la ligne de code qui permet sa reconnaissance if (Etat.substring(0, 3).equalsIgnoreCase("EP=")) {Val=9;} située vers la ligne 325 ait été décommentée avant la compilation du code et son chargement sur la carte. Cela nécessite également que le boitier soit branché en USB sur une station, et qu’Arduino IDE soit lancé avec le moniteur série pour visualiser ce qui se passe.

http://adresse_IP_du_boitier/EP=Dump

Affiche via le port série le contenu de l’EEPROM en hexadécimal et en ASCII à des fins de vérification.

http://adresse_IP_du_boitier/EP=Wipe

Remet à 0 les 512 octets de l’EEPROM et affiche le résultat pour vérification (si tous les octets ne sont pas à 0, l’EEPROM a un souci d’enregistrement et est probablement endommagée)

http://adresse_IP_du_boitier/EP=Fill

Remet à 0xFF les 512 octets de l’EEPROM et affiche le résultat pour vérification (si tous les octets ne sont pas à 0xFF, l’EEPROM a un souci d’enregistrement et est probablement endommagée)

NB : le système ne reboote volontairement pas tout seul après un « Wipe » ou un « Fill » pour permettre d’éventuelles autres opérations. Pour le faire redémarrer, il est possible d’appuyer sur le bouton « Hard Reset » ou de débrancher et rebrancher le boitier.

IPX_CFG?paramètres : configuration de l’IPX

Cette commande nécessite au moins un paramètre IP_IPX sous forme d’une chaine de caractères représentant l’adresse IP de l’IPX800 à joindre pour remonter les informations de surveillance du climat de la pièce. Les guillemets peuvent être omis autour de l’adresse IP.

Exemple :

http://adresse_IP_du_boitier/IPX_CFG?IP_IPX=192.168.1.100

Si la clef API est activée sur l’IPX (se référer à la documentation de l’IPX800 pour cela), il faut indiquer la valeur de celle-ci et ajoutant après l’adresse IP : « &APIkey=Mon_API_key »

Exemple :

http://adresse_IP_du_boitier/IPX_CFG?IP_IPX=192.168.1.100&APIkey=Ma_clé_API

NB : la validité et la syntaxe de l’adresse IP n’est pas contrôlée par le programme, mais vous pouvez la visualiser par la commande « ? » (status).

CTRL_TH?paramètres : paramétrage de la surveillance du climat

Cette commande permet d’activer/désactiver la surveillance du climat et de fixer les paramètres pour ce faire. Elle nécessite a minima le premier paramètre « PERIOD » qui indique, en minutes, la périodicité de la mesure de la température et de l’humidité. Si celui-ci est passé à 0, les autres paramètres éventuels sont ignorés et la fonction de surveillance est désactivée. Si celui-ci dépasse 1440 (plus de 24h), une erreur est renvoyée.

Si PERIOD est compris entre 1 et 1440, les 3 paramètres suivants sont lus. Ils doivent être, dans l’ordre :

  • T_MINI : seuil minimum de température (doit être comprise entre 0 et 20)
  • T_MAXI : seuil maximum de température (doit être comprise entre 0 et 30 et supérieure à T_MINI)
  • SV_TE : sortie virtuelle recevant les infos (doit être inférieure ou égale à 128)

S’il n’y a pas d’autres paramètres derrière, l’humidité mini est fixée à 0, la maxi à 100 et la sortie virtuelle à 0 (n’existe pas dans l’IPX). S’il y en a, les 3 paramètres suivants sont lus et doivent être, dans l’ordre :

  • H_MINI : seuil minimum d’humidité (doit être comprise entre 0 et 100)
  • H_MAXI : seuil maximum d’humidité (doit être comprise entre 0 et 100 et supérieure à H_MINI)
  • SV_HU : sortie virtuelle recevant les infos (doit être inférieure ou égale à 128)

La cohérence des données est vérifiée et génère une erreur sous forme d’une réponse en JSON en cas de problème, sans altérer la configuration précédente.

Exemples :

http://adresse_IP_du_boitier/CTRL_TH?PERIOD=0

Désactive la surveillance. Réponse :

{
     "device" : " Nom_boitier",
     "command" : "CTRL_TH?PERIOD=0",
     "status" : "CTRL_TH Successfully deactivated"
}

La commande « ? » (status) renverra :

{
     "device" : " Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.40,
     "IP_IPX" : " XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key= Mon_API_key&",
     "th_control" : {
       "status" : "Off"
     },
     "th_return" : {
       "status" : "Off"
     },
     "luminosity" : "10"
     "RSSI" : "-62"
}
http://adresse_IP_du_boitier/CTRL_TH?PERIOD=10&T_MINI=10&T_MAXI=12&SV_TE=30

Surveille la température toutes les 10 minutes et fait passer la sortie virtuelle 30 à 1 si la température mesurée devient inférieure à 10° et la fait passer à 0 si la température dépasse les 12°. Réponse :

{
     "device" : " Nom_boitier",
     "command" : "CTRL_TH?PERIOD=10&T_MINI=10&T_MAXI=12&SV_TE=33",
     "status" : "CTRL_TH Successfull"
}

La commande « ? » (status) renverra :

{
     "device" : "Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.10,
     "IP_IPX" : "XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key=Mon_API_key&",
     "th_control" : {
       "status" : "On",
       "periodicity" : "10",
       "t_min" : "10",
       "t_max" : "12",
       "sv_te" : "30",
       "h_min" : "0",
       "h_max" : "100",
       "sv_hu" : "0"
     },
     "th_return" : {
       "status" : "Off"
     },
     "luminosity" : "10"
     "RSSI" : "-62"
}
http://adresse_IP_du_boitier/CTRL_TH?PERIOD=30&T_MINI=18&T_MAXI=20&SV_TE=60&H_MINI=60&H_MAXI=70&SV_HU=61

Surveille la température et l’humidité toutes les 30 minutes et fait passer la sortie virtuelle 60 à 1 si la température mesurée devient inférieure à 18° et à 0 si la température dépasse les 20°, et fait passer la sortie virtuelle 61 à 1 si l’humidité mesurée dépasse les 75% et à 0 si elle devient inférieure 65%. Réponse :

{
     "device" : "Nom_boitier",
     "command" : "CTRL_TH?PERIOD=30&T_MINI=18&T_MAXI=20&SV_TE=60&H_MINI=65&H_MAXI=75&SV_HU=61",
     "status" : "CTRL_TH Successfull"
}

La commande « ? » (status) renverra :

{
     "device" : "Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.10,
     "IP_IPX" : "XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key=Mon_API_key&",
     "th_control" : {
       "status" : "On",
       "periodicity" : "30",
       "t_min" : "10",
       "t_max" : "12",
       "sv_te" : "60",
       "h_min" : "65",
       "h_max" : "75",
       "sv_hu" : "61"
     },
     "th_return" : {
       "status" : "Off"
     },
     "luminosity" : "10"
     "RSSI" : "-62"

RTRN_TH?paramètres : paramétrage des remontées du climat

Cette commande permet d’activer/désactiver la remontée d'informations relatives au climat et de fixer les paramètres pour ce faire. Elle est complètement indépendante de la commande de contrôle du climat et de remontée d'alertes sur des dépassements de seuils de température ou d'humidité. Son seul point commun est de nécessiter que les informations concernant l'IPX destinataire des requêtes aient été renseignées.

Elle nécessite a minima le premier paramètre « PERIOD » qui indique, en minutes, la périodicité de la mesure de la température et de l’humidité. Si celui-ci est passé à 0, les autres paramètres éventuels sont ignorés et la fonction de surveillance est désactivée. Si celui-ci dépasse 1440 (plus de 24h), une erreur est renvoyée.

Si PERIOD est compris entre 1 et 1440, le paramètre suivant est lu. Il doit impérativement être VA_TE : entrée analogique virtuelle recevant les infos de température (doit être inférieure ou égale à 32)

S’il n’y a pas d’autre paramètre derrière, ou si celui-ci n'est pas VA_HU, l'entrée analogique virtuelle est fixée à 0.

S'il y a un troisième paramètre, que celui-ci est bien VA_HU et que la valeur indiquée est différente de VA_TE, cela fixe l'entrée analogique virtuelle recevant les infos d'humidité (doit être inférieure ou égale à 32)

La cohérence des données est vérifiée, car remonter deux informations analogiques différentes dans la même entrée n'aurait aucun sens, et génère une erreur sous forme d’une réponse en JSON en cas de problème, sans altérer la configuration précédente.

Exemples :

http://adresse_IP_du_boitier/RTRN_TH?PERIOD=0

Désactive les remontées. Réponse :

{
     "device" : " Nom_boitier",
     "command" : "RTRN_TH?PERIOD=0",
     "status" : "RTRN_TH Successfully deactivated"
}

La commande « ? » (status) renverra :

{
     "device" : " Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.40,
     "IP_IPX" : " XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key= Mon_API_key&",
     "th_control" : {
       "status" : "Off"
     },
     "th_return" : {
       "status" : "Off"
     },
     "luminosity" : "10"
     "RSSI" : "-62"
}
http://adresse_IP_du_boitier/RTRN_TH?PERIOD=10&VA_TE=1

Fait remonter la température toutes les 10 minutes vers l'entrée analogique virtuelle 1. Réponse :

{
     "device" : " Nom_boitier",
     "command" : "RTRN_TH?PERIOD=10&VA_TE=1",
     "status" : "RTRN_TH Successfull"
}

La commande « ? » (status) renverra :

{
     "device" : "Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.10,
     "IP_IPX" : "XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key=Mon_API_key&",
     "th_control" : {
       "status" : "Off"
     },
     "th_return" : {
       "status" : "On",
       "periodicity" : "10",
       "va_te" : "1",
       "va_hu" : "0"
     },
     "luminosity" : "10"
     "RSSI" : "-62"
}
http://adresse_IP_du_boitier/RTRN_TH?PERIOD=30&VA_TE=16&SV_HU=17

Fait remonter la température et l'humidité toutes les 30 minutes vers les entrées analogiques virtuelles 16 et 17 respectivement. Réponse :

{
     "device" : "Nom_boitier",
     "command" : "RTRN_TH?PERIOD=30&VA_TE=16&SV_HU=17",
     "status" : "RTRN_TH Successfull"
}

La commande « ? » (status) renverra :

{
     "device" : "Nom_boitier",
     "command" : "?",
     "status" : "2",
     "dht" : "1",
     "temp" : 11.90,
     "humi" : 64.10,
     "IP_IPX" : "XXX.YYY.ZZZ.TTT",
     "IPX_API_Prefix" : "/api/xdevices.json?key=Mon_API_key&",
     "th_control" : {
       "status" : "Off"
     },
     "th_return" : {
       "status" : "On",
       "periodicity" : "30",
       "va_te" : "16",
       "va_hu" : "17"
     },
     "luminosity" : "10"
     "RSSI" : "-62"

Interfaçage avec l’IPX800 de plusieurs boîtiers dotés de capteur DHT22

Une fois les dispositifs mis en service et leurs différents paramètres réglés, ceux-ci peuvent-être intégrés dans l’IPX800 v.4 afin de :

  • voir l’état des pilotes, et éventuellement les valeurs de température et d’humidité si des capteurs DHT22 sont présents et activés, et faire changer chaque pilote d’état (et donc le radiateur associé), au travers d’un widget ;
  • piloter par scenarii le fonctionnement des radiateurs (présence/absence, jour/nuit…) ;
  • gérer dans des scenarii les remontées d’informations pouvant être faites par le boitier en cas de dépassement des seuils de température ou d’humidité pour déclencher des actions.

Le widget pour 4 pilotes

De la même façon que pour un unique radiateur sans capteur, c’est un widget HTML contenant du code JavaScript qui va permettre l’affichage de l’état et le pilotage des radiateurs via l’interface graphique de l’IPX.

Le code JavaScript est donné ci-dessous pour 4 boitiers, tous capables de mesurer température et humidité. L’affichage ressemble à cela dans l’interface de l’IPX.

Selon qu’il y a plus ou moins de 4 boitiers à afficher dans le même widget, le code est à adapter en conséquence.

Si certains boitiers n’ont pas de capteur DHT22, les lignes correspondantes peuvent être supprimées dans la partie « affichage ».

Le tableau IP_IoT, au début du code, est à renseigner avec les valeurs des adresses IP des dispositifs sur le réseau.

<script>
var IP_IoT=['http://IP_boitier_1', 'http://IP_boitier_2', 'http://IP_boitier_3', 'http://IP_boitier_4'];
var etatFP = ['Confort', 'Eco', 'Hors Gel', 'Arrêt'];
var cdeFP = ['CF', 'EC', 'HG', 'AR'];

function rename (name) {
	if (name == Nom_boitier_1') return 'Nom Boitier 1 pour IPX';
	if (name == Nom_boitier_2') return 'Nom Boitier 2 pour IPX';
	if (name == Nom_boitier_3') return 'Nom Boitier 3 pour IPX';
	if (name == Nom_boitier_4') return 'Nom Boitier 4 pour IPX';
	return name;
	};

function status_IoT (num) {
	url_IoT=IP_IoT[num]+'/?';
	headers={
		'Accept': 'application/json',
		};
	fetch(url_IoT, {headers}).then(r => r.json()).then(data_state => {
		let status=data_state.status;
		for(let i=0; i < 4; i++) {
			if (i==status) {document.getElementById('fp_IoT'+i+'_'+num).style.color='#3FB740'} else {document.getElementById('fp_IoT'+i+'_'+num).style.color='#C9C5C5'};
			};
		document.getElementById('fp_IoTText'+num).value=etatFP[status];
		document.getElementById('fp_name'+num).innerHTML=rename(data_state.device);
		document.getElementById('fp_name'+num).style.color='#C9C5C5';
		document.getElementById('temp_IoT'+num).innerHTML="Température : "+data_state.temp+" °C";
		document.getElementById('temp_IoT'+num).style.color='#C9C5C5';
		document.getElementById('humi_IoT'+num).innerHTML="Humidité    : "+data_state.humi+" %";
		document.getElementById('humi_IoT'+num).style.color='#C9C5C5';
		});
	};

function cmd_IoT (boitier, status) {
	let url_IoT=IP_IoT[boitier]+"/"+cdeFP[status];
	let headers={
		'Accept': 'application/json',
		};
	fetch(url_IoT, {headers});
    status_IoT(boitier);
	};

function status_IoTs () {
   for (let i=0; i < 4; i++) {
        status_IoT(i);
		}
	};

status_IoTs();
setInterval(status_IoTs, 5000);

</script>
<div id="fp_IoT0" style="margin-left:12px; margin-right:12px; margin-top:6px">
	<h2 id="fp_name0" class="section-title" style="color: '#C9C5C5'">Recherche boitier</h2>
	<p></p>
	<input value='----' id="fp_IoTText0" class="bouton2" style="margin-bottom: 15px; width: 110px; background-color: rgb(68, 68, 68);" type="button"></input>
	<br>
	<span id="fp_IoT3_0" onclick='cmd_IoT(0,3);' class="police-switch" style="font-size: 25px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT2_0" onclick='cmd_IoT(0,2);' class="police-snowflake-alt2" style="font-size: 30px; position: relative; top: 3px; left: 10px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT1_0" onclick='cmd_IoT(0,1);' class="police-moon_fill" style="font-size: 25px; width: 40px; position: relative; left: 22px; color: '#C9C5C5';"></span>
	<span id="fp_IoT0_0" onclick='cmd_IoT(0,0);' class="pol-sunny18" style="font-size: 35px; width: 40px; position: relative; top: 5px; left: 30px; color: '#C9C5C5';"></span>
    <br><br>
    <div id="temp_IoT0">Température</div>
    <div id="humi_IoT0" style="color: '#C9C5C5'">Humidité</div>
    <hr />
</div>
<div id="fp_IoT1" style="margin-left:12px; margin-right:12px; margin-top:6px">
	<h2 id="fp_name1" class="section-title" style="color: '#C9C5C5'">Recherche boitier</h2>
	<p></p>
	<input value='----' id="fp_IoTText1" class="bouton2" style="margin-bottom: 15px; width: 110px; background-color: rgb(68, 68, 68);" type="button"></input>
	<br>
	<span id="fp_IoT3_1" onclick='cmd_IoT(1,3);' class="police-switch" style="font-size: 25px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT2_1" onclick='cmd_IoT(1,2);' class="police-snowflake-alt2" style="font-size: 30px; position: relative; top: 3px; left: 10px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT1_1" onclick='cmd_IoT(1,1);' class="police-moon_fill" style="font-size: 25px; width: 40px; position: relative; left: 22px; color: '#C9C5C5';"></span>
	<span id="fp_IoT0_1" onclick='cmd_IoT(1,0);' class="pol-sunny18" style="font-size: 35px; width: 40px; position: relative; top: 5px; left: 30px; color: '#C9C5C5';"></span>
    <br><br>
    <div id="temp_IoT1">Température</div>
    <div id="humi_IoT1" style="color: '#C9C5C5'">Humidité</div>
    <hr />
</div>
<div id="fp_IoT2" style="margin-left:12px; margin-right:12px; margin-top:6px">
	<h2 id="fp_name2" class="section-title" style="color: '#C9C5C5'">Recherche boitier</h2>
	<p></p>
	<input value='----' id="fp_IoTText2" class="bouton2" style="margin-bottom: 15px; width: 110px; background-color: rgb(68, 68, 68);" type="button"></input>
	<br>
	<span id="fp_IoT3_2" onclick='cmd_IoT(2,3);' class="police-switch" style="font-size: 25px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT2_2" onclick='cmd_IoT(2,2);' class="police-snowflake-alt2" style="font-size: 30px; position: relative; top: 3px; left: 10px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT1_2" onclick='cmd_IoT(2,1);' class="police-moon_fill" style="font-size: 25px; width: 40px; position: relative; left: 22px; color: '#C9C5C5';"></span>
	<span id="fp_IoT0_2" onclick='cmd_IoT(2,0);' class="pol-sunny18" style="font-size: 35px; width: 40px; position: relative; top: 5px; left: 30px; color: '#C9C5C5';"></span>
    <br><br>
    <div id="temp_IoT2">Température</div>
    <div id="humi_IoT2" style="color: '#C9C5C5'">Humidité</div>
    <hr />
</div>
<div id="fp_IoT3" style="margin-left:12px; margin-right:12px; margin-top:6px">
	<h2 id="fp_name3" class="section-title" style="color: '#C9C5C5'">Recherche boitier</h2>
	<p></p>
	<input value='----' id="fp_IoTText3" class="bouton2" style="margin-bottom: 15px; width: 110px; background-color: rgb(68, 68, 68);" type="button"></input>
	<br>
	<span id="fp_IoT3_3" onclick='cmd_IoT(3,3);' class="police-switch" style="font-size: 25px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT2_3" onclick='cmd_IoT(3,2);' class="police-snowflake-alt2" style="font-size: 30px; position: relative; top: 3px; left: 10px; width: 40px; color: '#C9C5C5';"></span>
	<span id="fp_IoT1_3" onclick='cmd_IoT(3,1);' class="police-moon_fill" style="font-size: 25px; width: 40px; position: relative; left: 22px; color: '#C9C5C5';"></span>
	<span id="fp_IoT0_3" onclick='cmd_IoT(3,0);' class="pol-sunny18" style="font-size: 35px; width: 40px; position: relative; top: 5px; left: 30px; color: '#C9C5C5';"></span>
    <br><br>
    <div id="temp_IoT3">Température</div>
    <div id="humi_IoT3" style="color: '#C9C5C5'">Humidité</div>
 </div>

Explication du code JavaScript

La fonction « rename (name) » permet de faire traduire le nom du boitier, tel que vu sur le réseau (paramètre « DEVICE_NAME » de l’initialisation, « Nom_boitier » de la commande /NM= et paramètre « device » dans les réponses JSON), en un nom éventuellement plus explicite dans l’interface graphique de l’IPX. Dans la version pour un seul pilote, le nom était entré « en dur » dans le code JavaScript.

La fonction « status_IoT (num) » interroge un boitier particulier identifié par son n° dans le widget pour remonter son état et les valeurs de température et d’humidité si le capteur DHT est présent et les afficher dans la zone correspondante du widget. Elle est identique à la fonction du même nom du widget pour un pilote, à ceci près que l’on indique le n° du boitier à piloter.

NB : attention en JavaScript, comme dans de nombreux langages de programmation, le premier élément d’un tableau porte l’indice 0. Quatre boitiers portent donc les n° 0, 1, 2 et 3.

La fonction « cmd_IoT (boitier, status) », permet, lors du clic sur un des pictogrammes d’état d’un des boitiers, de faire changer le boitier d’état (et donc le radiateur) en lui en envoyant l’ordre via une requête http. Elle aussi est similaire à celle de la version pour un seul boitier, mais avec la possibilité d’indiquer le n° du boitier commandé.

La fonction « status_IoTs () » permet d’interroger successivement et régulièrement les différents boitiers toutes les 5 secondes depuis une seule fonction via la commande « setInterval (status_IoTs, 5000) » (la périodicité peut être changée).

NB : il est assez déconseillé de placer plusieurs widgets de ce type sur le même dashboard (correspondant à différentes zones de la maison par exemple), car les Id des balises <div> et <span> risquent d’entrer en conflit, de même que les fonctions. La mise au point et le déboguage en sera complexifié. Il vaudrait donc mieux les placer sur des dashboards différents ou augmenter le nombre de pilotes surveillés dans le même widget en l’adaptant.

Pilotage des boitiers par les scenarii et actions sur remontées d’informations

Ce point a déjà été abordé précédemment. On peut juste ajouter que, si la fonction de surveillance de la température et de l’humidité est activée et correctement paramétrée (cf les explications sur les commandes IP_IPX et CTRL_TH), la ou les sorties virtuelles choisies vont changer d’état lors du franchissement de ces seuils. La détection de ce changement d’état est particulièrement simple dans un scénario et consiste juste à surveiller la sortie virtuelle voulue (éventuellement combinée avec d’autres paramètres) pour pouvoir faire déclencher une action par le scénario. Cette action pourra être un ordre « Push » à destination du même boitier ou d’un autre ou toute autre commande que l’IPX pourra piloter (fermer des volets pour garder la chaleur, passer la VMC en marche forcée pour réduire l’humidité…).

Dès lors, comme pour la bascule entre « Confort » et « Eco » selon l’heure, un unique « Push » peut gérer la bascule de Hors-Gel en Eco et retour, lors de la détection des seuils de températures (pour éviter par exemple que la température du logement descende jusqu’au 7° usuels du mode Hors Gel et limiter des problèmes d’humidité). C’est une façon particulièrement simple de le faire.

Remontée des valeurs de températures et d'humidité

Si cette fonction a été activée via l'API "RTRN_TH" précédemment décrite, les valeurs de température et/ou d'humidité seront régulièrement reportées dans les entrées analogiques virtuelles choisies.

Pour pouvoir exploiter les valeurs en °C et en %, il faut juste déclarer les formules de conversion pour les entrées correspondantes.

Pour cela il faut choisir le type "Personnalisé" et entrer les formules indiquées dans la copie d'écran ci-dessous.

Dès lors, il est possible de faire avec les valeurs remontées tout ce que permet une entrée analogique dans l'IPX800, notamment déclencher des actions sur franchissement de seuils mini et maxi.

C'est une autre possibilité de pilotage que celle via les sorties virtuelles.

NB : dans le programme, les remontées de température et d'humidité ont été décalée dans le temps de 30 secondes par rapport à celles de franchissement de seuils, définies via l'API "CRTL_TH", afin de ne pas poser de conflit d'accès au DHT22 qui ne tolère pas un intervalle inférieur à 2 secondes entre 2 mesures.

Le code plus en détail (pour les « experts »)

Nous allons maintenant entrer dans l’analyse plus détaillée du code source pour en faciliter la compréhension et la modification éventuelle. Cela nécessite toutefois un minimum de connaissances en programmation C++

NB : le code étant très largement commenté, on pourra assez facilement comprendre son fonctionnement via sa lecture, c’est la raison pour laquelle cette analyse ne présente que les grands principes retenus.

Mémorisation des paramètres et de l’état du pilote

Les cartes WeMos D1 mini comportent une EEPROM de 512 octets. Les paramètres du dispositif (présence ou non du capteur DHT22, nom donné au boitier, paramètres pour les remontées automatiques d'informations vers un IPX…) étant des informations changeant très peu, le choix a donc été fait de les stocker dans l’EEPROM de la carte. Les informations d'accès au WiFI (SSID, clé WPA) sont, quant à elle, stockées directement par l'ESP8266 dans sa zone mémoire dédiée à cela.

En fonctionnement « normal » (connecté à un réseau WiFi et donc en mesure de piloter un radiateur), si elle a été activée dans le code (cf. ci-dessus) une fonction permet de « Dumper » le contenu de l’EEPROM sur le port série (et donc de le faire afficher par l’application Arduino IDE) et de la remettre complètement à 0 (« Wipe ») ou à 0xFF (« Fill ») en cas de besoin (changement de version de logiciel induisant une modification de l’organisation du contenu de l’EEPROM et pouvant nécessiter plus qu’un simple « Hard Reset », réutilisation d'une carte affectée précédemment à un autre usage ou des tests).

NB : de ce que j'ai constaté, une carte neuve a son EEPROM avec tous les octets à 0xFF. Mais ce cas observé sur certaines cartes que j'ai achetées n'est peut-être pas généralisable à toutes.

Par contre, l’état du radiateur étant une information appelée à changer fréquemment, j’ai choisi de mémoriser celle-ci dans la mémoire flash de la carte (via le système de fichiers SPIFFS) dans un petit fichier d’état « status.dat ». Cela permet de moins solliciter l’EEPROM, que des écritures trop fréquentes pourraient rapidement endommager.

Paramètre « Device Config »

Le premier octet de l’EEPROM contient le « Device Config ». Sur cet octet, seul le bit de poids faible est utilisé actuellement :

  • Le premier bit indique, s’il est à 1, qu’un capteur DHT est censé être branché sur la carte.
NB : pour mémoire, la présence réelle du capteur n'est pas vérifiée par le programme

Initialisation du boitier : fonction void setup()

Cette fonction, que l’on retrouve dans tous les programmes pilotant des cartes Arduino ou des cartes à base d’ESP8266, permet l’initialisation du dispositif, avant que celui-ci ne tourne sur la boucle principale loop().

Il est impossible de sortir de la fonction setup() tant qu’une configuration WiFi valide n’a pas été transmise au boitier et vérifiée (au premier allumage ou après un « Hard Reset »).

Le comportement de la fonction setup() est donc le suivant :

  • Au démarrage du dispositif la fonction procède aux initialisations de base (configuration des ports GPIO, ouverture de l’accès à l’EEPROM et lecture du 1er octet contenant le « Device Config », initialisation du système de fichier SPIFFS, lancement du serveur Web) ;
  • Durant celles-ci, elle vérifie si le bouton « Hard Reset » est enfoncé et effectue en ce cas un « Wipe » (remise à 0 de l'EEPROM) ;
NB :
- le programme fait clignoter alternativement les LEDs bleue (Link) et rouge et attend que le bouton soit relâché pour continuer, afin d'éviter un « Hard Reset » immédiatement derrière qui n'est pas nécessairement ce qui est voulu ; le relâcher et le renfoncer immédiatement doit pouvoir permettre de faire ce « Hard Reset », sinon, il pourra être effectué plus tard, si le réseau WiFi ne peut être joint (double clignotement permanent toutes les 0,3 s) ou en mode « normal » ;
- lors d'un « Wipe », les informations de luminosité des LEDs, présence d'un capteur DHT, informations pour les remontées d'informations de température et humidité vers l'IPX sont réinitialisées. En ce cas les LEDs resteront éteintes et il sera nécessaire d'utiliser la commande de réglage de la luminosité vue précédemment pour les rallumer.
  • le programme teste ensuite si un SSID WiFi est mémorisé, indiquant qu’une configuration valide a, a priori, été entrée et testée ;
  • Si ce n’est pas le cas, il appelle la fonction « autoConnect » de la librairie « WiFiManager » pour obtenir les informations nécessaires pour rejoindre le réseau WiFi voulu (voir ci-dessus pour le déroulement de la procédure). Quand l’accès au réseau WiFi est validé, le programme sort de cette étape d'initialisation et la LED bleue clignote lentement 5 fois pour acquitter cette validation ;
  • Si une configuration d’accès correcte au réseau WiFi est enregistrée (soit après les opérations précédentes, soit après une extinction à partir d'un fonctionnement normal), la carte termine son initialisation :
    • Elle se connecte au réseau WiFi (boucle indéfiniment si celui-ci n’est pas accessible, si le SSID ou la clé WPA a changé…, un appui sur « Hard Reset » permettra d'y remédier en faisant redémarrer la carte en mode « initialisation »), la LED bleue clignotante indique la connexion en cours : 2 fois toutes les 0,3 s pendant la recherche du réseau, puis 5 fois lentement lorsque la connexion est établie  ;
    • Elle recharge tous les paramètres précédemment enregistrés : nom du boitier, mode du fil pilote, luminosité des LEDs, présence du capteur DHT, paramètres de surveillance de la température et de l’humidité et ceux de l’IPX vers lequel remonter ces infos ;
NB : ces paramètres seront ceux par défaut après une initialisation ou un « Hard Reset » : fil pilote en mode Eco, luminosité des LEDs à 10‰, pas de capteur DHT.
  • Elle sort de la fonction setup() pour passer la main à la fonction loop() qui va gérer le fonctionnement du dispositif en mode « normal ».

Le fonctionnement « normal »: fonction void loop()

Les différentes étapes de fonctionnement de la boucle principale sont :

  • la détection de l’appui sur le bouton de « Hard Reset » (qui déconnecte le boitier du réseau WiFI, efface le SSID enregistré et fait rebooter le boitier) ;
  • la détection de l’appui sur le bouton de changement d’état, ce qui a pour effet de faire passer le pilote d’un état au suivant dans l’ordre indiqué précédemment (Confort -> Eco -> Hors Gel -> Arrêt -> Confort) ;
  • diminuer la luminosité des LEDs en ne les gardant allumées que pendant un certain nombre de cycles tous les 1000 tours de boucle ;
NB : ce principe très simple a toutefois pour conséquence de conduire a quelques clignotements intempestifs quand la carte est occupée à faire autre chose que sa boucle principale (interrogation via l’IPX depuis un widget par exemple…).
  • mesurer la température et l’humidité à intervalle de temps régulier et informer l’IPX en positionnant à 0 ou à 1 la ou les sorties virtuelles déclarées, si cette fonction est activée ;
  • vérifier l’arrivée d’une nouvelle commande http et l’interpréter pour exécuter les opérations nécessaires. Pour cela, les commandes reçues sont converties en un n° si elles sont reconnues (-1 si la commande n’est pas reconnue), ce qui permet leur traitement par un « case ». Les commandes renvoient toutes vers le client (navigateur Web) une réponse sous forme JSON pour indiquer le succès ou non de l’opération, retourner les paramètres demandés…

Améliorations possibles du code

Parmi les améliorations possibles du code il y aurait notamment :

  • pouvoir attribuer une adresse IP fixe, ainsi qu’un masque de sous-réseau et éventuellement une adresse de routeur si on souhaite pouvoir accéder au boitier au travers d’une redirection de port (déjà permis via un bail statique) ;
  • pouvoir piloter les états « Confort -1° » et « Confort -2° ».

N’ayant personnellement pas l’usage de ces deux fonctions, j’ai choisi de ne pas les développer.

La fixation de l’adresse IP des boitiers est faite chez moi, comme dit précédemment, via des baux statiques au niveau du service DHCP de ma Box (une FreeBox en ce qui me concerne) qui permet d’attribuer toujours la même IP à une certaine adresse MAC. La plupart des Box, incorporent a priori ce mécanisme. Le bouton « Info » de l'interface de rattachement du boitier au réseau WiFi permet d'ailleurs de récupérer cette adresse MAC pour pouvoir faire facilement cette affectation. Fixer des adresses IP statiques directement dans les boitiers, complexifierait, à mon sens inutilement, l’administration du réseau et alourdirait beaucoup le code avec les nécessaires contrôles sur les informations IP que cela nécessiterait.

Quand aux ordres « Confort -1° » et Confort -2° », ils ne présentent, de mon point de vue, aucun intérêt pour le pilotage via un IPX. Par contre, il est possible d'en tirer parti sur des radiateurs intégrant un capteur de présence et qui vont être capables de passer d’eux-mêmes dans ces modes, en l’absence de détection durable d’une présence pour faire des économies d’énergie et malgré un ordre « Confort » sur leur fil pilote. Se référer à la documentation du radiateur pour voir si cette fonction est proposée dessus, si elle est compatible avec le pilotage par fil pilote et comment la mettre en service.

Une autre amélioration potentielle serait la détection de la présence du capteur DHT pour interdire sa mise en fonction s’il n’est pas présent (ce qui fait perdre du temps dans les réponses aux requêtes). Présentant peu d’intérêt, parce que je ne m'amuse pas à mettre et enlever le capteur DHT sur mes boitiers, je ne l’ai pas développée pour l’instant.

Enfin, le montage ayant été fait avec un capteur DHT22, il faudrait adapter le code pour pouvoir utiliser un autre type de capteur (par ex. un DHT11), voire détecter automatiquement quel capteur est branché pour le gérer correctement.


Bon montage et n’hésitez pas à me remonter vos remarques et améliorations.

Liste de « courses »

Les lignes ci-dessous regroupent les liens vers tous les fichiers utiles pour la réalisation de l'appareil :

  • Le typon en PDF
  • Le code source pour Arduino IDE (version 2.6a)