J’ai entrepris un voyage pour explorer Azure IoT et transférer les milliers d’événements diffusés via mon courtier MQTT local (Mosquitto) dans Azure IoT.

Après mon dernier article sur l’utilisation du SDK Azure IoT pour Python avec Paho MQTT, je pensais que mon travail ici était terminé. Mais j’ai récemment été informé qu’il existe un support intégré pour divers appareils Arduino de Microsoft et Espressif. Comme c’est incroyable !

Avant que vous ne soyez trop excité compte tenu des exigences de ces bibliothèques, cela ne fonctionnera pas sur votre Arduino Uno, Arduino Mega 2560, etc. La prise en charge d’Azure IoT Hub est (jusqu’à présent) réservée à la nouvelle génération de cartes d’Espressif (ESP32, ESP8266) et Realtek Ameba D. Ces cartes peuvent contenir des mégaoctets, et non des kilooctets de RAM, des processeurs multicœurs et sont capables de charger dans une pile TCP / IP, MQTT et ainsi de suite.

S’il y a un thème dans ma maison, il est fiable et il est donc temps de ranger mon Raspberry Pi monté en rack et de prendre un microcontrôleur. Un Raspberry Pi, aussi étonnant soit-il, est un SBC (Single Board Computer) qui a besoin d’être mis à jour, arrosé et alimenté. Il utilise un système de fichiers, un sous-système de mémoire flash. Comment cela s’appuie-t-il sur la fiabilité, et avez-vous déjà eu un système de fichiers corrompu sur un microcontrôleur ?

Comme tout bon architecte sensé, je vous encourage à arrêter, à ranger votre Raspberry Pi et à adopter une autre approche : un microcontrôleur.

Aujourd’hui, j’utilise environ 30 sorties sur un Arduino Mega 2560 avec un blindage Ethernet et PoE utilisant le MQTT (Pub/Sub Client Library), mais il est temps de moderniser, et compte tenu de mon amour des appareils ESP avec Tasmota, j’ai décidé d’acheter un ESP32 pour cette tâche même. Dans cet article, je vais illustrer comment créer un pont entre Mosquitto MQTT et Azure IoT Hub à l’aide de cet appareil ESP32.

J’ai expliqué dans un article précédent pourquoi j’emprunte cette voie de publication de la télémétrie pour Azure IoT Hub, ainsi que les différentes façons dont j’ai illustré comment atteindre cet objectif. De la connexion directe à Azure IoT Hub (via des jetons MQTT et SAS) à Azure IoT Edge exécuté localement avec MQTT et enfin les SDK. J’ai pu atteindre mes objectifs avec plus ou moins de succès, mais j’ai quelques inquiétudes concernant les approches que j’ai essayées jusqu’à présent.

  • La connexion directe à Azure IoT Hub introduit une latence dans le cloud.
  • Approbation, des tokens SAS aux certificats X509 : ce n’est pas anonyme et certains de mes petits appareils (Tasmota) n’augurent rien de bon.
  • Structure du sujet : elle est définie (devices/{DeviceID}/messsages/events/) et non de forme libre. Cela signifie une reconfiguration, ce qui n’est pas difficile, mais beaucoup de frictions.
  • Fiabilité : Jusqu’à présent, toutes les solutions reposaient sur un système d’exploitation nécessitant des correctifs, des mises à jour et même une petite charge administrative.

Mes objectifs pour construire une solution

  1. Aucune reconfiguration de mes appareils MQTT (Home Assistant, PLC, Arduino Mega 2560, ~ 75 appareils Tasmota).
  2. Utiliser mon courtier MQTT existant (Mosquitto) pour Azure IoT.
  3. Exécuter sur microcontrôleur car je veux être fiable.

Des objectifs assez élevés, vous pouvez même dire que je suis paresseux, mais la réalité est que je veux une faible friction pour tirer une intelligence opérationnelle des milliers d’événements chaque jour (lisez ci-dessous, c’est plus de 10 000 par jour !)

Ce que nous allons construire

Pour surmonter les limitations décrites ci-dessus, nous allons utiliser un microcontrôleur ESP32 avec du code C++ avec une bibliothèque. Juste au cas où vous ne seriez pas familier, laissez-moi vous présenter ESP32.

ESP32

Où est-ce que je commence? Qu’est-ce qui n’est pas de l’amour dans ce SOC ? ESP32 est un microcontrôleur moderne et puissant compatible Arduino qui pilote de nombreux appareils de mon contrôleur d’irrigation (Opensprinkler) au robot d’apprentissage de mes enfants (MBot), ils utilisent soit un ESP32, soit un dérivé plus ancien, tel qu’un ESP8266. Aujourd’hui, je l’utilise comme pont logiciel, mais il existe une multitude d’E / S et de support pour PWM, I2c et plus, ce qui en fait un outil polyvalent et polyvalent.

