Mein Python MQTT Tutorial soll dir in ein paar Beispielen zeigen, wie du ganz leicht MQTT-Nachrichten mit Python senden und empfangen kannst.
Die Grundlagen habe ich bereits in meiner
MQTT Raspberry Pi Einführung vorgestellt.
Diese Python MQTT Einführung soll dir jedoch darüber hinaus weitere Funktionen und Anwendungsbeispiele verdeutlichen.
Inhaltsverzeichnis
- MQTT mit dem Raspberry Pi und dem ESP8266
- Was ist MQTT?
- Quality of Service Levels
- Python MQTT Bibliothek
- Kostenlose MQTT Broker
- MQTT Nachrichten empfangen
- MQTT Nachrichten versenden
- MQTT Last Will Nachricht konfigurieren
- Mit Nutzername und Password am Broker anmelden
Weitere MQTT Tutorials
Ich habe bereits zwei weitere MQTT-Tutorials hier veröffentlicht. Eines für den
Raspberry Pi und eines für den
NodeMCU ESP8266.
Dort gehe ich auf bereits auf ein paar der Punkte ein, die ich in diesem Guide erkläre. Sieh dir die beiden Tutorials auf jeden Fall an, wenn du den
Raspberry Pi oder ESP8266 mit MQTT in dein Smarthome integrieren möchtest!
MQTT Grundlagen
Bevor mit der Programmierung des Tutorials begonnen wird, möchte ich die Grundlagen des MQTT-Standards erklären.
Was ist MQTT?
Bei MQTT handelt es sich um ein
Publish-Subscribe-Messaging-Protokoll. Beim
Publish-Subscribe-Modell gibt es
Themen, die
abonniert (subscribe) und auf denen
Daten veröffentlicht (publish) werden können. Teilnehmer, die ein Thema abonniert haben, erhalten alle Daten, die auf diesem Kanal veröffentlicht werden.
In der Mitte des Netzwerks befindet sich ein
Broker, der als Server agiert und der die gesamte Kommunikation aller Teilnehmer verwaltet.
Das Publish-Subscribe-Modell eignet sich vor allem für Anwendungen im Bereich
Internet of Things, da dort sehr viele Daten gesammelt und mit anderen Geräten geteilt werden. Durch die Einteilung in einzelne Themen-Kanäle können die Daten gezielter verteilt werden.
Im Smarthome wird beispielsweise für jeden Raum ein Kanal angelegt und in diesem Kanal ein Unterkanal für jedes Gerät.
Ein
Bewegungsmelder im Wohnzimmer würde dann seine Daten auf dem Kanal
"Wohnzimmer/Bewegung" veröffentlichen. Die
Lampen im Wohnzimmer können dann auf neue Daten in diesem Kanal reagieren und zum Beispiel das
Licht einschalten, wenn der Bewegungsmelder eine neue Bewegung meldet.
Zusätzlich zu den normalen Nachrichten, gibt es auch sogenannte
Last Will Messages, die automatisch versendet werden können, wenn die Verbindung eines Geräts unerwartet getrennt wird. Im Smarthome kann so zum Beispiel eine Nachricht gesendet werden, wenn der Akku eines Sensors leer ist.
MQTT Quality of Service (QoS)
Der MQTT-Standard verfügt über drei unterschiedliche "Qualitätsstufen" (Quality of Service oder QoS). Sie geben an, wie zuverlässig die Zustellung der Nachrichten ist.
Die verfügbaren QoS-Levels:
- Nachricht kommt höchstens einmal an (0)
- Nachricht kommt mindestens einmal an (1)
- Nachricht kommt genau einmal an (2)
QoS Level 0: Nachricht kommt höchstens einmal an
Das unterste Quality of Service Level im MQTT-Standard
garantiert nicht, dass die Nachrichten auch ankommen. Vielmehr wird eine Nachricht gesendet und nicht geprüft, ob die Nachricht auch ankommt. Geht die Nachricht aufgrund von Verbindungsabbrüchen oder sonstigen technischen Problemen verloren, wird sie
nicht erneut gesendet.

Beim QoS Level 0 wird nur eine einzige Nachricht versendet.
Das QoS-Level 0 eignet sich also im Smarthome in den meisten Fällen
nicht für den produktiven Einsatz, da nicht sichergestellt ist, dass die Nachrichten auch ankommen. Dabei könnten beispielsweise Sensorwerte verloren gehen oder Geräte nicht auf Schaltbefehle reagieren.
QoS Level 1: Nachricht kommt mindestens einmal an
Das nächst-höhere Level besitzt bereits eine
Prüfung, ob die gesendete Nachricht auch beim Empfänger angekommen ist. Dies geschieht durch eine
Bestätigung des Empfängers, die an den Absender der Nachricht geschickt wird. Falls jedoch die Empfangsbestätigung verloren geht, sendet der Absender die Nachricht solange erneut, bis er eine
Empfangsbestätigung empfängt.

