MQTT – eine Einführung

Wer Daten von A nach B übermitteln möchte, hat unzählige Möglichkeiten dies zu tun. Je nach Anforderung und Anwendungsfall sieht die ideale Möglichkeit der Datenübermittlung anders aus. Für die Kommunikation zwischen Sensoren und im IoT-Bereich hat das Protokoll MQTT den Standard gesetzt. Immer dort wo verteilte Systeme miteinander kommunizieren müssen, eignet sich MQTT. MQTT steht für Message Queue Telemetry Transport und ist architektonisch relativ einfach aufgebaut. MQTT ist Nachrichten-orientiert und zentralisiert.

Die MQTT-Architektur

Für MQTT wird ein Broker benötigt, die zentrale Instanz an welche alle Clients ihre Nachrichten senden und sie von diesem Broker empfangen. Im Umkehrschluss bedeutet dies, das sich die Clients untereinander nicht kennen. Die gesamte Kommunikation läuft über dem Broker ab. Die Nachrichten werden nicht einfach wahllos an den Broker geschickt, sondern an ein sogenanntes Topic, ein Thema z.B. bad/lichtsensor1. Diese Topics sind hierarchisch aufgebaut und werden wie ein Pfad, mit einem Slash als Trennzeichen, definiert. Die Topics können von anderen Clients abonniert werden, so das diese bei einer neuen Nachricht betreffend des Topics informiert werden. Durch den hierarchischen Aufbau ist es möglich alle Topics einer bestimmten Hierarchieebene zu abonnieren. So würde der Topic:

bad/#

alle Untertopics von bad abonnieren. Eine weitere Möglichkeit ist es an einer bestimmten Stelle im Pfad das Sonderzeichen Plus zu benutzen:

+/lautsprecher/

In diesem Beispiel würden alle Lautsprecher aller Zimmer abonniert, so wären bad/lautsprecher als auch wohnzimmer/lautsprecher abgedeckt.

Nach der Verbindung mit einer CONNECT-Nachricht antwortet der Broker mit einer CONNACK-Nachricht. Damit ist die Verbindung etabliert. Der Client abonniert in dem Beispiel (siehe Bild) den Topic bad/lichtsensor1. Nun kann der Broker den Client über Nachrichten dieses Topic betreffend informieren. Wenn eine solche Nachricht eingeht, reagiert der Client, indem er auf dem Topic bad/lautsprecher die Nachricht bzw. den Wert on hinterlässt. Soll die Verbindung später wieder beendet werden, so wird eine DISCONNECT-Nachricht gesendet.

Die Kommunikation zwischen Client und Broker

Wenn ein Client keine aktive Verbindung zum Broker hat und eine neue Nachricht auf einem Topic aufläuft, auf welches der Client ein Abonnement hält, so verpasst er diese Nachricht. Anders sieht es aus, wenn der Sender beim Senden der Nachricht das sogenannte Retain-Flag für die Nachricht gesetzt hat. In diesem Fall stellt der Broker die Nachricht später noch zu.

Für den Fall, das die Verbindung vom Client nicht beendet wird bzw. beendet werden kann, existiert in MQTT ein sogenanntes Testament. So kann es bei Sensoren, die über Batterien gespeist sind durchaus vorkommen, dass die Verbindung plötzlich abbricht. Deshalb kann ein Client ein Testament, eine Nachricht auf ein Topic, hinterlegen, welche im Falle des Verbindungsabbruches vom Broker über das Topic versendet wird.

In der Praxis existieren zwei Versionen von MQTT: MQTT 3 welches die größte Basis besitzt und MQTT 5, welches mit einigen Neuerungen aufwarten kann, um das Protokoll fit für die Zukunft zu machen. Spezifiziert wird MQTT von OASIS, der Organization for the Advancement of Structured Information Standards. Die größten Unterschiede zwischen der letzten 3er-Version 3.1.1 und 5 sind Shared Subscriptions, welche Load Balancing auf Clientseite erlauben, Negative Acks eine Art Statuscodes ähnlich den HTTP-Statuscodes und User Properties, bei denen es sich um die Entsprechung zu den HTTP-Headern handelt. Diese können unter anderem für Metadaten genutzt werden. Ergeben haben sich diese Neuerungen hauptsächlich durch die Rückmeldungen aus der Community über die letzten Jahre.

Das OSI-Modell

