Différences
Ci-dessous, les différences entre deux révisions de la page.
arduino:clientmqttesp8266 [2022/08/03 17:49] – [1. Sauvegarde des paramètres de connexion au réseau Wifi] phil | arduino:clientmqttesp8266 [Date inconnue] (Version actuelle) – supprimée - modification externe (Date inconnue) 127.0.0.1 | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | [[arduino: | ||
- | ====== Mettre en oeuvre un client MQTT sur un EP8266 (ESP32) Feather Huzzah ou MKR1010 ====== | ||
- | [Mise à jour le 3/11/2021] | ||
- | {{ : | ||
- | |||
- | === Prérequis === | ||
- | Lire les généralités sur le protocole MQTT et installer un **broker Mosquitto sur un Raspberry Pi**. \\ Pour cela, on pourra consulter la page [[raspberrypi: | ||
- | |||
- | === Ressources === | ||
- | * Article //" | ||
- | * Tutoriel < | ||
- | * Exemples de code pour un ESP8266 sur < | ||
- | * Bibliothèque pubsubclient pour implémenter un client MQTT sur Arduino disponible sur < | ||
- | * Documentation des bibliothèques Arduino pour l' | ||
- | * Bibliothèque pour la résolution de nom : < | ||
- | |||
- | |||
- | === Lectures connexes === | ||
- | * [[raspberrypi: | ||
- | * [[raspberrypi: | ||
- | * [[reseaux: | ||
- | * [[web: | ||
- | * [[raspberrypi: | ||
- | |||
- | === Mots-clés === | ||
- | **client**((Dans un réseau informatique, | ||
- | |||
- | ---- | ||
- | |||
- | ===== A. Découverte ===== | ||
- | ==== Objectif ==== | ||
- | Se familiariser avec le protocole MQTT (Message Queuing Telemetry Transport), standard de l’IoT (Internet Of Things), en créant une communication entre deux clients MQTT, un ESP8266 et un outil de simulation via un broker Mosquitto installé sur un Raspberry Pi. \\ La préparation du Raspberry Pi est décrite sur la page [[raspberrypi: | ||
- | |||
- | {{ : | ||
- | ---- | ||
- | |||
- | ==== Cahier des charges ==== | ||
- | |||
- | * **Schéma** | ||
- | Le schéma ci-dessous illustre le fonctionnement attendu : \\ | ||
- | - La LED embarquée de l' | ||
- | - L' | ||
- | |||
- | {{ : | ||
- | |||
- | * **Topics** | ||
- | * abonnement à " | ||
- | * publication de " | ||
- | |||
- | * **Algorithme du programme ARD_ESP8266_MQTT.ino** | ||
- | |||
- | < | ||
- | // Initialisations | ||
- | Connexion au point d' | ||
- | Configuration du broker | ||
- | Activation de la fonction de rappel chargée de traiter les messages reçus | ||
- | |||
- | < | ||
- | < | ||
- | // Maintenir la connexion et s' | ||
- | < | ||
- | se connecter puis s' | ||
- | < | ||
- | // Traiter les messages reçus | ||
- | < | ||
- | la fonction de rappel traite le message | ||
- | < | ||
- | // Publier | ||
- | < | ||
- | | ||
- | < | ||
- | < | ||
- | </ | ||
- | |||
- | ---- | ||
- | ==== 1. Sauvegarde des paramètres de connexion au réseau Wifi ==== | ||
- | <callout type=" | ||
- | |||
- | * **Espressif** | ||
- | En sauvegardant ces paramètres de connexion dans la mémoire **EEPROM émulée** de chaque ESP8266 (ESP32), on se libère de cette tâche et on fait en sorte qu'ils ne soient pas affectés par la suite lors de la mise à jour du croquis. | ||
- | |||
- | Le croquis ci-dessous stocke les paramètres de connexion dans une structure, les enregistre dans l' | ||
- | |||
- | <note warning> | ||
- | |||
- | <file cpp ARD_ESP_infosClientMQTT.cpp> | ||
- | #include < | ||
- | |||
- | // Structure | ||
- | struct EEconf | ||
- | { | ||
- | char ssid[32]; | ||
- | char password[64]; | ||
- | char myhostname[32]; | ||
- | }; | ||
- | |||
- | void setup() | ||
- | { | ||
- | // Initialisation des paramètres de connexion | ||
- | EEconf myconf = { // A remplacer par : | ||
- | " | ||
- | " | ||
- | " | ||
- | |||
- | // Variable pour la relecture | ||
- | EEconf readconf; | ||
- | |||
- | Serial.begin(115200); | ||
- | |||
- | // Initialisation EEPROM | ||
- | EEPROM.begin(sizeof(myconf)); | ||
- | // Enregistrement | ||
- | EEPROM.put(0, | ||
- | EEPROM.commit(); | ||
- | |||
- | // Relecture et affichage | ||
- | EEPROM.get(0, | ||
- | Serial.println(" | ||
- | Serial.println(readconf.ssid); | ||
- | Serial.println(readconf.password); | ||
- | Serial.println(readconf.myhostname); | ||
- | } | ||
- | |||
- | void loop() | ||
- | { | ||
- | } | ||
- | </ | ||
- | |||
- | {{ : | ||
- | |||
- | <callout type=" | ||
- | |||
- | * **MKR1010** : le SSID, le mdp du réseau et le nom de la carte sont placé dans un fichier de configuration. | ||
- | ==== 2. Conception du client MQTT (template) === | ||
- | * **Source** : bibliothèque < | ||
- | |||
- | Le client MQTT décrit dans ce paragraphe repose sur la bibliothèque **PubSubClient**. Celle-ci fournit un client pour faire des messages de publication / abonnement simples avec un serveur prenant en charge MQTT. | ||
- | * Le client utilise **MQTT 3.1.1** par défaut. Il peut être modifié pour utiliser MQTT 3.1. | ||
- | * Il ne peut **publier** que des messages **QoS 0**. Il peut s' | ||
- | * La taille maximale du message (configurable), | ||
- | * L' | ||
- | |||
- | Ce client cible un **ESP8266**. Moyennant quelques modifications, | ||
- | |||
- | === a. Préparer l'IDE === | ||
- | Télécharger et installer | ||
- | |||
- | === b. Inclure les bibliothèques === | ||
- | Le croquis débute par l' | ||
- | * < | ||
- | * < | ||
- | * < | ||
- | * < | ||
- | <code cpp biblio.cpp> | ||
- | // MQTT : implémentation d'un client MQTT | ||
- | #include < | ||
- | // Connexion au wifi | ||
- | #include < | ||
- | // mDNS pour la résolution des noms des hôtes | ||
- | #include < | ||
- | // EEPROM : émule une EEPROM dans l' | ||
- | #include < | ||
- | // Paramètres de connexion au broker | ||
- | #include " | ||
- | </ | ||
- | |||
- | === c. Déclarer les constantes et les variables globales === | ||
- | <code cpp init.cpp> | ||
- | // --------------------------------------------------------------------------------- | ||
- | // Broker | ||
- | // --------------------------------------------------------------------------------- | ||
- | // Nom (mDNS) de la machine sur laquelle est installé le broker et port | ||
- | // Ne pas modifier, RENSEIGNER les paramètres situés dans parametres.h | ||
- | const char *mqtt_server = BROKER; | ||
- | uint16_t mqtt_PORT = MQTTPORT; // Port TCP sur lequel le broker écoute | ||
- | // (par défaut pour brokers MQTT) | ||
- | // --------------------------------------------------------------------------------- | ||
- | // Topics | ||
- | // --------------------------------------------------------------------------------- | ||
- | const char inTopicLed[] = " | ||
- | const char outTopicVal[] = " | ||
- | // --------------------------------------------------------------------------------- | ||
- | // Structure pour la configuration de la connexion au réseau wifi | ||
- | struct EEconf | ||
- | { // Les champs sont remplis avec les données stockées dans l' | ||
- | // par le croquis infoClientMQTT_ESP8266.ino | ||
- | char ssid[32]; | ||
- | char password[64]; | ||
- | char myhostname[32]; | ||
- | } readconf; | ||
- | // Objet pour la connexion au réseau wifi | ||
- | WiFiClient espClient; | ||
- | // Objet pour la connexion au broker MQTT (Publisher/ | ||
- | PubSubClient mqttClient(espClient); | ||
- | // Intervalle de temps séparant la publication des topics | ||
- | const long interval = 6000; // #### A adapter #### | ||
- | // Permet de calculer l' | ||
- | // publication des topics | ||
- | unsigned long previousMillis = 0; | ||
- | // Valeur à publier | ||
- | byte val = 0; | ||
- | </ | ||
- | |||
- | === d. Se connecter au point d' | ||
- | **Ressource** : < | ||
- | |||
- | Pour simplifier l' | ||
- | |||
- | <code cpp connect.cpp> | ||
- | void setup_wifi() | ||
- | { | ||
- | // mode station | ||
- | WiFi.mode(WIFI_STA); | ||
- | Serial.println(); | ||
- | Serial.print(" | ||
- | Serial.println(readconf.ssid); | ||
- | // Connexion Wifi | ||
- | WiFi.begin(readconf.ssid, | ||
- | while (WiFi.status() != WL_CONNECTED) | ||
- | { | ||
- | delay(5000); | ||
- | Serial.print(" | ||
- | } | ||
- | // Affichage | ||
- | Serial.println("" | ||
- | Serial.println(" | ||
- | Serial.println(" | ||
- | Serial.println(WiFi.localIP()); | ||
- | // Configuration mDNS | ||
- | WiFi.hostname(readconf.myhostname); | ||
- | if (!MDNS.begin(readconf.myhostname)) | ||
- | { | ||
- | Serial.println(" | ||
- | } | ||
- | else | ||
- | { | ||
- | Serial.println(" | ||
- | Serial.println(readconf.myhostname); | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | === e. Traiter les messages reçus (fonction) === | ||
- | Le principe de fonctionnement de la bibliothèque **PubSubClient** repose sur un mécanisme de **callback** (fonction de rappel((Une fonction de rappel est passée en paramètre d'une autre fonction et est appelée automatiquement dans certaines situations.))). | ||
- | |||
- | Dans le cas présent, la bibliothèque demande que l'on implémente cette fonction de rappel. Elle sera appelée en cas de réception d'un message sur n' | ||
- | |||
- | <code cpp recept.cpp> | ||
- | void callback(char *topic, byte *payload, unsigned int length) // topic : chaîne de caractères décrivant le topic | ||
- | { // payload : message associé au topic | ||
- | // length : taille des données du message | ||
- | // Afffichage dans la console pour debug | ||
- | Serial.print(" | ||
- | Serial.print(topic); | ||
- | Serial.print(" | ||
- | // Affichage du message | ||
- | for (int i = 0; i < length; i++) | ||
- | { | ||
- | Serial.print((char)payload[i]); | ||
- | } | ||
- | Serial.println("" | ||
- | // ' | ||
- | // Traitement | ||
- | if ((char)payload[0] == ' | ||
- | { | ||
- | // Oui led=on | ||
- | digitalWrite(BUILTIN_LED, | ||
- | } | ||
- | else | ||
- | { | ||
- | // Non led=off | ||
- | digitalWrite(BUILTIN_LED, | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | === f. Maintenir la connexion au broker MQTT et s' | ||
- | Pour simplifier l' | ||
- | |||
- | <code cpp connect.cpp> | ||
- | void reconnect() | ||
- | { | ||
- | // Non, on se connecte | ||
- | if (!mqttClient.connect(readconf.myhostname)) | ||
- | { | ||
- | Serial.print(" | ||
- | Serial.println(mqttClient.state()); | ||
- | delay(5000); | ||
- | continue; | ||
- | } | ||
- | Serial.println(" | ||
- | // Connecté ! On s' | ||
- | mqttClient.subscribe(inTopicLed); | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | === g. Programme principal === | ||
- | <code cpp setup.cpp> | ||
- | // Initialisation | ||
- | void setup() | ||
- | { | ||
- | // Configuration de la broche connectée à la LED de la carte | ||
- | pinMode(BUILTIN_LED, | ||
- | // Configuration du moniteur série | ||
- | Serial.begin(115200); | ||
- | // Lecture des paramètres sauvegardés par ARD_ESP_SauveInfosClientMqtt.ino | ||
- | EEPROM.begin(sizeof(readconf)); | ||
- | EEPROM.get(0, | ||
- | // Connexion au Wifi | ||
- | setup_wifi(); | ||
- | // Configuration du broker | ||
- | // MQTT_PORT = 1883 (port TCP par défaut des brokers MQTT) | ||
- | mqttClient.setServer(mqtt_server, | ||
- | // Activation de la fonction callback | ||
- | mqttClient.setCallback(callback); | ||
- | } | ||
- | </ | ||
- | |||
- | Les messages envoyés par le protocole MQTT sont des chaînes de caractères, | ||
- | |||
- | <note warning> | ||
- | |||
- | <code cpp loop.cpp> | ||
- | void loop() | ||
- | { | ||
- | // Tableau pour la conversion de la valeur " | ||
- | char msg[16]; | ||
- | // Tableau pour le topic | ||
- | char topic[64]; | ||
- | |||
- | // Sommes-nous connectés au broker MQTT ? | ||
- | if (!mqttClient.connected()) | ||
- | { | ||
- | // Non alors | ||
- | reconnect(); | ||
- | } | ||
- | // Oui, maintien de la connexion avec le broker | ||
- | // Interrogation du broker : ne doit pas être bloquée !!! pour traiter les messages reçus | ||
- | mqttClient.loop(); | ||
- | |||
- | // Temporisation "non blocante" | ||
- | long currentMillis = millis(); | ||
- | if (currentMillis - previousMillis > interval) // si temporisation > interval en ms | ||
- | { // alors on publie | ||
- | // On mémorise la " | ||
- | previousMillis = currentMillis; | ||
- | val++; // incrémentation de la valeur à transmettre | ||
- | // Construction du message | ||
- | sprintf(msg, | ||
- | // Construction du topic avec le nom d' | ||
- | // Exemple "< | ||
- | sprintf(topic, | ||
- | // Publication du message sur le topic | ||
- | mqttClient.publish(topic, | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | === h. Téléchargement des templates === | ||
- | {{ : | ||
- | Le code complet (MàJ le 26/ | ||
- | |||
- | <note tip> | ||
- | - pour un ESP8266 : [[https:// | ||
- | - pour un ESP32 : [[https:// | ||
- | - pour un MKR1010 : [[https:// | ||
- | </ | ||
- | |||
- | ==== 3. Essais et validation du croquis ==== | ||
- | {{ : | ||
- | La vérification du fonctionnement des croquis peut se faire dans une console, sur un **Raspberry Pi**, à l'aide des outils logiciels **mosquitto_pub** et **mosquitto_sub**. Au préalable, il est nécessaire d' | ||
- | Cette vérification peut également se faire après avoir installé l' | ||
- | |||
- | === 3.1 Publication d'un message sur un topic === | ||
- | La commande de la LED de la carte ESP866 peut se faire comme ci-dessous : | ||
- | |||
- | * **Sans sécurité** | ||
- | |||
- | <code bash cmd1a.bash> | ||
- | mosquitto_pub -h localhost -t ctrlled -m 0 | ||
- | mosquitto_pub -h localhost -t ctrlled -m 1 | ||
- | </ | ||
- | |||
- | * **Avec sécurité** | ||
- | <code bash cmd1b.bash> | ||
- | mosquitto_pub -h localhost -u " | ||
- | mosquitto_pub -h localhost -u " | ||
- | </ | ||
- | |||
- | === 3.2 Abonnement à un topic === | ||
- | L' | ||
- | |||
- | * **Sans sécurité** | ||
- | <code bash cmd2a.bash> | ||
- | mosquitto_sub -h localhost -t maison/ | ||
- | </ | ||
- | |||
- | * **Avec sécurité** | ||
- | <code bash cmd2b.bash> | ||
- | mosquitto_sub -h localhost -u " | ||
- | </ | ||
- | |||
- | > **N.B.** | ||
- | > **-h** : permet de spécifier l' | ||
- | > **-t** : permet de spécifier le topic (publication, | ||
- | > **-m** : permet de spécifier le message (payload). | ||
- | > **-u** : permet de spécifier l' | ||
- | > **-P** : permet de spécifier le mot de passe associé à l' | ||
- | |||
- | === Résultat attendu === | ||
- | {{ : | ||
- | |||
- | ==== 4. Sécurité ==== | ||
- | Si un fichier de mots de passe a été défini sur le broker Mosquitto comme cela est indiqué au paragraphe " | ||
- | {{ : | ||
- | |||
- | * Il faut modifier la commande // | ||
- | <code bash cmd3.bash> | ||
- | client.connect(readconf.myhostname, | ||
- | </ | ||
- | |||
- | * Pour simplifier les tests, il est également possible d' | ||
- | |||
- | <code bash *.bash> | ||
- | sudo nano / | ||
- | allow_anonymous true # Connexions sans mot de passe autorisées | ||
- | </ | ||
- | |||
- | |||
- | ==== 5. QoS ==== | ||
- | La qualité de service (QDS) ou quality of service (QoS) est la capacité à véhiculer dans de bonnes conditions un type de trafic donné. Voir [[raspberrypi: | ||
- | |||
- | <note warning> | ||
- | ---- | ||
- | |||
- | ==== Résumé pour un ESP8266 ==== | ||
- | * La gestion des **paramètres de connexion** est simplifiée en les sauvegardant dans l' | ||
- | |||
- | <code cpp *.cpp> | ||
- | // Initialisation des paramètres de connexion | ||
- | EEconf myconf = { | ||
- | // A remplacer par : | ||
- | " | ||
- | " | ||
- | " | ||
- | // Ce nom peut être repris dans les topics. | ||
- | }; | ||
- | </ | ||
- | |||
- | * Si mDNS est installé, **configurer le nom du broker** et **créer les topics** dans le fichier // | ||
- | |||
- | <code cpp *.cpp> | ||
- | // Nom de la machine sur laquelle est installé le broker (mDNS) | ||
- | const char *mqtt_server = " | ||
- | </ | ||
- | |||
- | * La **publication** des topics est placée dans la boucle **loop** | ||
- | |||
- | <code cpp *.cpp> | ||
- | // Extrait | ||
- | // Construction du topic avec le nom d' | ||
- | // Topic " | ||
- | sprintf(topic, | ||
- | </ | ||
- | |||
- | * La **réponse** à un **abonnement** est placée dans une **fonction de rappel** nommée // | ||
- | <code cpp *.cpp> | ||
- | // Gestion des topics | ||
- | void callback(char *topic, byte *payload, unsigned int length) | ||
- | { | ||
- | // A compléter | ||
- | } | ||
- | </ | ||
- | ---- | ||
- | ===== B. Pour aller plus loin ===== | ||
- | |||
- | {{ : | ||
- | ==== Projet Domotique HG (MàJ le 3/11/21) ==== | ||
- | <note tip> | ||
- | * Description du projet [[https:// | ||
- | * Code des cartes ArduinoESP8266, | ||
- | * Code Node-Red [[https:// | ||
- | </ | ||
- | |