MQTT & Python
paho-mqtt
. Lors du passage des versions 1.x vers les versions 2.x un certain nombre de changements ont été réalisés dans cette bibliothèque. Voir pour cela les consignes de migration à cette URL: Change between version 1.x and 2.0.
Dans ce tutoriel j’ai essayé de simplifier au maximum la mise en œuvre de MQTT en Python. J’ai pour cela utilisé la librairie Paho MQTT pour Python mise à disposition par la Fondation Eclipse.
Comme je l’avais déjà fait pour Java, mon objectif est de réduire cet exemple au strict minimum: un programme qui envoie un message MQTT fixe (pahoTest001Producer.py
), et un programme qui affiche les messages MQTT reçus (pahoTest001Consumer.py
). Dans la terminologie MQTT on parle de publish et de subscribe. Une fois que l’on a compris les mécanismes de base, faire “mieux” n’est plus qu’une question d’algorithmique ☺
NB: Après quelques recherches sur le net j’étais tombé sur cet article dont je me suis largement inspiré pour le présent tutoriel: How to use MQTT in Python (Paho).
Quelques infos supplémentaires sur MQTT:
- MQTT: The Standard for IoT Messaging
- Internet des Objets : bien comprendre MQTT
- What is MQTT ? An Introduction about MQTT
Installation de la bibliothèque Paho MQTT
Pour télécharger et installer la librairie Paho MQTT dans votre environnement Python nous allons utiliser l’outil pip3
de Python:
pip3 install paho-mqtt
Ce qui devrait vous donner un résultat du style:
login@host:dir$ pip3 install paho-mqtt
Collecting paho-mqtt
Downloading paho-mqtt-1.6.1.tar.gz (99 kB)
|████████████████████████████████| 99 kB 993 kB/s
Building wheels for collected packages: paho-mqtt
Building wheel for paho-mqtt (setup.py) ... done
Created wheel for paho-mqtt: filename=paho_mqtt-1.6.1-py3-none-any.whl size=62114 sha256=b96320ee231c7ed052f07c704e22126b7aa4217a0b2f31185c705ab7dce73b80
Stored in directory: /home/munier/.cache/pip/wheels/6a/48/01/c895c027e9b9367ec5470fbf371ee56e795a49ac6a19aa4c9f
Successfully built paho-mqtt
Installing collected packages: paho-mqtt
Successfully installed paho-mqtt-1.6.1
Envoi d’un message
Voici les principales étapes pour l’envoi d’un message MQTT:
-
configuration du broker MQTT et génération du ID client unique
import random from paho.mqtt import client as mqtt_client broker = 'test.mosquitto.org' port = 1883 topic = "/foo" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 1000)}'
-
création du connecteur MQTT (
client
) et connection au broker MQTTdef on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port)
-
création d’un message MQTT (
payload
= chaîne de caractères) puis publication sur le brokermsg = "A single message from my computer" result = client.publish(topic, msg) # result: [0, 1] status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}")
Code source complet du script <code>pahoTest001Producer.py</code>
# python 3.6
import random
import time
from paho.mqtt import client as mqtt_client
# --------------------------------------------------
broker = 'test.mosquitto.org'
port = 1883
topic = "/foo"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 1000)}'
# --------------------------------------------------
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.on_connect = on_connect
client.connect(broker, port)
return client
# --------------------------------------------------
def publish(client):
time.sleep(1)
msg = "A single message from my computer"
result = client.publish(topic, msg)
# result: [0, 1]
status = result[0]
if status == 0:
print(f"Send `{msg}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
# --------------------------------------------------
def run():
client = connect_mqtt()
client.loop_start()
publish(client)
# --------------------------------------------------
if __name__ == '__main__':
run()
# --------------------------------------------------
Réception d’un message
Voici les principales étapes pour la réception d’un message MQTT (NB: les 2 premières étapes sont strictement similaires à celles de la section précédente):
-
configuration du broker MQTT et génération du ID client unique
import random from paho.mqtt import client as mqtt_client broker = 'test.mosquitto.org' port = 1883 topic = "/foo" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 1000)}'
-
création du connecteur MQTT (
client
) et connection au broker MQTTdef on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port)
-
configuration du
client
pour définir l’action à exécuter (notion decallback
) à réception d’un message; ici on appelera la fonctionon_message(...)
def on_message(client, userdata, msg): s = str(msg.payload.decode("utf-8")) print(f"Received `{s}` from `{msg.topic}` topic") client.on_message = on_message
-
souscription du
client
au topicfoo
sur le broker MQTT; dès qu’un client publiera un message sur ce topic, le broker le diffusera à tous les autres clients qui y auront souscritclient.subscribe(topic)
Code source complet du script <code>pahoTest001Consumer.py</code>
# python3.6
import random
from paho.mqtt import client as mqtt_client
# --------------------------------------------------
broker = 'test.mosquitto.org'
port = 1883
topic = "/foo"
# generate client ID with pub prefix randomly
client_id = f'python-mqtt-{random.randint(0, 100)}'
# --------------------------------------------------
def connect_mqtt() -> mqtt_client:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.on_connect = on_connect
client.connect(broker, port)
return client
# --------------------------------------------------
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
s = str(msg.payload.decode("utf-8"))
print(f"Received `{s}` from `{msg.topic}` topic")
client.subscribe(topic)
client.on_message = on_message
# --------------------------------------------------
def run():
client = connect_mqtt()
subscribe(client)
client.loop_forever()
# --------------------------------------------------
if __name__ == '__main__':
run()
# --------------------------------------------------
Exécution de cet exemple
- Exécuter les 2 programmes dans 2 terminaux différents en démarrant le consumer en $1^{er}$ pour qu’il soit bien à l’écoute quand le producer enverra le message:
python3 pahoTest001Consumer.py python3 pahoTest001Producer.py