Über unsMediaKontaktImpressum
Florian Raschbichler 13. Juni 2017

MQTT - Leitfaden zum Protokoll für das Internet der Dinge

Das leichtgweichtige Protokoll MQTT ist klar auf dem Vormarsch. © Robert Kneschke / Fotolia.com
© Robert Kneschke / Fotolia.com

Im Jahr 2007 stellte Apple das iPhone der ersten Generation vor und revolutionierte damit den Smartphone-Markt. Im darauf folgenden Jahrzehnt wurden immer mehr Geräte "smart" – ob Waffeleisen oder Waschmaschine, Rollladen oder Toaster, E-Bike oder Armbanduhr: Immer mehr Geräte wurden connected bzw. smart. Das heißt, diese Geräte sind in der Lage, Daten zu versenden und zu empfangen und werden somit Teil des sogenannten Internet of Things. Insbesondere für die Verbindung über große Distanzen und unzuverlässige Netzwerke hat sich das leichtgewichtige Protokoll MQTT als wichtigstes Internet of Things-Standardprotokoll etabliert.

MQTT (MQ Telemetry Transport oder Message Queue Telemetry Transport) wurde 1999 zur M2M-(Maschine zu Maschine)-Kommunikation im Zuge eines gemeinsamen Projekts zur Ölpipeline [1] von IBM und Arcom Control Systems entwickelt.  Um den besondere Herausforderungen bei der Überwachung von Ölpipelines gerecht zu werden, wurden die folgenden Eigenschaften für das Protokoll erarbeitet:

  • Einfache Implementierung, um das Vernetzen von Geräten mit geringen Ressourcen zu ermöglichen,
  • unterschiedliche Servicequalitäten müssen existieren, damit auch in instabilen Netzen die Übertragung gewährleistet werden kann,
  • Metainformationen sollen serverseitig gespeichert werden, um die Notwendigkeit, diese nach Wiederaufnahme der Verbindung neu zu senden, zu unterbinden (session-awareness) und
  • Datentypen unterschiedlichster Art sollen ohne Festlegung auf eine bestimmte Struktur mit dem Protokoll übertragen werden (datenagnostisch).

Im Jahr 2010 wurde das Protokoll in Version 3.1 unter einer freien Lizenz und 2014 die bis heute aktuelle Version 3.1.1 [2] veröffentlicht, welche bei dem Standardisierungsgremium OASIS spezifiziert wurde.

Client-Server-Prinzip

Abb.1: Publish/Subscribe-Architektur von MQTT. © Florian Raschbichler
Abb.1: Publish/Subscribe-Architektur von MQTT. © Florian Raschbichler

Der zentrale Aspekt von MQTT ist eine ereignisgesteuerte Publish/Subscribe-Architektur. Es gibt keine Ende-zu-Ende-Verbindung, wie beispielsweise bei HTTP mit seiner Request/Response-Architektur, sondern einen zentralen Server (Broker), zu welchem sich Sender und Empfänger von Daten gleichermaßen verbinden. Gesendet (published) oder empfangen (subscribed) werden Nachrichten über sogenannte Topics. Ein Topic ist ein String, der eine URL-ähnliche Struktur aufweist und eine Art Betreff der Nachricht darstellt. Beispielsweise könnte ein Temperatursensor, der im Wohnzimmer angebracht ist, seine Messwerte auf dem Topic Daheim/Wohnzimmer/Temperatur veröffentlichen. Entscheidend ist, dass das Topic nicht die Adresse des Temperatursensors darstellt. Es ist viel mehr ein Kommunikationskanal, den der Temperatursensor nutzt, um Nachrichten an den Broker zu senden. Der Broker überprüft nun, welche Interessenten ihrerseits einen Kanal zum Empfangen dieser Daten geöffnet haben und leitet die Nachrichten an diese weiter.

Wildcard Subscriptions

