Créer un serveur MQTT

MQTT est un protocole de messagerie léger. Il fonctionne sur le principe « publication/souscription », c’est-à-dire qu’un objet connecté appelé « broker » publie des informations, et  d’autres objets connectés (les clients) souscrivent pour les recevoir. Dans cet article, on utilise le broker MQTT appelé Mosquitto pour publier la température (c’est le « topic ») mesurée par un capteur Dallas DS18B20 connecté à une carte Wemos Lolin32 Lite. Un Raspberry Pi Zéro W souscrit à ce topic. La communication entre les deux se fait au sein d’un réseau local WiFi.

Étape 1 : Installer Mosquitto sur le Raspberry Pi

Se connecter sur le Pi puis lancer l’installation de Mosquitto :

sudo apt-get install mosquitto

Si Mosquitto est déjà installé, cette commande permet de rechercher la dernière version.

Étape 2 : Installer le client Mosquitto

Entrer :

sudo apt-get install mosquitto-clients

Si Mosquitto est déjà installé, cette commande permet de rechercher la dernière version.
Nous allons lancer deux commandes, chacune dans un terminal. La première commande (mosquitto_sub) affiche les messages d’un topic publiés grâce à une seconde commande (mosquitto_pub) :
Dans le 1er terminal, on lance la commande pour souscrire (« subscribe ») :

mosquitto_sub -t temperature

L’option -t est suivie du nom du topic. A la suite de cette commande, les messages reçus pour le topic « temperature » apparaîtront dans le terminal 1 au fur et à mesure de leur publication.
Ouvrons un 2e terminal (Alt-F2) ou une seconde console (avec Putty). Ce terminal est celui qui va publier (« publish »). Il envoie les messages
du topic « temperature » :

mosquitto_pub –t temperature –m “Test température”

L’option -m est suivie du message. Si tout fonctionne, le 1e terminal doit afficher le message dès que la commande ci-dessus est entrée :

mosquitto_sub -t temperature
Test température

Pour arrêter la commande mosquitto_sub, taper Ctrl-C dans le terminal 1.

La souscription fonctionnant correctement sur le Pi, passons à la publication du message.

Etape 3 : Publier la température sur la carte d’acquisition

Lancer le logiciel Arduino et installer la carte (ici la Wemos Lolin32) qui va acquérir puis publier la température. Installer les librairies Adafruit MQTT, Wifi, OneWire, Dallas Temperature utilisées dans le programme ci-dessous. Avant de compiler ce programme, n’oubliez pas de l’adapter à votre propre montage (type de carte, numéro de la broche recevant la température du capteur) et indiquez :

  • le nom de votre réseau (WLAN_SSID)
  • son mot de passe (WLAN_PASS)
  • l’adresse IP du Raspberry
  • le nom du topic
// Matériel : Capteur de température Dallas DS18B20 sur une carte Wemos Lolin32 Lite.
// Une résistance de pull-up de 4,7 kΩ entre le + et le fil de données.
// La carte Lolin32 publie le topic "phil/temperature/capteur1" (voir ci-dessous) à l'aide de Adafruit MQTT sur le réseau local Wifi.
// Le Pi Zéro W souscrit à ce topic : mosquitto_sub -d -t phil/temp/capteur1
// Philippe Sept 2018
// https://atelier.guilers.org
// MQTT_connect() : voir
// https://learn.adafruit.com/mqtt-adafruit-io-and-you/intro-to-adafruit-mqtt

// Adafruit MQTT
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>

// Wifi
#include <ETH.h>
#include <WiFi.h>
#include <WiFiAP.h>
#include <WiFiClient.h>
#include <WiFiGeneric.h>
#include <WiFiMulti.h>
#include <WiFiScan.h>
#include <WiFiServer.h>
#include <WiFiSTA.h>
#include <WiFiType.h>
#include <WiFiUdp.h>

// OneWire et Dallas temperature
#include <OneWire.h>
#include <DallasTemperature.h>

/************************* WiFi Access Point *********************************/
#define WLAN_SSID "NomReseauWifi"
#define WLAN_PASS "MotDePasseWifi"

/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "192.168.0.11" // L'adresse du Pi Zero.
#define AIO_SERVERPORT 1883 // use 8883 for SSL
#define AIO_USERNAME "raspi"
#define AIO_KEY "raspberry"

/****************************** Capteur ***************************************/
float temperature=0.0;
// PIN_TEMP est le pin sur la carte Wemos Lolin32 Lite connecté à la patte centrale du
// capteur Dallas DS18B20.
const int PIN_TEMP = 19;
OneWire oneWire(PIN_TEMP);
DallasTemperature sensors(&oneWire);

/****************************** WiFi ***************************************/
// Create a WiFiClient class to connect to the MQTT broker.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

/****************************** MQTT ***************************************/
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

Adafruit_MQTT_Publish pub_temp = Adafruit_MQTT_Publish(&mqtt, "phil/temp/capteur1");

/****************************** ***************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
// void MQTT_connect();

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(10);
Serial.println(F("\nAtelier OC - Agora"));

// Connect to WiFi access point.
Serial.println();
Serial.print(F("Connecting to "));
Serial.println(WLAN_SSID);

WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();

Serial.println(F("WiFi connected."));
Serial.print(F("IP address: "));
Serial.println(WiFi.localIP());

// Capteur
sensors.begin();// initialise le capteur
}

void loop() {
// put your main code here, to run repeatedly:
sensors.requestTemperatures();
temperature=sensors.getTempCByIndex(0);
// Publier la température sur le broker MQTT
char BUFFER[32];
String str=String(temperature);
sprintf(BUFFER, "{\"temperature\": %s }", str.c_str());
Serial.println(BUFFER);

// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
pub_temp.publish(BUFFER);
delay(2000);
}

// https://learn.adafruit.com/mqtt-adafruit-io-and-you/intro-to-adafruit-mqtt
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect()
{
int8_t ret;
// Stop if already connected.
if (mqtt.connected())
{
return;
}
Serial.print("Connecting to MQTT... ");

while ((ret = mqtt.connect()) != 0)
{ // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected!");
}

//************************ end of file

Pour vérifier que le programme fonctionne normalement côté Lolin32, ouvrir le moniteur dans Arduino (« Outils »-> »Moniteur série ») et les messages de température du topic phil/temp/capteur1 doivent s’afficher :

Atelier OC - Agora
Connecting to NomReseauWifi
.....
WiFi connected.
IP address: 192.168.0.16
{"temperature": 20.75 }
Connecting to MQTT... MQTT Connected!
{"temperature": 22.00 }
{"temperature": 22.00 }
{"temperature": 22.00 }
{"temperature": 21.94 }
{"temperature": 21.94 }

Etape 4 : Souscrire au topic sur le Raspberry Pi

Maintenant que tout est en place, il est temps de souscrire au topic pour recevoir les messages :

mosquitto_sub -t phil/temp/capteur1
{"temperature": 22.00 }
{"temperature": 21.94 }
{"temperature": 21.94 }
^C

Le Pi affiche ainsi les messages de température qui peuvent par la suite être stockés dans une base de données type influxDB qui sera consultée par Grafana pour afficher la courbe de la température.

Références

Plus de détails sur MQTT :
https://blog.groupe-sii.com/le-protocole-mqtt-dans-liot/ .

Installer Mosquitto sur le Raspberry (en anglais) :
http://www.instructables.com/id/Installing-MQTT-BrokerMosquitto-on-Raspberry-Pi/

Utiliser la librairie Adafruit MQTT (en anglais) :
https://learn.adafruit.com/mqtt-adafruit-io-and-you/intro-to-adafruit-mqtt