L’ESP32 est une série de systèmes peu coûteux et à faible consommation d’énergie sur des microcontrôleurs à puce avec Wi-Fi intégré et Bluetooth bimode. La série ESP32 utilise soit un microprocesseur Tensilica Xtensa LX6 dans les variantes double cœur et monocœur, le microprocesseur double cœur Xtensa LX7 ou un microprocesseur RISC-V monocœur et comprend des connecteurs d’antenne intégrés, un balun RF, un amplificateur de puissance. , amplificateur récepteur à faible bruit, amplificateur de fichier et modules de gestion de l’alimentation. ESP32 est créé et développé par Espressif Systems, une société chinoise basée à Shanghai, et est fabriqué par TSMC à l’aide de son procédé 40 nm. Il succède au microcontrôleur ESP8266.

ESP32 – Wikipédia

Construisons.

Présentation des codes

Regardez les étapes ci-dessous pendant que je taquine cette solution ou mon référentiel GitHub pour l’esquisse complète d’Arduino. Pour vous donner une meilleure compréhension de la façon dont cela fonctionne, je vais le décomposer en étapes logiques ci-dessous nécessaires pour recevoir des messages de Mosquitto via MQTT en utilisant.

« PubSubClient », puis republiez-les dans Azure IoT Hub à l’aide de « Esp32MQTTClient ».

Étape 1 – Arduino IDE – Ajouter ESP32 au gestionnaire de carte

Arduino IDE n’est pas familier avec ESP32, donc la toute première étape que nous devons prendre est d’exploiter les capacités du gestionnaire de carte d’Arduino IDE pour fournir un support pour ESP32. Dans l’IDE Arduino, ouvrez « Préférences » et entrez l’une des URL suivantes

Ouvrez ‘Board Manager’ dans le menu ‘Outils’> ‘Tableau blanc’. Rechercher une installation ‘ESP32’. Sélectionnez votre carte ESP32 spécifique dans le menu après l’installation.

Redémarrez l’IDE Arduino.

Étape 2 – Nous avons besoin d’une bibliothèque – PubSubClient

Bien que nous ayons maintenant un support pour ESP32, nous devons ajouter une bibliothèque qui nous permet de nous abonner et de recevoir des messages MQTT de notre courtier Mosquitto. Pour cela, nous avons besoin d’une bibliothèque MQTT. Il y en a beaucoup, mais j’ai déjà utilisé ‘PubSubClient’ sur d’autres projets sans aucun problème. Pour installer, ‘Outils’> ‘Gérer les bibliothèques’> ‘PubSubClient’

Étape 3 – Créer du code (bibliothèques et variables)

Après avoir validé que votre carte fonctionne (je vous suggérerais de télécharger un croquis Blink), nous pouvons commencer à coder. Cet exemple est basé sur ‘Examples> ESP32 Azure IoT Arduino> Simple MQTT’ ;

Nous devons inclure certaines bibliothèques que nous voulons utiliser Wi-Fi (pour la connectivité), PubSubClient (pour Mosquitto MQTT) et ESP32MQTTClient (pour Azure IoT Hub).

#include <WiFi.h>
#include <PubSubClient.h>
#include "Esp32MQTTClient.h"
 
const char* ssid = "Wifi SSID";
const char* password =  "Wifi Password
const char* mqttServer = "IP Address of MQTT Server";
const int mqttPort = 1883;
String MQTTTopic;
String MQTTPayload;

Pour Azure IoT Hub, vous devez définir votre chaîne de connexion. Cet article ne concerne pas la création d’un hub IoT ou la création d’un appareil et suppose que vous en avez déjà créé un. Voir Utilisation du portail Azure pour créer un hub IoT | Microsoft Docs pour plus d’informations sur la configuration d’un Azure IoT Hub, l’ajout d’un appareil et l’obtention d’une chaîne de connexion d’appareil.

//Azure IOT Hub Setup
static const char* connectionString = "*******************=";
static bool hasIoTHub = false;

Étape 4 – Créez du code (fonctionnalité de configuration : connexion au Wi-Fi, Azure et Mosquitto MQTT)

