Publier et souscrire à des messages MQTT
Le protocole MQTT est largement utilisé dans les systèmes distribués et IoT pour la communication légère entre appareils et applications. Souvent, une application doit être capable à la fois de publier des messages vers un topic MQTT et de s’abonner à des topics pour recevoir des messages.
Ce tutoriel explique en détail comment, avec la bibliothèque Python paho-mqtt
, réaliser un client MQTT qui publie et souscrit simultanément, en détaillant chaque étape, ainsi que la gestion des callbacks et des boucles réseau.
Préparation
Avant de commencer, assurez-vous que :
- Python 3.x est installé sur votre machine.
- La bibliothèque
paho-mqtt
est installée viapip install paho-mqtt
. - Un broker MQTT est accessible. Vous pouvez utiliser un broker public comme
test.mosquitto.org
ou installer un broker local commemosquitto
.
Principes clés à comprendre
Pour utiliser MQTT efficacement, voici quelques concepts fondamentaux à garder en tête :
- Broker MQTT : Le serveur qui relaie les messages entre clients.
- Client MQTT : Programme qui se connecte au broker, capable de publier et/ou souscrire à des topics.
- Topic : Canal de communication hiérarchique (ex:
maison/cuisine/température
). - QoS (Quality of Service) : Niveau de garantie de livraison d’un message (0, 1 ou 2).
- Callbacks : Fonctions que la bibliothèque exécute automatiquement en réponse à des événements (connexion, réception de message…).
Créer un client MQTT capable de publier et de souscrire
Le client MQTT doit :
- Se connecter au broker.
- S’abonner à un ou plusieurs topics.
- Publier des messages sur un topic.
- Traiter les messages reçus via une fonction callback.
Écrire le code complet
import paho.mqtt.client as mqtt
import time
# Fonction appelée quand la connexion au broker est établie
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connecté au broker MQTT avec succès")
# S'abonner à un topic à la connexion
client.subscribe("maison/salon/temperature", qos=1)
else:
print(f"Échec de connexion, code {rc}")
# Fonction appelée quand un message est reçu sur un topic abonné
def on_message(client, userdata, message):
payload = message.payload.decode('utf-8')
print(f"Message reçu sur {message.topic} : {payload}")
# Création d’un client MQTT
client = mqtt.Client()
# Assignation des callbacks
client.on_connect = on_connect
client.on_message = on_message
# Connexion au broker public test.mosquitto.org
client.connect("test.mosquitto.org", 1883, 60)
# Démarrage de la boucle réseau dans un thread séparé (non bloquant)
client.loop_start()
# Publier un message toutes les 5 secondes
try:
while True:
message = "23.5°C"
result = client.publish("maison/salon/temperature", message, qos=1)
status = result[0]
if status == 0:
print(f"Message publié : {message}")
else:
print(f"Erreur lors de la publication du message : {status}")
time.sleep(5)
except KeyboardInterrupt:
print("Arrêt du client MQTT")
# Arrêter proprement la boucle réseau
client.loop_stop()
client.disconnect()
Explications approfondies
on_connect
est appelée lorsque le client établit la connexion au broker. Si le code de retourrc
est 0, la connexion est réussie. À ce moment, on s’abonne au topicmaison/salon/temperature
.on_message
s’exécute chaque fois qu’un message arrive sur un topic auquel on est abonné. Ici, le message est décodé de bytes vers une chaîne UTF-8 pour être affiché.client.loop_start()
lance la boucle réseau dans un thread à part, ce qui permet au script principal de continuer à s’exécuter sans être bloqué.- Dans la boucle principale, on publie un message simulant la température toutes les 5 secondes sur le même topic. La publication retourne un tuple dont le premier élément est un code de statut (0 = succès).
- Un bloc
try-except KeyboardInterrupt
permet de terminer proprement le programme en interrompant la boucle avec Ctrl+C. - Enfin,
client.loop_stop()
etclient.disconnect()
arrêtent la boucle réseau et ferment la connexion proprement.
Pourquoi utiliser loop_start()
au lieu de loop_forever()
?
La méthode loop_forever()
bloque le programme tant que la connexion MQTT est active, ce qui empêche d’exécuter d’autres tâches dans le même script. Ici, nous voulons pouvoir publier des messages périodiquement tout en écoutant les messages reçus.
loop_start()
démarre la boucle réseau en arrière-plan, dans un thread distinct, et laisse le contrôle au script principal. Cela permet d’avoir un client MQTT capable de publier et recevoir en même temps.
Gestion des erreurs et reconnexions
Il est important dans une application réelle de gérer les erreurs et reconnexions automatiques. Paho-MQTT supporte cette gestion mais il faut parfois ajouter des callbacks additionnels, notamment on_disconnect
et on_subscribe
, pour gérer proprement ces cas. Le tutoriel de base n’en traite pas mais c’est une étape importante pour la robustesse.
Les QoS en MQTT
Le Quality of Service définit la garantie de livraison du message :
- QoS 0 : Livraison au mieux, sans confirmation (le message peut être perdu).
- QoS 1 : Livraison au moins une fois, avec accusé de réception (le message peut être dupliqué).
- QoS 2 : Livraison exactement une fois, avec un protocole d’échange supplémentaire (plus lourd).
Dans notre exemple, nous utilisons généralement QoS 1 pour un bon compromis entre fiabilité et performance.
Résumé
- Avec Paho-MQTT, il est facile de créer un client Python qui publie et s’abonne à des topics simultanément.
- Les callbacks permettent de gérer la connexion, la réception des messages, et plus encore.
- Utiliser
loop_start()
permet d’exécuter la boucle réseau en arrière-plan et de continuer à publier des messages dans la boucle principale. - Les QoS permettent d’adapter la fiabilité selon le besoin de l’application.
Pour aller plus loin
Voici quelques pistes pour améliorer ce client MQTT :
- Ajouter la gestion des reconnexions et des déconnexions.
- Utiliser des topics dynamiques et des jokers pour s’abonner à plusieurs sous-topics.
- Publier et recevoir des messages au format JSON pour structurer les données.
- Utiliser l’authentification par login/mot de passe ou TLS pour sécuriser la communication.
- Intégrer ce client dans une application plus large (exemple : interface web, collecte de données IoT, etc.).
Ce tutoriel vous offre une base solide pour maîtriser la publication et la souscription MQTT en Python et vous invite à expérimenter et étendre ces principes pour vos projets.