MQTT bietet die Möglichkeit sogenannter Wildcard Subscriptions. Der +-Operator steht hier für eine Hierarchiestufe an beliebiger Stelle des Topictree und der #-Operator abonniert beliebig viele Hierarchiestufen, darf allerdings nur am Ende des Topictree verwendet werden.

Ein Beispiel:
Um Nachrichten auf dem Topic Daheim/Erdgeschoss/Besenkammer/Licht zu erhalten, gibt es beispielsweise folgende Möglichkeiten an Wildcard Subscriptions:

  • # (Die sogenannte Root-Wildcard abonniert alle Topics),
  • Daheim/+/+/Licht (somit werden Lichtquellen in allen Stockwerken und Zimmern abonniert),
  • Daheim/Erdgeschoss/# (Alle Informationen zum Erdgeschoss werden abonniert) oder
  • Daheim/#/Licht (Dies ist nicht zulässig und der MQTT-Broker wird diese Subscription nicht akzeptieren)

Quality of Service

Abb.2: Qos0. © Florian Raschbichler
Abb.2: Qos0. © Florian Raschbichler
Abb.3: Qos1. © Florian Raschbichler
Abb.3: Qos1. © Florian Raschbichler
Abb.4: Qos2. © Florian Raschbichler
Abb.4: Qos2. © Florian Raschbichler

MQTT baut auf TCP als Transportprotokoll auf, wodurch die komplette Übertragung von Nachrichten bei stabiler Verbindung garantiert ist. Da MQTT aber insbesondere für instabile Netzwerke konstruiert wurde, erlaubt es die Verwendung dreier unterschiedlicher Servicequalitäten (Quality of Service, QoS) 0, 1 und 2.

  • QoS=0 bedeutet, eine Nachricht wird maximal einmal geliefert. Bei Verwendung dieser Servicequalität wird jede Nachricht genau einmal verschickt (PUBLISH), ohne Rücksicht auf eine eventuelle Bestätigung des Empfängers.
  • QoS=1 wird als "mindestens einmal geliefert" verstanden. Hier wartet der Sender auf eine Bestätigung des Empfängers (PUBACK) und ist verpflichtet, die Nachricht erneut zu verschicken, insofern keine Empfangsbestätigung eintrifft. Allerdings kann es zu mehrfachen Auslieferungen kommen.
  • QoS=2 bietet die Garantie, dass eine Nachricht "exakt einmal geliefert" wurde. Um diese Garantie einhalten zu können, verwendet MQTT eine zweistufige Empfangsbestätigung.

Insbesondere bei instabilen Netzwerken kann es vorkommen, dass verschiedene Sender und Empfänger von Nachrichten häufig die Verbindung zum Broker verlieren und wieder neu aufbauen. Deshalb ist ein Szenario in dem eine bestimmte Anwendung (Empfänger), welche sich gemäß eines Messwertes eines Sensors (Sender) verhalten soll und gar nicht wissen kann, ob jener Sender aktuell zum Broker verbunden ist und aktuelle Werte übermittelt, vorstellbar und auch relevant.

Um für eine solche Situation gewappnet zu sein, wurden in MQTT die Funktionalitäten "Last Will and Testament" und "Retained Message" eingeführt. Ein Client, der sich zu einem Broker verbindet, hat die Möglichkeit, einen sogenannten letzten Willen bekannt zu geben. Dieser besteht aus einem Topic und einer Nachricht. Dieser letzte Wille wird vom Broker als Standard-MQTT-Nachricht für den Client versendet, sobald der Broker eine Verbindungsunterbrechung zum Client feststellt. Ein gutes Beispiel ist hier die Nachricht "offline" auf dem Topic ClientID/Status in Chat-Anwendungen.

Last Will and Testament – Retained Messages

Für das Sensor-Beispiel ist die Funktionalität allerdings nur nützlich, insofern die Anwendung (Empfänger) zu dem Zeitpunkt zum Broker verbunden ist, an dem dieser den Verbindungsabbruch des Sensors (Sender) feststellt. Da dies für sehr instabile Netzwerk eben nicht immer selbstverständlich ist, kann ein Sensor sogenannte "Retained Messages" – also gespeicherte Nachrichten – senden. Pro Topic kann eine Nachricht gespeichert sein, die überschrieben wird, falls erneut eine gespeicherte Nachricht auf dem gleichen Topic gesendet wird. Jeder Empfänger, der dieses Topic abonniert, bekommt als erstes die gespeicherte Nachricht zugesandt.