Technisch basiert das MQTT-Protokoll auf TCP/IP. Dabei werde die Ports 1883 und 8883 genutzt. Der erste Port ist für die unverschlüsselte, der zweite Port für die verschlüsselte Kommunikation reserviert. Im OSI-Schichtenmodell befindet sich MQTT, wie HTTP auf dem Application Layer (OSI Layer 7). Im Gegensatz zu HTTP ist MQTT bleibt die Verbindung bei MQTT auch bestehen, wenn keine Daten übertragen werden.

Gestartet wird die Kommunikation des Clients mit einer CONNECT-Nachricht, woraufhin der Broker das Ganze mit einer CONNACK-Nachricht bestätigt. Nun kann der Client Topics abonnieren und Informationen zu einem Topic senden (PUBLISH).

MQTT beherrscht drei verschiedene Stufen des Quality of Service (QoS). Stufe 0 ist vom Modell her Fire-and-Forgot; die Nachricht wird einmal versendet und danach vom Broker vergessen. Ob sie ankommt, ist auf dieser QoS-Stufe nicht relevant. Bei Stufe 1 garantiert der Broker das die Nachricht mindestens einmal zugestellt wird, sie kann aber durchaus auch mehrfach bei den Clients ankommen. Stufe 2 hingegen garantiert, dass die Nachricht exakt einmal ankommt. Offiziell sind die QoS-Stufen wie folgt benannt:

At most once (0)
At least once (1)
Exactly once (2)

Je nach gewählter QoS-Stufe kommt es zu vermehrter Kommunikation über das MQTT-Protokoll. Bei Stufe 1 würde die Gegenstelle nach einer PUBLISH-Nachricht mit einer PUBACK-Nachricht antworten. Ohne eine solche Nachricht wird bei Stufe 1 der Sendevorgang so lange wiederholt, bis er von der Gegenseite bestätigt wurde. Deshalb ist nicht sichergestellt das die Nachricht nur einmal ankommt.

Wenn dies nicht gewünscht ist, kann stattdessen die QoS-Stufe 2 genutzt werden. Hier wird in der PUBLISH-Nachricht vom Sender eine ID mitgegeben. Nach dem Empfang wird die Nachricht gespeichert, aber noch nicht verarbeitet. Der Empfänger sendet eine PUBREC-Nachricht mit der ID an den Sender. Erhält der Sender diese Nachricht, sendet er eine Release-Nachricht (PUBREL), an den Empfänger. Als letzte Aktion sendet Empfänger ein PUBCOMP-Nachricht an den Sender und verarbeitet anschließend die Nachricht. Der Sender löscht beim Empfang der PUBCOMP-Nachricht die Nachricht.

Hintergrund für die unterschiedlichen Qualitätsstufen ist der Ressourcenverbrauch; je niedriger die QoS-Stufe um so weniger Ressourcen wie Zeit, Speicher und CPU, werden benötigt, um die Nachricht zu verarbeiten.

An Brokern und Client-Bibliotheken mangelt es MQTT nicht. Zu den bekanntesten Brokern gehören Mosquitto, HiveMQ und VerneMQ. Im Produktivbetrieb muss auf eine Absicherung der Topics geachtet werden. So ist es je nach Broker möglich das diese eine Authentifizierung der Clients verlangen und erst dann den Zugriff auf die Topics erlauben. Client-Bibliotheken für MQTT gibt es wie Sand am Meer, für unterschiedlichste Systeme wie Arduino, C, Java, .NET, Go und viele weitere Sprachen und Frameworks.

MQTTBox unter macOS

Daneben existieren grafische Client, welche die Nachrichten auf dem Broker anzeigen und die Interaktion mit einem Broker ermöglichen. Zu diesen Clients gehören unter anderem MQTT.fx, mqtt-spy und MQTTBox.

Regelwerk zu FUK – The System

Vor knapp zwei Jahren schrieb ich über ein Pen & Paper-System mit dem Namen FUK – The System. Wer heute die offizielle Seite des Projektes unter fuk-the-system.de besucht, wird leider feststellen das dort nichts mehr zu finden ist.

Die offizielle Seite des Projektes in früheren Tagen

Da die Seite nicht mehr verfügbar ist, stelle ich das Regelwerk, in der aktuellsten Version 1.2.0, zum Download zur Verfügung. Das Regelwerk ist unter der Creative Commons-Lizenz CC-BY lizenziert. Entwickelt wurde das Regelwerk ursprünglich vom Goldenen Kamel. Neben dem Regelwerk gibt es weitere Tools rund um FUK, wie z.B. einen Heldengenerator.