Notre fonctionnalité de « configuration » se connectera à notre réseau local via Wi-Fi, puis se connectera à Azure, où la fonctionnalité « MQTTConnect » se connecte non seulement à notre courtier MQTT local, mais définit également les éléments MQTT auxquels s’abonner. Vous pouvez vous abonner à plusieurs sujets MQTT en ayant plusieurs lignes d’abonnement. Vous pouvez également utiliser des filtres génériques MQTT pour faire correspondre les événements avec moins d’abonnements.

Plus (+) : il s’agit d’un caractère générique à un niveau qui correspond à n’importe quel nom pour un niveau de sujet spécifique. Nous pouvons utiliser ce caractère générique au lieu de spécifier un nom pour n’importe quel niveau de sujet dans le filtre de sujet.

Dièse (#) : il s’agit d’un caractère générique à plusieurs niveaux que nous ne pouvons utiliser qu’à la fin du filtre de sujet comme dernier niveau et correspond à tout sujet dont le premier niveau est le même que les niveaux de sujet indiqués sur le côté gauche du # symbole.

Comprendre les jokers | MQTT Essentials – Un protocole IoT léger (packtpub.com)

Le moniteur série est pratique pour résoudre les problèmes de Wi-Fi ou de connexion à Azure IoT Hub.

client.on_message = on_message  

void setup() {
  //Set baud rate
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("ESP32 : Connecting to WiFi...");
  }
  Serial.println("ESP32 : WiFi connected");
  Serial.println("ESP32 : IP address: ");
  Serial.println(WiFi.localIP());
  //Set MQTT details
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
 
  //Connect to Azure IOT
  if (!Esp32MQTTClient_Init((const uint8_t*)connectionString))
  {
    hasIoTHub = false;
    Serial.println("Azure IoT Hub : Initializing IoT hub failed.");
    return;
  }
  hasIoTHub = true;
 
}
    
void MQTTConnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("MQTT : Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP32Client")) {
      Serial.println("MQTT : Connected");
      // Once connected, publish an announcement...
      client.publish("stat/ESP32/IP_Address","Your IP Address");
      //Subscribe to topics, one topic per line.
      client.subscribe("stat/+/POWER");      
    } else {
      Serial.print("MQTT : Failed to connect to MQTT , rc=");
      Serial.print(client.state());
      Serial.println("MQTT : Trying again to connect to MQTT in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Étape 4 – Créez du code (rappel MQTT et publication sur Azure)

Après les fonctions de configuration, nous devons maintenant créer une fonction qui écoute les messages MQTT entrants qui correspondent à notre abonnement (rappel), extraire l’élément et la charge utile avant de masser ces données et de les envoyer à Azure via une autre fonction (AzureIoTHub).

void callback(char* topic, byte* payload, unsigned int length) {

  MQTTTopic = String(topic);
  MQTTPayload = ""; 
  for (int i = 0; i < length; i++) {
    // Serial.print((char)payload[i]); - Use for debugging
    MQTTPayload = String(MQTTPayload + (char)payload[i]);
  }    
}


void AzureIoTHub() {
  if (hasIoTHub)
      {
        String tempString;
        tempString = "{" + MQTTTopic + ":" + MQTTPayload + "}";
        if (Esp32MQTTClient_SendEvent(tempString.c_str()))
        {
          Serial.println("Azure IoT Hub : Sending data to Azure IoT Hub succeed");
        }
        else
        {
          Serial.println("Azure IoT Hub : Failure...");
        }
      MQTTPayload = "";
      MQTTTopic = "";

   }
}

Étape 5 – Créer du code (notre boucle principale)

La boucle principale utilise toutes ces fonctionnalités, et sa logique peut être résumée en quelques points. Connectez-vous à MQTT si vous n’êtes pas connecté

Si un élément/message MQTT a été décodé via notre « fonctionnalité de rappel », envoyez-le à Azure IoT Hub et reconnectez-vous s’il n’y a pas de connexion.

void loop() {
   //Connect to MQTT and reconnect if connection drops
   if (!client.connected()) {
     MQTTConnect();
   }
   //Respond to messages received
   if (MQTTTopic != "") { 
      Serial.println("MQTT : Topic is [" + MQTTTopic +"]");
      Serial.println("MQTT : Payload is [" + MQTTPayload + "]");
      AzureIoTHub(); 
  }
  client.loop();
}

Rassemble le tout

Voici une copie complète de ce qui précède plus un peu plus. Vous pouvez couper et coller ce qui suit ou cloner mon référentiel GitHub.

#include <WiFi.h>
#include <PubSubClient.h>
#include "Esp32MQTTClient.h"
 
const char* ssid = "****";
const char* password =  "****";
const char* mqttServer = "****";
const int mqttPort = 1883;
String MQTTTopic;
String MQTTPayload;

//Azure IOT Hub Setup
static const char* connectionString = "****";
static bool hasIoTHub = false;
 
WiFiClient espClient;
PubSubClient client(espClient);
 
void callback(char* topic, byte* payload, unsigned int length) {

  MQTTTopic = String(topic);
  MQTTPayload = ""; 
  for (int i = 0; i < length; i++) {
    // Serial.print((char)payload[i]); - Use for debugging
    MQTTPayload = String(MQTTPayload + (char)payload[i]);
  }    
}



void MQTTConnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("MQTT : Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP32Client")) {
      Serial.println("MQTT : Connected");
      // Once connected, publish an announcement...
      client.publish("stat/ESP32/IP_Address","Your IP Address");
      //Subscribe to topics, one topic per line.
      client.subscribe("stat/+/POWER");      
    } else {
      Serial.print("MQTT : Failed to connect to MQTT , rc=");
      Serial.print(client.state());
      Serial.println("MQTT : Trying again to connect to MQTT in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  //Set baud rate
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("ESP32 : Connecting to WiFi...");
  }
  Serial.println("ESP32 : WiFi connected");
  Serial.println("ESP32 : IP address: ");
  Serial.println(WiFi.localIP());
  //Set MQTT details
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
 
  //Connect to Azure IOT
  if (!Esp32MQTTClient_Init((const uint8_t*)connectionString))
  {
    hasIoTHub = false;
    Serial.println("Azure IoT Hub : Initializing IoT hub failed.");
    return;
  }
  hasIoTHub = true;
 
}

void loop() {
   //Connect to MQTT and reconnect if connection drops
   if (!client.connected()) {
     MQTTConnect();
   }
   //Respond to messages received
   if (MQTTTopic != "") { 
      Serial.println("MQTT : Topic is [" + MQTTTopic +"]");
      Serial.println("MQTT : Payload is [" + MQTTPayload + "]");
      AzureIoTHub(); 
  }
  client.loop();
}

void AzureIoTHub() {
  if (hasIoTHub)
      {
        String tempString;
        tempString = "{" + MQTTTopic + ":" + MQTTPayload + "}";
        if (Esp32MQTTClient_SendEvent(tempString.c_str()))
        {
          Serial.println("Azure IoT Hub : Sending data to Azure IoT Hub succeed");
        }
        else
        {
          Serial.println("Azure IoT Hub : Failure...");
        }
      MQTTPayload = "";
      MQTTTopic = "";

   }
}

Pour voir cela en action

Passons à une vidéo pour voir que cela fonctionne de bout en bout, pour valider que les messages circulent dans Azure IoT Hub, je peux utiliser Azure CLI (AZ-CLI) pour surveiller la sortie couplée au moniteur série Arduino.

az iot hub monitor-events --output table --device-id devicename --hub-name hubname --output json

Pour les besoins de cette démo, j’ai laissé une poignée de messages au niveau QoS 2 et mis LWT (Last Will and Testament) au sable.

Après 24 heures de conduite, nous pouvons voir que j’ai publié 10,52 K de messages dans Azure IoT Hub et qu’il y a certains flux et reflux qui se produisent dans ma maison.

Période de 24 heures avec des messages circulant dans Azure IoT Hub

Conclusion

Il existe de nombreuses façons de décortiquer cette morue. Mes exigences étaient de publier des messages dans Azure et nous avons pu y parvenir de différentes manières (je suis sûr qu’il y en a d’autres). L’automatisation est un voyage, quel chemin souhaitez-vous emprunter ?

Nous avons illustré une approche side-car transparente qui écoute un courtier existant sur les sujets que vous souhaitez et les pousse dans Azure IoT, le tout sans apporter de modifications de configuration (la chose la plus importante pour ma mise en œuvre). Cette méthode fonctionne sur un microcontrôleur, utilise moins de 5 W de puissance et fonctionne tout simplement.

Y a-t-il des inconvénients ? Bien sûr qu’il y en a. À l’heure actuelle, il s’agit d’un chemin dans la direction (simplex) et me permet d’envoyer des messages dans Azure IoT mais de ne pas recevoir de messages en retour.

Personnellement, j’aime bien cette approche, elle combine l’élégance d’un SDK comme c’est mon code et déconnecte la fiabilité d’un microcontrôleur. C’est mon code, mes choix sur ce que je fais, mais je comprends que ce n’est pas pour tout le monde. Nous avons maintenant mes messages, mes événements dans Azure, et il est temps de se faire des amis et d’apprendre à dériver l’intelligence opérationnelle des visualisations à l’apprentissage automatique et au-delà.

Penser grand et construire heureux

Shane

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *