Définitions relatives au NodeState.
Dans le dernier épisode, nous avons réalisé un petit projet comportant un actionneur, pour piloter à distance une LED par MQTT. Pour mémoire : notre carte Pretzel est équipée d'une puce Wi-Fi ESP8266, pilotée par un ATmega328 qui lui envoie des instructions AT. Ce µC exécute le croquis Arduino que nous avons développé pas à pas lors du dernier épisode ; il y a aussi une bibliothèque TCP/IP élémentaire et une bibliothèque MQTT rudimentaire qui permettent de constituer la suite d'octets à envoyer au courtier (serveur) MQTT (cf. les spécifications MQTT).
La communication commence avec une requête CONNECT ; nous vérifions ensuite que le courtier accuse réception en retournant une séquence d'octets fixes CONNACK. Ensuite, nous envoyons toutes les 15 s les octets d'une requête PINGREQ. Le serveur du courtier répond aussi avec une séquence d'octets fixes (PINGRESP) et conclut alors que le client maintient la communication ouverte. Par ailleurs, à l'aide de SUBSCRIBE, nous nous sommes abonnés au topic « /ElektorMyJourneyIoT/TestTopic/test » pour recevoir les messages du client de commande (dans notre cas réalisé par un logiciel PC) et commuter la LED. Une fois l'action demandée exécutée, nous envoyons ensuite sous le topic « …/TestTopicBack/… » des messages PUBLISH en retour.

Malgré tout, de temps en temps, la communication entre la carte de l'actionneur et le serveur MQTT s'interrompt quelque part sur l'Internet. Si la requête PINGREQ que nous envoyons reste sans réponse, nous savons que c'est le cas. Dans le dernier épisode nous nous sommes alors contentés d'allumer la LED rouge. En appuyant sur le poussoir, l'utilisateur pouvait ensuite reconnecter le client actionneur au courtier pour se réabonner au topic cité plus haut.

Ce schéma n'est pas acceptable pour un usage quotidien dès lors que l'actionneur se trouve loin dans la nature. Si on s'aperçoit sur la page du client MQTT de commande qu'il n'y a plus de message de confirmation, il faut se rendre sur place pour reconnecter « manu militari » la carte de l'actionneur. Ça risque de vous lasser rapidement.

Il est cependant aisé d'automatiser cette reconnexion. Toutes les fonctions nécessaires sont déjà présentes dans le croquis Arduino du dernier épisode. À présent, l'amélioration saute aux yeux en comparant le nouveau croquis (téléchargement ci-dessous) à celui de l'épisode précédent.

Automate fini MQTT

J'ai ajouté quelques définitions pour le « NodeState » (état du nœud, voir la copie d'écran). Des valeurs positives indiquent un fonctionnement normal tandis que zéro et les valeurs négatives indiquent un défaut. En cas de défaillance, les fonctions de communication, d'abonnement au topic (ConnectAndSubscribeToTopic()) et d'envoi du ping (SendPingRequestToBroker()) ne commutent pas seulement la LED rouge, elles retournent également une valeur (négative) à la boucle principale. La boucle principale réalise un automate fini (State Machine) élémentaire : grâce à la valeur numérique retournée, une variable booléenne MQTTClient_Connected prend sa valeur logique, à savoir true (vrai), si la tentative de communication puis la commande ping ont abouti et que la communication n'est pas interrompue, et false (faux), si un défaut est apparu. Dans le premier cas, la carte se comporte comme dans l'épisode précédent : elle envoie régulièrement un PING et écoute sagement les messages de requête de commutation qui arrivent via MQTT. Si un ordre tombe, elle l'exécute via l'actionneur et publie un message de confirmation via MQTT.
Si MQTTClient_Connected == false, c'est que la communication est coupée et la fonction ConnectAndSubscribeToTopic() entreprend de la rétablir. MQTTClient_Connected a d'ailleurs la valeur faux au démarrage du programme de sorte que la première tentative de communication est effectuée dès la connexion au réseau Wi-Fi, sans attendre que l'utilisateur actionne le bouton. En l'actionnant, l'utilisateur force toujours la carte à établir une nouvelle communication.

Messages d'état via MQTT

Maintenant que beaucoup de tâches sont automatisées, la carte délivre des messages d'état tant sur l'interface série locale (ça aide pour la mise au point sur place) que via MQTT (même topic que les messages de confirmation de l'actionneur). Comme, en cas de défaillance, il n'est pas possible d'envoyer des messages d'état via MQTT, le défaut est mémorisé par la variable NodeStateLog et le message correspondant est envoyé dès que la communication est rétablie. Dans les messages d'état, « S1» à « S3 » indiquent une fonctionnement correct et « E0 » à « E4 » un défaut.

Essayez, la configuration est la même que lors du dernier épisode. Le téléchargement renferme le code Arduino (dans lequel vous devez, comme toujours, ajouter les données de connexion Wi-Fi – SSID et mot de passe) ainsi que le client MQTT pour PC. La carte actionneur travaille déjà depuis déjà longtemps en toute autonomie ; la sortie série permet de savoir si la connexion a dû être rétablie automatiquement (le client PC peut parfois avoir besoin d'être redémarré). Le manque global de fiabilité de la connexion est lié au fait que nous travaillons (encore) avec un courtier dont l'accessibilité n'est pas toujours garantie.

Il nous reste encore beaucoup à faire et nous y reviendrons dans les prochains épisodes !