Praxis

2011 wurden die MQTT-Bibliotheken von IBM und Eurotech (vormals Arcom) unter das Dach der Eclipse Foundation gebracht und das Eclipse Paho-Projekt entstand. Paho bietet Implementierung für viele Programmiersprachen wie JavaScript, C++, Lua oder Java. Im Folgenden werden Beispiele an Hand der Java-Implementierung gezeigt. Sie lassen sich auf Grund ihrer Ähnlichkeit allerdings leicht in andere Programmiersprachen übertragen.

Zunächst wird ein MQTT-Broker benötigt. Solche zentralen MQTT-Kommunikationsserver existieren sowohl als Open Source [3], als auch in kommerzieller Variante [4]. Für die folgenden Beispiele wird ein sogenannter Public Broker verwendet, welcher über das Internet frei zugänglich ist, keinerlei Installation benötigt und somit für erste Gehversuche im Bereich MQTT optimal geeignet ist.

Wir verbinden einen MQTT Client unter Verwendung des Quality of Service-Levels 1 mit dem Public Broker [5] und machen von der Last Will and Testament-Funktion Gebrauch.

Codeblock 1:

String broker = “tcp://broker.mqttdashboard.com";
String clientID = “MQTTclient1”;
String lastWillTopic = “Daheim/Erdgeschoss/Bad/Thermometer/Status”;
String lastWillMessage = “offline”;
int qos = 1;

MqttClient client = new Mqttclient(broker,clientID,
    new MemoryPersistence());
// MemoryPersistence ist ein Zwischenspeicher für Daten bei Verbindungsabbruch

MqttConnectOptions mqttConnectOptions;

mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setWill(
lastWillTopic,    // Topic
lastWillMessage.getBytes("UTF-8"), // Nachricht
 1, // QoS
 true); // Retained Message

client.connect(mqttConnectOptions);

Wir teilen dem Broker mit, dass er bei Verbindungsabbruch die Nachricht "offline" auf dem Topic Daheim/Erdgeschoss/Kueche/Thermometer/Status mit dem Quality of Service-Level 1 senden soll und diese Nachricht für das Topic gespeichert werden soll.

Sobald der Client mit dem Broker verbunden ist, kann er Nachrichten senden und Topics abonnieren.

Codeblock 2:

//Publish
String topic = “Daheim/Erdgeschoss/Bad/Temperatur”;
String message = “22.5”;
int qos=1;

client.publish(
topic,
message.getBytes("UTF-8"),
qos,
true); //Retained Message 

Das folgende Beispiel zeigt einen anderen MQTT-Client (beispielsweise eine Smart Home-Applikation), der sich für alle Temperaturen im Erdgeschoss interessiert und von daher beim Abonnieren (Subscribe) von einer Wildcard Gebrauch macht. Vor dem Abonnieren wird ein Callback gesetzt. Dieser erlaubt es, ein Verhalten des Client festzulegen, für den Fall, dass eine Nachricht beim Client ankommt, eine gesendete Nachricht vom Broker bestätigt wurde oder die Verbindung zum Broker abbricht.

Codeblock 3:

//Subscribe

String topic = “Daheim/Erdgeschoss/Bad/Temperatur”;
int qos=2;

client.setCallback(new MqttCallback() {                
 @Override
 public void messageArrived
     (String arg0, MqttMessage arg1) throws Exception {
 // Weiterverarbeiten der Nachricht
 }
            
 @Override
 public void deliveryComplete(IMqttDeliveryToken arg0) {
 }
            
 @Override
 public void connectionLost(Throwable arg0) {
 }
});

client.subscribe(topic, qos);