Das QoS-Level 1 erhält bereits eine Empfangsbestätigung.
Dieses QoS-Level eignet sich beim Einsatz im Smarthome
in den meisten Fällen für alle Schaltbefehle. Falls beispielsweise die Nachricht "Flur-Licht an" doppelt gesendet wird, geht das Licht an und die doppelte Nachricht ändert nichts daran. Lediglich bei Toggles (z.B. Licht umschalten) kann es zu Problemen führen, wenn eine Nachricht doppelt gesendet wird. Der erste Befehl schaltet hier das Gerät zum Beispiel an, während der zweite Befehl das Gerät sofort wieder ausschalten würde.
Für das Loggen von Sensorwerten macht das QoS-Level 1 nur wenig Sinn, da Sensorwerte dann doppelt gespeichert werden könnten. Abhilfe schafft hier das QoS-Level 2.
QoS Level 2: Nachricht kommt genau einmal an
Ähnlich wie das QoS-Level 1 besitzt auch Level 2 eine
Empfangsbestätigung - jedoch wird die
Empfangsbestätigung ebenfalls bestätigt und die komplette Transaktion damit abgeschlossen. Geht eine der Bestätigungen dabei verloren, so wird die ursprüngliche Nachricht erneut gesendet, jedoch mit dem Hinweis, dass es sich um ein Duplikat handelt. Der Empfänger kann diese Nachricht dann ignorieren, wenn er sie beim ersten Versuch bereits empfangen hat und anschließend seine Empfangsbestätigung senden. Diese Prozedur wird so oft wiederholt, bis alle Empfangsbestätigungen empfangen wurden.

