Mqtt avec Arduino

Le protocole Mqtt est utilisé par les objets connectés pour communiquer. Il s’agit d’un protocole très léger de messagerie. Il permet donc à un objet connecté d’envoyer et/ou de recevoir des messages.

Un serveur Mqtt unique (Broker) sert à centraliser les messages. Ainsi un objet connecté va publier (publish) vers le Broker. Pour recevoir des messages le client va souscrire (subscribe) à leurs réception auprès du Broker.

Pour que les messages ne se mélangent pas, ils sont publiés sur une chaine (topic).

Par exemple :  blaisepascal/meteo1/temperature

Pour récupérer la température de la station météo1 du lycée Blaise Pascal on va donc souscrire au topic : blaisepascal/meteo1/temperature

La bibliothèque pubsubclient.h (disponible dans Croquis – Inclure une bibliothèque – gérer les bibliothèques), permet de publier et souscrire auprès d’un Broker MQTT. (voir http://arduino.blaisepascal.fr/installer-une-bibliotheque/)

Après connexion au broker, la commande :

client.publish("esp/test", "Hello from ESP8266");

permet de publier la phrase « Hello from ESP8266 » sur le topic esp/test.

mqtt_publish("esp/test/qqchose",temp);

permet de publier un float sur le topic esp/test/qqchose.

La fonction callback permet de programmer une action lors de l’apparition d’une donnée sur un topic auquel on a souscrit. Pour souscrire a un topic, il faut utiliser la commande :

client.subscribe("esp/test/souscription");

Cette commande pourra être placée juste après la connexion au serveur Mqtt (ci-dessous la fonction reconnect().

Exemple de code Arduino avec un ESP8266 :

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h> 
#include <PubSubClient.h> //Librairie pour la gestion Mqtt 

//WIFI
const char* ssid = "SSID";
const char* password = "mdp";
//MQTT
const char* mqtt_server = "192.168.x.y";//Adresse IP du Broker Mqtt
const int mqttPort = 1883; //port utilisé par le Broker 
long tps=0;

ESP8266WiFiMulti WiFiMulti;
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {

  Serial.begin(115200);
  setup_wifi();
  setup_mqtt();
  client.publish("esp/test", "Hello from ESP8266");
}

void loop() {
  reconnect();
  client.loop(); 
  //On utilise pas un delay pour ne pas bloquer la réception de messages 
  if (millis()-tps>10000){
     tps=millis();
     float temp = random(30);
     mqtt_publish("esp/test/qqchose",temp);
     Serial.print("qqchose : ");
     Serial.println(temp); 
   }
}

void setup_wifi(){
  //connexion au wifi
  WiFiMulti.addAP(ssid, password);
  while ( WiFiMulti.run() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  Serial.println("");
  Serial.println("WiFi connecté");
  Serial.print("MAC : ");
  Serial.println(WiFi.macAddress());
  Serial.print("Adresse IP : ");
  Serial.println(WiFi.localIP());
}

void setup_mqtt(){
  client.setServer(mqtt_server, mqttPort);
  client.setCallback(callback);//Déclaration de la fonction de souscription
  reconnect();
}

//Callback doit être présent pour souscrire a un topic et de prévoir une action 
void callback(char* topic, byte *payload, unsigned int length) {
   Serial.println("-------Nouveau message du broker mqtt-----");
   Serial.print("Canal:");
   Serial.println(topic);
   Serial.print("donnee:");
   Serial.write(payload, length);
   Serial.println();
   if ((char)payload[0] == '1') {
     Serial.println("LED ON");
      digitalWrite(2,HIGH); 
   } else {
     Serial.println("LED OFF");
     digitalWrite(2,LOW); 
   }
 }


void reconnect(){
  while (!client.connected()) {
    Serial.println("Connection au serveur MQTT ...");
    if (client.connect("ESP32Client")) {
      Serial.println("MQTT connecté");
    }
    else {
      Serial.print("echec, code erreur= ");
      Serial.println(client.state());
      Serial.println("nouvel essai dans 2s");
    delay(2000);
    }
  }
  client.subscribe("esp/test/led");//souscription au topic led pour commander une led
}

//Fonction pour publier un float sur un topic 
void mqtt_publish(String topic, float t){
  char top[topic.length()+1];
  topic.toCharArray(top,topic.length()+1);
  char t_char[50];
  String t_str = String(t);
  t_str.toCharArray(t_char, t_str.length() + 1);
  client.publish(top,t_char);
}

Utilisation d’un Broker en ligne

L’utilisation d’un Broker gratuit en ligne permet de s’affranchir de l’installation d’un Broker et de publier/souscrire les messages Mqtt sur un Cloud.

Nous utiliserons un Broker en ligne gratuit : MaQiaTTo

Il suffit de s’inscrire avec un email. Les topics commenceront toujours par l’email.

exemple : prenom.nom@mail.org/meteo1/temperature

Code Arduino pour publier des données :

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h> 
#include <PubSubClient.h> 

//WIFI
const char* ssid = "SSID";
const char* password = "mdp";
//MQTT
#define MQTT_BROKER       "maqiatto.com"
#define MQTT_BROKER_PORT  1883
#define MQTT_USERNAME     "your-maqiatto-user-name"
#define MQTT_KEY          "your-maqiatto-broker-pass" 

ESP8266WiFiMulti WiFiMulti;
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {

  Serial.begin(115200);
  setup_wifi();
  setup_mqtt();
  client.publish("emailuser@maqiatto/test", "Hello from ESP32");
}

void loop() {
  reconnect();
  client.loop(); 
  float temp = random(30);
  mqtt_publish("emailuser@maqiatto/test/qqchose",temp);
  Serial.print("qqchose : ");
  Serial.println(temp); delay(10000);
}

void setup_wifi(){
  //connexion au wifi
  WiFiMulti.addAP(ssid, password);
  while ( WiFiMulti.run() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  Serial.println("");
  Serial.println("WiFi connecté");
  Serial.print("MAC : ");
  Serial.println(WiFi.macAddress());
  Serial.print("Adresse IP : ");
  Serial.println(WiFi.localIP());
}

void setup_mqtt(){
  client.setServer(MQTT_BROKER, MQTT_BROKER_PORT);
  reconnect();
}

void reconnect(){
  while (!client.connected()) {
    Serial.println("Connection au serveur MQTT ...");
    if (client.connect("ESPClient", MQTT_USERNAME, MQTT_KEY)) {
      Serial.println("MQTT connecté");
    }
    else {
      Serial.print("echec, code erreur= ");
      Serial.println(client.state());
      Serial.println("nouvel essai dans 2s");
    delay(2000);
    }
  }
}

//Fonction pour publier un float sur un topic
void mqtt_publish(String topic, float t){
  char top[topic.length()+1];
  topic.toCharArray(top,topic.length()+1);
  char t_char[50];
  String t_str = String(t);
  t_str.toCharArray(t_char, t_str.length() + 1);
  client.publish(top,t_char);
}

Remarque :

Il faut utiliser une carte avec wifi intégré de type ESP8266 ou ESP32 :

Arduino IDE : Installer les cartes ESP32 et ESP8266

Vous aimerez aussi...

7 réponses

  1. Mariller Guy dit :

    bonjour pourquoi j’obtiens chaque fois dans void setup ‘setup_wifi’ was not declared in this scope lors de la compilation une réponse me servirait grandement cordialement GM

  2. Arnaud BULCKE dit :

    Bonjour, normalement ça fonctionne, j’ai essayé. Au pire il faut déplacer le void setup_wifi() avant le void setup().

  3. mikael dit :

    erreur de compilation

  4. Arnaud BULCKE dit :

    Il faut choisir une carte ESP32 ou ESP8266 pour avoir le wifi intégré (cf https://arduino.blaisepascal.fr/arduino-ide-installer-les-cartes-esp32-et-esp8266/)

  5. Mikael dit :

    Autant pour moi ton code marche très bien.
    Par contre juste un petit détail important sur lequel je suis resté bloqué pendant très longtemps.
    C’ est de ne surtout pas oublier de rajouter dans la fonction  » setup() :

     » pinMode( 2 , OUTPUT)  » .

    Voila merci à toi pour ton partage .

    • Safidy dit :

      Bonjour, quelle version d’ Arduino utilises-tu dans ce projet?
      J’aimerai aussi savoir si il serait possible d’utiliser SerialSoftware pour relier l’esp8266 ou esp32 à l’Arduino au lieu d’utiliser les Pin TX et RX ?

      • Arnaud BULCKE dit :

        La version de l’IDE utilisée afin de pouvoir programmer des cartes ESP8266 ou ESP32 doit être en version 1.8 minimum.
        Pour programmer les cartes j’utilise la connexion USB donc le serial hardware fonctionne bien, mais il n’y a aucune raison que softwareserial ne fonctionne pas pour communiquer avec le PC.

Laisser un commentaire

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