Dieses Beispiel zeigt, dass Sender und Empfänger der Nachricht für das Senden und das Abonnieren unterschiedliche Quality of Service-Level nutzen. Das ist vollkommen legitim und verdeutlich die Tatsache, dass MQTT keine Ende-zu-Ende-Garantien bietet. Tatsächlich bietet der Sendevorgang Client (Publisher) zum Broker (Subscriber) die Garantie "mindestens ein Mal" und der Vorgang Broker (Publisher) zum Client (Subscriber) die Garantie "exakt ein Mal". Es ist nicht Aufgabe des Protokolls oder Brokers, eine Garantie für das Erreichen der Nachricht vom sendenden zum empfangenden Client zu bieten.

Plugin-Systeme

Benötigt eine Implementierung, die auf MQTT als Transportprotokoll setzt, in der Realität nun beispielsweise eine Ende-zu-Ende-Verbindungsgarantie oder andere Features, welche durch den MQTT-Standard nicht geboten sind, bietet sich die Verwendung eines Plugin-Systems an. Auch das Speichern empfangener Daten in eine Datenbank oder eine andere Art von Anbindung eines weiteren Systems lässt sich mit einem solchen Plugin-System umsetzen. Der Open Source-Broker Mosquitto [3], der sich besonders für Heimanwendungen oder Implementierungen weniger MQTT-Clients eignet, bieten die Möglichkeit, simple Funktionalitäten über ein Plugin-System zu integrierten. Der kommerzielle Broker HiveMQ [4] der durch seine hohe Verfügbarkeit und lineare, horizontale Skalierung bis hin zu Millionen von gleichzeitig verbundenen MQTT-Clients ideal für anspruchsvolle Integrationen von Unternehmen geeignet ist, bietet ein erweitertes Plugin-System, mit dessen Hilfe sich auch komplizierte Geschäftslogik oder die Integration weiterer Systeme umsetzen lassen.

Einsatz von MQTT

Die Möglichkeit, Nachrichten ereignisgesteuert zu pushen, der geringe Overhead und die Möglichkeit, bis zu einer hohen Zahl an gleichzeitig verbundenen Clients zu skalieren, sind einige der Gründe, warum sich MQTT hervorragend für Chat-Anwendungen wie den Facebook Messenger eignet. Ein weiteres typisches Einsatzgebiet für MQTT ist das Versenden von Sensordaten aus schlecht vernetzten oder schwer zugänglichen Bereichen. In diesen Fällen wird besonders von den Servicequalitäten, dem Last Will and Testament und Retained Messages profitiert, um suboptimale Rahmenbedingungen beim Netzwerk zu kompensieren.

Fazit

Die geringen Anforderungen vieler MQTT-Implementierungen erlauben es beinahe jeder Maschine, mit minimalen Ressourcen Teil des Internet der Dinge zu werden, also Daten zu verschicken und zu empfangen. Auch für eine große Anzahl an Software-Anwendungen bietet MQTT mit seiner leichtgewichtigen Push-Funktionalität die Möglichkeit, das Nutzererlebnis positiv zu beeinflussen. MQTT ist ganz klar auf dem Vormarsch und hat sich in der Zwischenzeit als de facto Standard-Protokoll des Internet of Things etabliert.

Quellen
  1. Projekt zur Ölpipeline von IBM und Arcom Control Systems
  2. Version 3.1 und Version 3.1.1
  3. MQTT-Kommunikationsserver als Open Source: Mosquitto
  4. MQTT-Kommunikationsserver als kommerzielle Variante: HiveMQ
  5. Public Broker

Weitere Informationen

nach Oben
Autor

Florian Raschbichler

Florian Raschbichler hilft IoT-Interessierten bei Problemlösungen rund um die Themen MQTT und HiveMQ. Er ist Supportverantwortlicher bei der dc-square GmbH, die hochskalierbare IoT-Lösungen wie den MQTT-Broker HiveMQ entwickelt.
>> Weiterlesen
botMessage_toctoc_comments_929