Das QoS-Level 2 erhält auch eine zweite Empfangsbestätigung, damit der Erhalt aller Nachrichten gewährleistet werden kann.
Somit
eignet sich das QoS-Level 2 also auch für Toggles oder den Versand von Sensorwerten, da Duplikate von Nachrichten entsprechend gekennzeichnet sind und so nicht zu doppelten Daten führen.
Welches Quality of Service Level soll ich verwenden?
Im Smarthome dürfte das QoS-Level 0 in nahezu keinem Anwendungsfall Sinn machen, da nicht garantiert werden kann, dass die Nachricht überhaupt ankommt.
QoS-Level 1 hingegen reicht für alle Befehle aus, die einen festen Status setzen ("Gerät x an", "Heizung auf 25°C", "Lampe auf 100%"), jedoch weniger für das Loggen von Sensordaten oder Toggle-Befehle ("Lampe umschalten"), da das potenzielle doppelte Senden dieser Befehle den Status verfälscht.
QoS-Level 2 eignet sich dagegen am besten für das Loggen von Sensorwerten und Toggle-Befehle, da sichergestellt ist, dass jede Nachricht genau einmal empfangen wird.
MQTT-Client für Python 2
Um den MQTT-Client für Python Version 2.x zu installieren, führst du die folgenden Befehle auf der Kommandozeile aus:
sudo apt-get install python-pip -y
sudo pip install paho-mqtt
MQTT-Client für Python 3
Falls du Python Version 3.x verwendet, führst du hingegen die folgenden Befehle auf der Kommandozeile aus:
sudo apt-get install python3-pip -y
sudo pip3 install paho-mqtt
Kostenlose MQTT Broker
Es gibt ein paar
kostenlose und öffentliche MQTT-Broker, die du zum Testen von deinen Projekten benutzen kannst:
- mqtt.eclipse.org
- broker.hivemq.com
Da diese Broker jedoch für jeden
öffentlich zugänglich sind, solltest du
keine sensiblen Daten darüber versenden.
Für den produktiven Einsatz solltest du daher unbedingt einen eigenen MQTT-Broker verwenden. Ich habe hier bereits ein Tutorial veröffentlicht, dass dir erklärt, wie du einen Raspberry Pi als MQTT-Broker einsetzen kannst:
Raspberry Pi MQTT Tutorial
MQTT Nachrichten mit Python empfangen
Das erste Skript, dass erstellt werden muss, ist das Empfänger-Skript. Es abonniert Nachrichten aus einer bestimmten Topic und gibt alle Nachrichten aus, die darauf veröffentlicht werden.
Für dieses Tutorial benutze ich den
öffentlichen MQTT-Broker von HiveMQT.[/vc_column_text]Für das Empfänger-Skript fügst du den folgenden Code in deine IDE ein und führst ihn aus:
import paho.mqtt.client as mqtt
TOPIC = "home/tutorial/PubSubDemo"
BROKER_ADDRESS = "broker.hivemq.com"
PORT = 1883
def on_message(client, userdata, message):
msg = str(message.payload.decode("utf-8"))
print("message received: ", msg)
print("message topic: ", message.topic)
def on_connect(client, userdata, flags, rc):
print("Connected to MQTT Broker: " + BROKER_ADDRESS)
client.subscribe(TOPIC)
if __name__ == "__main__":
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER_ADDRESS, PORT)
client.loop_forever()
Der Code verbindet sich mit dem HiveMQ-Broker und abonniert das Topic "home/tutorial/PubSubDemo". Dann wartet er auf Nachrichten auf diesem Kanal und gibt alle aus.
MQTT Nachrichten mit Python verschicken
Als nächstes wird ein Skript erstellt, das eine Nachricht auf dem Topic "home/tutorial/PubSubDemo" mit dem
QoS-Level 1 veröffentlicht.
Füge einfach den folgenden Code ein und führe ihn aus (das erste Skript muss ebenfalls aktiv sein):
import paho.mqtt.client as mqtt
TOPIC = "home/tutorial/PubSubDemo"
BROKER_ADDRESS = "broker.hivemq.com"
PORT = 1883
QOS = 1
if __name__ == "__main__":
client = mqtt.Client()
client.connect(BROKER_ADDRESS, PORT)
print("Connected to MQTT Broker: " + BROKER_ADDRESS)
DATA = "{TEST_DATA}"
client.publish(TOPIC, DATA, qos=QOS)
client.loop()
Last Will Nachricht
Der MQTT-Standard ermöglicht es auch, andere Geräte zu benachrichtigen, wenn ein Gerät die Verbindung verliert. Dies ist möglich durch die sogenannte
Last Will-Message (deutsch: Letzter Wille). Diese Nachricht kann vom Client gesetzt werden und wird dann vom Broker an alle Subscriber einer definierten Topic gesendet. Im Smarthome-Einsatz ließe sich damit etwa das Gateway benachrichtigen, dass ein Gerät die Verbindung verloren hat.
Last Will Nachricht senden
Im folgenden Beispiel zeige ich dir, wie du mit Python ganz einfach eine
Last Will Message per MQTT versenden kannst.Als Empfänger wird wieder das Skript aus dem ersten Abschnitt dieses Tutorials verwendet. Die
Last Will Nachricht wird dann auf dem entsprechenden Topic veröffentlicht.Der andere Client setzt auf der Topic "home/tutorial/PubSubDemo" als Last Will Message die Nachricht "Verbindung beendet!", verbindet sich dann mit dem Broker und veröffentlicht danach die Nachricht "Hello World!" auf der selben Topic.
Als
Quality of Service wird Level 1 verwendet, alle Nachrichten kommen also mindestens einmal beim Empfänger an.
Verliert er die Verbindung, so veröffentlicht er also die Nachricht "Verbindung beendet!" auf dem Kanal "home/tutorial/PubSubDemo".
Um dies zu simulieren, wird das Skript beendet, ohne die Verbindung zum Broker ordnungsgemäß zu beenden.
Dies sorgt dafür, dass der Broker die Last Will Message auf dem entsprechenden Topic veröffentlicht.
import paho.mqtt.client as mqtt
TOPIC = "home/tutorial/PubSubDemo"
BROKER_ADDRESS = "broker.hivemq.com"
PORT = 1883
QOS = 1
if __name__ == "__main__":
client = mqtt.Client()
LAST_WILL = "Verbindung beendet!"
client.will_set(TOPIC, LAST_WILL, qos=QOS, retain=False)
client.connect(BROKER_ADDRESS, PORT)
print("Connected to MQTT Broker: " + BROKER_ADDRESS)
DATA = "{TEST_DATA}"
client.publish(TOPIC, DATA, qos=QOS)
client.loop()
Um nun das Beispiel zu testen, startest du den Empfänger-Code und führst anschließend den Absender-Code aus.
Der Empfänger sollte nun die Nachricht "Hello World!" erhalten und kurz darauf die Nachricht "Verbindung beendet!".

Die Ausgabe des Empfänger-Skripts sollte in etwa so aussehen.
Verbindung zu einem MQTT-Broker mit Zugangsdaten
Damit nicht jeder Zugang zu den veröffentlichten Nachrichten bekommt, ist es möglich, verschiedene Topics
mit einem Nutzernamen und einem Passwort zu schützen.
Um dich mit deinem Python-Skript
an einem geschützten Broker anzumelden, kannst du einfach das folgende Code-Snippet verwenden und die
entsprechenden Zugangsdaten einsetzen
client = mqtt.Client()
client.username_pw_set("my_username", "my_password")
Fazit
Ich hoffe, dass dir mein
Python MQTT Tutorial einen guten Einblick in das MQTT-Protokoll geben konnte!