Lors de l'épisode précédent, nous avons construit un petit appareil autonome associant la carte ESP32 Pico Kit, une LED RVB et une photorésistance, pour mesurer périodiquement la luminosité ambiante et l'envoyer dans le nuage sur la plateforme AllThingsTalk. Ces valeurs sont ensuite affichées sur une page Web spécifique affectée à l’appareil (Device). L'utilisateur peut configurer la page et elle est bien entendue accessible depuis le monde entier. Vous vous rappelez sans doute que nous avons également géré les interruptions de la communication et la connexion automatique en Wi-Fi, ainsi que le rétablissement de la connexion avec le courtier AllThingsTalk MQTT.

Émission de commandes avec AllThingsTalk

La plate-forme d’accès au nuage permet également d'envoyer des commandes à l'appareil, via MQTT, à partir de sa propre page Web. Vous pouvez par exemple l'utiliser pour commander des LED, des moteurs et autres actionneurs.
Lors de l'épisode 18, nous avions créé un appareil  AllThingsMaker-Device baptisé « MyJourneyIoT_Sensor », en associant une fonction (Asset) « temperature » au capteur, puis une fonction « light ». Pour tester le processus de commande depuis le nuage, j'ai créé une fonction « lamp » pour le même appareil, mais en cliquant cette fois sur l’option « Actuator » (actionneur) et non « Sensor » (capteur). J’ai ensuite choisi le type « Number » (nombre) pour produire des valeurs numériques (voir la capture d‘écran) :


 
Trois éléments apparaissent dans la fenêtre Asset :


 
Si vous cliquez sur les trois points alignés verticalement sur la droite, l'élément de menu « Send command » vous dirige vers une fenêtre qui va vous permettre d'éditer directement le contenu utile du message MQTT et l’envoyer. Il n'est pas inutile de se rappeler que les valeurs numériques émises par les capteurs sont enregistrées au format JSON. Par exemple, cette commande fixe la valeur 15 à l’actionneur :
 
{
    "value": 15
}

Il existe aussi une autre méthode de commande, plus pratique. Dans les éléments du menu principal situé à gauche, choisissez l'option « Pinboards » (tableaux) pour configurer votre périmètre de commande personnalisé. Il suffit pour cela de créer un nouveau Pinboard, puis de sélectionner l'icône en forme de crayon, en haut, à droite, pour le modifier. Dans l’écran de conception, le bouton « New pin » vous permet de créer de nouveaux éléments de commande que vous pouvez affecter aux capteurs et aux actionneurs. La capture d'écran montre comment mon actionneur « lamp » a été configuré :


 
Dans la fenêtre suivante, j'ai indiqué que la lampe devait être commandée par un slider (curseur). Une fois terminé, le tableau ressemble à la capture d’écran illustrant le début de cet article.
 


Si vous déplacez le curseur dans une nouvelle position, une commande contenant la nouvelle valeur est émise via MQTT.

Un message MQTT en attente ?

Parvenu à ce stade, il me restait à mettre l’ESP32 en attente des messages entrants. J'ai utilisé dans un premier temps le croquis du dernier épisode comme point de départ. Vous pouvez le télécharger ici et le comparer au nouveau, téléchargeable ci-dessous.
J'ai d'abord étendu ma fonction ConnectToATT() avec les lignes de code suivantes, issues du croquis d’un épisode précédent, en le modifiant légèrement :
 
String ActuatorName = "lamp";
String ATT_ActuatorTopic = "device/" + strDeviceID + "/asset/" + ActuatorName + "/command";
       
int MQTT_Subscribe_Result = attMQTTClient.Subscribe(ATT_ActuatorTopic);   // Attempt to subscribe to topic
 
if (MQTT_Subscribe_Result == 1)   // successful
{
      BreadboardRGBLED.SwitchRGBLED(LED_GREEN);  
      NodeState = NODESTATE_OK;  
      Serial.println("MQTT subscribed.");       
}
else
{
      BreadboardRGBLED.SwitchRGBLED(LED_RED);
      BreadboardRGBLED.setRGB(255, 0, 0);          // set the default color to red for dimming
      NodeState = NODESTATE_NOMQTTSUBSCRIPTION;  
      Serial.println("MQTT not subscribed.");       
}
 
Dans cette fonction, l’ESP32 joue le rôle de client MQTT. Il ne se connecte pas seulement au courtier, mais reçoit également les messages du nuage, ce qui permet de commander la lampe. La première ligne montre comment la rubrique (Topic) doit être assemblée.

Dans la boucle principale, il est nécessaire de vérifier régulièrement si des messages ont été reçus. L’ESP32 reçoit ces messages en tant que client MQTT (ou client TCP) du courtier MQTT (ou serveur TCP) via la connexion MQTT / TCP ouverte.
Mon approche initiale n’était pas vraiment élégante. Avec les lignes de code
 
byte PayloadCountReceivedMessage = attMQTTClient.Get(attMQTTClient.PayloadBuffer);

le programme vérifie périodiquement si un message MQTT a été reçu. Si tel est le cas, la variable  PayloadCountReceivedMessage devient supérieure à zéro, et la charge utile du message est stockée dans le tableau attMQTTClient.PayloadBuffer (que gère ma bibliothèque MQTTClient). Il est très rapidement apparu évident que la fonction.Get risquait de monopoliser le processeur.  Cette fonction de la bibliothèque MQTTClient utilise la fonction .Receive de la bibliothèque TCPClient. Elle possède une temporisation d'une seconde si aucun caractère n'est détecté, ce qui peut être très utile, par exemple, si vous souhaitez vous mettre en attente d'une réponse d'un serveur Web. Dans ce cas, vous vous attendez à recevoir des caractères. Par contre, si vous souhaitez seulement vérifier que quelque chose est arrivé, vous devrez adopter une approche différente.
J'ai donc ajouté une fonction .ReceiveIfAvailable(…) à la bibliothèque TCPClient. Elle utilise la fonction  .available() de la bibliothèque Arduino ESP32 WifiClient. Celle-ci renvoie le nombre de caractères reçus en TCP / IP.  Si rien ne se passe, .ReceiveIfAvailable prend fin extrêmement rapidement. Il ne me restait plus alors qu'à modifier la bibliothèque MQTT-Lib pour que .Get accède à cette nouvelle fonction. J'ai noté que le test des échanges (ping) n'était pas très efficace, mais faute de temps, j'ai décidé de reporter l'optimisation à un épisode futur.

L’ESP32 reçoit les commandes

L’ESP32 est donc maintenant capable de recevoir les messages MQTT. Au départ, j'ai simplement utilisé l'interface série pour adresser les données entrantes à l’ESP32 en déplaçant le curseur sur le Pinboard. Les messages contiennent une chaîne de caractères comme dans l'exemple ci-dessous :
 
{"at":"2018-04-09  ……  ","value":46}

Le résultat m'a semblé très prometteur, avec des valeurs correspondant à la position du curseur situées entre les caractères « : » et « } ». Dans le fichier à télécharger ci-dessous, vous trouverez le croquis terminé avec une petite démo utilisant le curseur pour commander à distance la composante bleue de la lumière émise par la LED RVB pulsée. Le dossier téléchargé contient également les bibliothèques modifiées, qui doivent être ajoutées au dossier « libraries » de l’IDE Arduino.

J'ai constaté que je reçois presque toujours les commandes MQTT lorsque je déplace le curseur, mais sans garantir une fiabilité à 100 %. Dans une situation de contrôle critique, il serait nécessaire d'introduire une boucle de contre-réaction pour accuser réception de la valeur correcte reçue par la lampe.