Telemetrie über das MQTT Protokoll - teuler/robotling GitHub Wiki
MicroPython unterstützt das MQTT-Protokoll (Message Queuing Telemetry Transport), welches sich als offenes Nachrichtenprotokoll für Machine-to-Machine-Kommunikation (M2M) hervorragend für die robuste Übertragung von Telemetriedaten zwischen Geräten eignet. Dabei tauschen Clients über einen "Broker" genannten Server Nachrichten aus, die in Themen (Topics) organisiert sind. Clients können Nachrichten zu Topics veröffentlichen ("publish") und/oder ausgewählte Topics abonnieren.
MQTT ermöglicht, Telemetriedaten über WLAN zu versenden, um den aktuellen Zustand des Roboters auf einem PC quasi in "Echtzeit" zu visualisieren. Voraussetzung ist nur eine WLAN-fähiger ESP32 (wie der HUZZAH32).
WARNUNG: Obwohl MQTT auch verschlüsselte und gesicherte
Kommunikation unterstützt, werden in den folgenden Beispielen die Daten der
Einfachheit halber unverschlüsselt und ungesichert übertragen. Dessen sollte man
sich bewußt sein, wenn man nicht innerhalb des privaten WLAN-Netzwerks
bleibt (d.h. mit lokalem MQTT-Broker), sondern öffentliche MQTT-Broker (wie
z.B. test.mosquitto.org oder mqtt.eclipse.org)
benutzt.
Im Folgenden wird geschildert, wie man einen MQTT-Broker inklusive Tools auf dem PC installiert, den Broker dort startet und testet, wie man vom Robotling aus Telemetriedaten verschickt und anschließend auf dem PC verarbeitet.
- MQTT-Installation auf dem PC
- Einen lokalen MQTT-Broker auf dem PC starten und testen
- Robotling verschickt Statusnachrichten
- Robotling-Nachrichten empfangen
Hinweis: Die folgenden Instruktionen wurden unter Windows 10 mit einer aktuellen Anaconda-Distribution von Python 3 getestet (Anaconda 03.2019, 64bit, Python 3.7). Die Anweisungen sollten mit wenigen Änderungen auch unter Linux funktionieren. Hinweise für die Installation unter anderen Betriebssystemen finden sich auf den jeweiligen Webseiten der Pakete.
-
paho-mqtt
ist die Python-Adaptation der Eclipse Paho MQTT Python client-Bibliothek und implementiert das aktuelle MQTT-Protokoll. Diese Bibliothek ermöglicht, einen Client in Python zu erstellen, der sich mit einem MQTT-Broker verbindet, um Nachrichten zu versenden und Nachrichten zu bestimmten abonnierten Topics zu empfangen.pip install paho-mqtt
-
Mosquitto ist ein Open Source MQTT Broker, der von der Eclipse Foundation gepflegt wird. Die Installationsanweisungen finden sich hier.
Die Installation testet man am einfachesten, indem man drei Kommandozeilenfenster öffnet; eines für den MQTT-Broker (=Server) und zwei für die MQTT-Clients. In allen Fenstern muss man zunächst in das Installationsverzeichnis von Mosquitto wechseln, z.B.:
cd "C:\Program Files\mosquitto\"
-
Im ersten Fenstern startet man den Broker mit:
.\mosquitto.exe -v
Die Option
-v
(verbose) sorgt dafür, dass der Broker über alle Ereignisse berichtet; das hilft ggf. beim Debuggen. -
Im zweiten Fenstern starten man einen Empfänger-Client, der Nachrichten zu einem bestimmten Topic abonniert:
.\mosquitto_sub.exe -h 192.168.4.150 -t robotling/test
Die Option
-h
gibt die IP-Adresse des Brokers an; in diesem Fall ist das die IP-Adresse des PCs, auf dem dieser Test ausgeführt wird (z.B. mitipconfig
zu ermitteln). Die Option-t
gibt den zu abonnierenden Topic an (hierrobotling/test
). Der Client wartet nun auf Nachrichten, die den Broker zu diesem Topic erreichen. -
Vom dritten Fenster erfolgt der Nachrichtenversand durch den Sender-Client:
.\mosquitto_pub.exe -h 192.168.4.150 -t robotling/test -m "123"
Dieser Befehl versendet die Nachricht
123
unter dem Topicrobotling/test
an den MQTT-Broker unter der IP-Adresse192.168.4.150
. Sobald der Befehl ausgeführt wird, erscheinen entsprechende Protokolleinträge im Fenster des Brokers ...[...] 1563573666: New connection from 192.168.4.150 on port 1883. 1563573666: New client connected from 192.168.4.150 as mosq/IUMc414fsphFAkDQXy (p2, c1, k60). 1563573666: No will message specified. 1563573666: Sending CONNACK to mosq/IUMc414fsphFAkDQXy (0, 0) 1563573666: Received SUBSCRIBE from mosq/IUMc414fsphFAkDQXy 1563573666: robotling/test (QoS 0) 1563573666: mosq/IUMc414fsphFAkDQXy 0 robotling/test 1563573666: Sending SUBACK to mosq/IUMc414fsphFAkDQXy
und die Nachricht
123
im Fenster des Empfänger-Clients:PS C:\Program Files\mosquitto> .\mosquitto_sub.exe -h 192.168.4.150 -t robotling/test 123
Für die Versendung von Telemetrie muss der Robotling natürlich mit einem WLAN-fähigen Mikrocontrollermodul (z.B. ESP32) ausgestattet sein. Eine einfache MQTT-API ist bereits in MicroPython eingebaut (umqtt
). umqtt
bietet zwei verschiedene Clients an,
simple
und robust
, wobei der wesentliche Unterschied darin besteht, dass die "robuste" Version automatisch versucht, unterbrochene Verbindungen wiederherzustellen. Hier wird umqtt.robust
verwendet.
Hinweis: Der folgende Code wurde bisher nur mit dem HUZZAH32-Modul getestet.
Damit der Robotling Telemetrie als MQTT-Nachrichten verschickt (d.h. veröffentlicht), müssen folgenden Einstellungen geändert werden:
-
In
hexbug_config.py
muss die KonstanteSEND_TELEMETRY
auf1
gesetzt werden. -
Das WLAN wird aktiviert, indem man in
hexbug_config.py
den String"wlan"
zur ListeMORE_DEVICES
hinzufügt. -
Die Datei
NETWORK.py
, aus der der Robotling Informationen über das WLAN und den zu verwendeten MQTT-Broker erhält, muss angepasst werden:my_ssid = "MY_WLAN_SSID" my_wp2_pwd = "MY_WLAN_PASSWORD" my_mqtt_usr = "" my_mqtt_pwd = "" my_mqtt_srv = "MY_BROKER" my_mqtt_port = 1883 my_mqtt_alive_s = 60
Neben
my_ssid
undmy_wp2_pwd
muss der MQTT-Broker inmy_mqtt_srv
definiert werden. Dabei kannmy_mqtt_srv
auf die IP-Adresse des PCs im lokalen WLAN gesetzt werden, auf dem der Mosquitto-Broker läuft (siehe oben); es kann aber auch ein öffentlicher Broker wietest.mosquitto.org
odermqtt.eclipse.org
sein.
Beim Start des Robotlings kann man anhand der roten on-board LED verfolgen, wie sich das HUZZAH-Modul mit dem WLAN (rasches Blinken der LED) und dann mit dem MQTT-Broker (rote LED an) verbindet. Dauert das Blinken länger als ein paar Sekunden oder bleibt die LED an, weist dies auf ein Problem hin, zu dessen Eingrenzung man sich die Ausgabe in der REPL ansehen muss.
Zu Beachten ist, dass der Robotling-Code für das Zusammensetzen und Verschicken einer Telemetrie-Nachricht im Schnitt etwa 7 ms benötigt. Die Daten werden in housekeeper
verschickt, d.h. in der Routine, die u.a. die Sensordaten und den Neopixel aktualisiert und die daher oft (20 Hz) aufgerufen wird. Daher reduziert die Telemetrie-Option auch etwas die Rechenzeit, die dem Roboter für andere Aufgaben (z.B. Verhalten) zur Verfügung stehen. Man sollte also diese Option nur aktivieren, wenn man sie benötigt.
Ohne die Telemetrie-Option verbringt der Roboter etwa 10 ms mit "housekeeping", d.h. etwa 20% der Rechenzeit:
Memory : 38% of 117kB heap RAM used.
Battery : 4.2V, ~100% charged
Performance: spin: 9.830ms @ 20.0Hz ~20%
Mit Telemetrie-Option sind es 17 ms und 35% der Rechenzeit:
Memory : 41% of 117kB heap RAM used.
Battery : 4.2V, ~100% charged
Performance: spin: 17.436ms @ 20.0Hz ~35%
Wenn ein Fehler (exception) im Programmcode passiert, versucht der Roboter die entsprechende Traceback-Information als letzte Nachricht über MQTT zu verschicken. Dies hilf bei der Fehlersuche, auch man die Ausgabe des Roboter nicht per USB in der REPL sieht.
robotling_b4e62da1dccd/raw {"debug": "Traceback (most recent call last):\n
File \"main.py\", line 124, in <module>\n File \"main.py\", line 52, in
main\n File \"hexbug.py\", line 343, in lookAround\nZeroDivisionError:
divide by zero\n"}
Um testweise Robotling-Nachrichten zu empfangen, kann man zunächst das oben bereits
genannte Kommandozeilenprogramm mosquitto_sub
verwenden. Nach dem Wechsel in das
Mosquitto-Programmverzeichnis, abonniert man die Robotling-Nachrichten mit
.\mosquitto_sub.exe -h 192.168.4.150 -t "robotling_b4e62da1dccd" -v
wobei 192.168.4.150
durch die IP-Adresse des lokalen Brokers ersetzt werden muss.
Alternativ geht auch ein öffentlicher MQTT-Broker.
Wichtig ist, dass der Robotling denselben Broker benutzt
(siehe NETWORK.py
).
robotling_b4e62da1dccd
muss durch den GUID des eigenen Robotlings ersetzt werden.
Der GUID wird ausgegeben, wenn der Robotling bootet:
Robotling (board v1.20, software v0.1.7.0) w/ MicroPython 1.11.0 (esp32)
GUID = 'b'robotling_b4e62da1dccd''
Initializing ...
[...]
Nach dem Starten von mosquitto_sub
sollten Nachrichten wie die folgende
ausgegeben werden:
[...]
robotling_b4e62da1dccd/raw {"state": 3, "timestamp_s": 53.663, "power":
{"motor_load": [0, 63], "battery_V": 3.936561}, "debug": [1, 0.0],
"sensor": {"compass": {"pitch_deg": 96, "heading_deg": 342.8, "roll_deg": -7},
"distance_cm": [5, 4, 11]}}
[...]
Jede Nachricht beginnt mit dem GUID ("globally unique idendifier") des Robotlings. Für den GUID wird die ID des ESP32-Chips mittels machine.unique_id()
ausgelesen und in hexadezimaler Form verwendet (z.B. robotling_b4e62da1dccd
).
Die Telemetriedaten werden aus Performancegründen (siehe auch vorheriger Abschnitt) nicht in der oben erwähnten
Topic-Struktur verschickt, sondern in Form eines einzigen Strings unter dem Topic raw
. Jeden Wert als einzelne, MQTT-konforme Nachricht unter einem eigenen (Sub)Topic (z.B. sensor/compass/heading_deg
) zu verschicken, würde zu viel Zeit kosten und die Hauptschleife des Robotling stark verlangsamen. Stattdessen sammelt der Roboter alle Daten in einem Dictionary, welches dann mittels ujson.dumps()
in einen JSON-String umgewandelt und verschickt wird. JSON (JavaScript Object Notation) ist ein einfaches Format für den Datenaustausch, dass von vielen Programmiersprachen inklusive Python unterstützt wird.
Welche Daten versandt werden, hängt natürlich davon ab, wie der Robotling konfiguriert ist. Zum Beispiel taucht der Schlüssel {"photodiode": {"intensity": [47, 49]}}
unter "sensor":
nur auf, wenn das Verhalten "find light" in hexbug_config.py
aktiviert ist.
test_mqtt.py
ist ein einfaches Python-Beispiel,
dass illustriert, wie man MQTT-Nachrichten des Roboters abonniert und verarbeitet. Im Skript müssen die GUID des Robotling sowie der verwendete MQTT-Broker definiert werden.
hexbug_relay.py
baut auf test_mqtt.py
auf. Es abonniert Robotling-MQTT-Nachrichten und veröffentlicht sie seinerseits in einer "besseren" Topic-struktur.
Es gibt eine Vielzahl von MQTT-Tools für jeden möglichen Zweck; hier findet man eine gute Übersicht. Zum Beispiel macht es der freie MQTT Explorer von Thomas Nordquist sehr einfach, die Nachrichten des Roboters zu visualisieren.
Weiter zu "Adding native modules to MicroPython" (Englisch)