Kommunikation

Pub/Sub-Systeme

Im Internet der Dinge (Internet of Things, IoT) tauschen viele Millionen Geräte, Sensoren und Aktoren untereinander Daten aus. Jedoch sind diese oft nicht sehr leistungsfähig und nur vorübergehend erreichbar, weil die Netzverbindung unterbrochen ist oder sie nur zeit- und ortsabhängig benötigt wird. Wie baut man nun eine Infrastruktur mit unzuverlässigen Teilnehmern (Clients), die nicht einmal in der Lage sind, die Liste der Empfänger für ihre Nachrichten zu verwalten?

Eine mögliche Lösung bieten sogenannte Publish/Subscribe-Systeme (Pub/Sub). Hier übernimmt ein Vermittler (Broker) die Aufgabe Nachrichten an die richtigen Empfänger weiterzuleiten. Jedes Gerät kann Daten senden (publish) oder dem Vermittler gegenüber mitteilen (subscribe), an welcher Art Nachrichten (topic) es interessiert ist und diese später empfangen.

Pub/Sub
Figure 1. Pub/Sub mit verschiedenen Teilnehmern

MQTT

MQTT[1] ist ein standardisiertes Nachrichtenprotokoll für Pub/Subs. Es wird seit 1999 stetig weiterentwickelt, bietet verschiedene Übertragungsgarantien (Quality of Service oder QoS) für den Nachrichtentransport und zeichnet sich durch geringe Ansprüche an Verbindungsqualität und Rechenleistung aus.

QoS Level

Für die Operationen subscribe und publish können als Option verschiedene QoS-Level festgelegt werden. Das MQTT-Protokoll sichert daraufhin über ggf. zusätzliche Nachrichten deren Einhaltung ab.

QoS Level 0

Die Nachricht erreicht die Empfänger höchstens einmal.

QoS Level 1

Die Nachricht erreicht die Empfänger mindestens einmal.

QoS Level 2

Die Nachricht erreicht die Empfänger genau einmal.

Mit Erhöhen des QoS-Level steigt die Komplexität des Protokolls und die Anzahl der verschickten Nachrichten im Hintergrund.

Im RoboLab wird MQTT auf QoS Level 1 eingesetzt.

Nutzung im RoboLab

Jeder Roboter nimmt während der Erkundung regelmäßig Kontakt zu seinem Mutterschiff auf, das ihn zuvor auf dem Planeten abgesetzt hat. Aufgrund der dichten Atmosphäre gelingt dies jedoch nur mit den Verstärkern der Versorgungsstationen, die an den Kreuzungspunkten der Pfade eingerichtet wurden.

Dort eröffnet der Roboter eine Übertragung und schickt seine geschätzte neue Position. Er empfängt vom Mutterschiff eine Bestätigung und möglicherweise verschiedene andere Nachrichten. Es wird dabei zwischen Planeten-Nachrichten, zum Beispiel nützlichen Informationen wie neuen Pfaden und den direkten Anweisungen des Mutterschiffs, also einem Erkundungsziel unterschieden.

Nach der letzten gesendeten oder empfangenen Nachricht wird ein Timeout von 3 Sekunden abgewartet, bevor die Kommunikation an dem Knoten beendet und die Erkundung fortgesetzt wird. Allgemein gesprochen gilt eine Übertragung an einem Knoten also als beendet, wenn der Roboter 3 Sekunden lang keine Nachricht mehr empfangen hat.

Das Timeout von 3 Sekunden bedeutet nicht, dass zwischen zwei gesendeten oder empfangenen Nachrichten jeweils 3 Sekunden Funkstille herrschen sollen.
Es ist auch nicht erforderlich, an jedem Knoten eine neue Verbindung zu erstellen und diese danach wieder zu schließen.

Nachrichten-Format

Die Kommunikation zwischen Roboter (Client) und Mutterschiff (Server) erfolgt im JSON-Format[2].
Nachrichten des Roboters haben dabei immer den from-Typ "client", Antwortnachrichten darauf vom Mutterschiff den from-Typ "server". Alle anderen Nachrichten haben den from-Typ "debug".
Weiterhin werden alle Keywords in camelCase-Notation angegebenen.

Ein JSON-Schema mit allen möglichen Nachrichtentypen und Feldern findet ihr hier.

Nicht alle vom Mutterschiff verschickten Nachrichten werden hier aufgeführt. Um die Entwicklung zu erleichtern, sendet das Mutterschiff Nachrichten mit dem from-Typ "debug". Dadurch sind Fehler schneller erkenn- und behebbar.
Wichtig: Debug-Nachrichten werden zur Prüfung NICHT gesendet!

Einige Platzhalter kurz erläutert:

<GROUP> = Group name / ID (z.B. 001)
<PLANET> = Planet name
<TEXT> = Integer / String placeholder
Xs, Ys, Ds = Start coordinates and direction
Xe, Ye, De = End coordinates and direction
Xc, Yc, Dc = End coordinates and direction, possibly corrected
Xt, Yt = Target coordinates

Beispiele:

Explorer: explorer/001
Planet: planet/Gromit/001

Häufige Fehler & Hinweise

  • Verschickte Nachrichten liegen im Format UTF-8 vor und müssen dementsprechend zuerst mit message.payload.decode('utf-8') dekodiert werden, damit es bei der Weiterverarbeitung der enthaltenen Strings nicht zu Fehlern kommt.

  • Häufig werden keine Nachrichten empfangen, da das Skript oder Modul für die Kommunikation direkt nach Start des Listeners schon wieder beendet wird. Eine while-Schleife wie im Beispiel schafft hier Abhilfe.

  • Koordinaten sowie Gewichte der Pfade werden als ganze Zahlen (Integer) geschickt.

  • Für Abzweigrichtungen Abkürzungen der Himmelsrichtungen in Form von ASCII-Zeichen N (Nord), E (Ost), S (Süd), W (West) verwendet.

  • Ihr könnt die Kommunikation, nach Installation geeigneter Werkzeuge, auch zuerst lokal auf eurem Rechner oder beispielsweise von eurem Handy aus testen. Bitte beachtet, dass das Mutterschiff (also der Server) nur über das WLAN-Netzwerk RoboLab Playground erreichbar ist.

# Subscribe to a topic and listen for any messages (https://mosquitto.org/man/mosquitto_sub-1.html)
$ mosquitto_sub -h mothership.inf.tu-dresden.de -p 1883 -u "<GROUP>" -P "<PASS>" -t "explorer/<GROUP>" -q 1

# Publish a message to the specified channel (https://mosquitto.org/man/mosquitto_pub-1.html)
$ mosquitto_pub -h mothership.inf.tu-dresden.de -p 1883 -u "<GROUP>" -P "<PASS>" -t "explorer/<GROUP>" -m '<JSON_STRING>' -q 1