Alben von Imgur herunterladen

Imgur ist ein kostenloser Hosting-Dienst für Bilder. Die Bilder können bei Imgur zu Alben zusammengefasst werden. Leider gibt es keine einfache Möglichkeit direkt bei Imgur die Bilder eines Albums herunterzuladen. Abhilfe bei diesem Problem schafft der Imgur Album Downloader von Daniel Schep.

Die Oberfläche des Imgur Album Downloader

Über den Imgur Album Downloader wird das gewünschte Album geladen. Anschließend können die Bilder selektiert werden, welche heruntergeladen werden sollen. Danach kann der Download gestartet werden und nach einer kurzen Vorbereitungszeit liegen die Bilder auf des Festplatte. Der Quelltext des Imgur Album Downloader ist auf GitHub zu finden. Er ist unter der MIT-Lizenz lizenziert und damit freie Software.

Composer für PHP nutzen

Composer ist ein Paket- bzw. Dependency-Manager für PHP. Damit ist es möglich die Abhängigkeiten von PHP-Projekten komfortabel zu verwalten und aktuell zu halten. Dazu wird in dem Projekt eine Datei mit dem Namen composer.json angelegt. In dieser Datei finden sich die Abhängigkeiten für das Projekt:

{
  "minimum-stability": "RC",
  "require": {
    "slim/slim": "3.*"
  }
}

Um diese Abhängigkeiten initial dem Projekt hinzuzufügen, muss der Befehl:

composer install

eingegeben werden. Anschließend werden die Abhängigkeiten aufgelöst und heruntergeladen:

Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 6 installs, 0 updates, 0 removals
  - Installing psr/container (1.0.0): Loading from cache
  - Installing container-interop/container-interop (1.2.0): Loading from cache
  - Installing nikic/fast-route (v1.3.0): Loading from cache
  - Installing psr/http-message (1.0.1): Loading from cache
  - Installing pimple/pimple (v3.2.3): Loading from cache
  - Installing slim/slim (3.12.1): Loading from cache
Writing lock file
Generating autoload files

Nach der initialen Installation, finden die sich die Abhängigkeiten im Ordner vendor. Daneben wird eine composer.lock-Datei angelegt. In dieser sind die genauen Versionsnummern, der installierten Abhängigkeiten hinterlegt. Würde das Projekt nun nochmal mit der install-Option aufgerufen werden, so würden exakt diese Versionen installiert. Sollen diese Abhängigkeiten später aktualisiert werden, kann dafür der Befehl:

composer update

genutzt werden. Dabei werden die Versionen, welche sich in der composer-lock-Datei befinden ebenfalls aktualisiert.

getcomposer.org

Bezogen werden kann Composer unter anderem auf der offiziellen Seite unter getcomposer.org. Der Quelltext von Composer ist auf GitHub zu finden. Die Software ist unter der MIT-Lizenz lizenziert und damit freie Software.

Rewrites unter Nginx loggen

In der Konfiguration für den Webserver Nginx bzw. dessen Seiten, ist es möglich Rewrite-Direktiven zu nutzen. Damit können URLs umgeschrieben werden. Ein Beispiel für eine solche Direktive wäre z.B.

try_files $uri $uri/ @rewrite;

location @rewrite {
  rewrite ^/(.*)$ /index.php?_url=/$1;
}

Wenn dieser Rewrite zur Anwendung kommt, erscheint leider keine Meldung in den Nginx-Logs access.log und error.log. Um das Logging für Rewrites zu aktivieren, muss die Option:

rewrite_log on;

im server-Block der Konfiguration, welche unter /etc/nginx/sites-available/ zu finden ist, aktiviert werden. Daneben muss die Logging-Severity, also die Schwere der Events die geloggt werden sollen, angepasst werden. Dazu wird folgende Option dem server-Block hinzugefügt:

error_log /var/log/nginx/error.log notice;

Wenn die Log-Datei nun angeschaut wird, so finden sich dort für jeden Rewrite entsprechende Meldungen:

2019/05/29 08:35:30 [notice] 16054#16054: *127817 „^/(.*)$“ matches „/name/german“, client: 82.193.248.37, server: api.example.com, request: „GET /name/german HTTP/1.1“, host: „api.example.com“
2019/05/29 08:35:30 [notice] 16054#16054: *127817 rewritten data: „/index.php“, args: „_url=/name/german“, client: 82.193.248.37, server: api.example.com, request: „GET /name/german HTTP/1.1“, host: „api.example.com“