MQTT Einführung

Aus FHEMWiki
Wechseln zu: Navigation, Suche

MQTT ist ein Protokoll ("Message Queue Telemetry Transport"), mit dem Daten und Befehle zwischen verschiedenen Geräten ausgetauscht werden. Die Kommunikation erfolgt dabei über einen zentrale MQTT-Server, in alter Nomenklatur auch Broker genannt.

MQTT wurde entwickelt, um möglichst effizient, sicher und mit wenig Datenlast zu kommunizieren. MQTT ist nachrichtenorientiert, daher muss ein Client nicht beständig beim Server anfragen, ob neue Daten vorliegen. Heute findet sich MQTT vor allem im Bereich des Internet of Things (IoT). MQTT kann leicht mit FHEM verbunden werden, ohne dass dabei größerer CPU- oder Datenverbrauch entsteht.

Eine sehr kurze Einführung in MQTT

Die folgende Einführung kann eine vollwertige Einleitung wie beispielsweise diese Wikieinträge nicht ersetzen.

Bei MQTT findet die nachrichtenbasierte Kommunikation zwischen einzelnen Teilnehmern[1] in der Regel nicht direkt statt. Stattdessen werden alle Nachrichten von einem Teilnehmer an einen Serverdienst, den MQTT-Server (früher Broker genannt) übergeben, der dann dafür sorgt, dass die Nachricht an alle (berechtigten) anderen Teilnehmer verteilt wird, die sich für derartige Nachrichten "interessieren". Wenn also ein Teilnehmer ohne Server-Funktion (Client) Daten von einem bestimmten anderen Teilnehmer (anderer Client) empfangen will, muss es vorher dem MQTT-Server (Broker) mitteilen, dass es die Nachrichten dieses anderen Teilnehmers abonniert (deshalb wird dieser Vorgang als subscribe bezeichnet). Im IoT ist besonders interessant, dass Sender und Empfänger von Nachrichten durch den MQTT-Server vollständig entkoppelt werden können - jemand, der Daten bereit stellt, muss sich also nicht darum kümmern, wer diese Daten empfängt[2].

Eine Nachricht besteht im Wesentlichen aus den folgenden Elementen:

  • ClientID - das ist die Kennung des Senders einer Nachricht[3]
  • Topic - das ist die Adresse des endgültigen Empfängers. Topics sind einfache Strings, die mit Schrägstrichen getrennt werden (keine Leerzeichen und nur sehr wenige Sonderzeichen erlaubt). Ein Topic könnte beispielhaft so lauten: zuHause/1OG/Kueche/Licht/state. Diese Topics beinhalten also eine Hierarchie der Objekte - hier im Beispiel sind sie zuerst danach sortiert, ob sie sich zu Haus befinden, dann wird nach Stockwerken sortiert und im ersten Stock schaut man auf die Küche sowie das dort vorhandene Licht.
  • Payload - das ist der Inhalt der Nachricht, oft handelt es sich um Befehle oder Daten.
  • Quality of Service - soll geprüft werden, ob die Nachricht zugestellt wurde und wenn ja, mit welcher "Tiefe"?
  • Retained Message.

Details bitte in der oben genannten Einführung nachlesen.

MQTT kommuniziert üblicherweise über Port 1883, es können aber unter derselben Netzwerkadresse an unterschiedlichen Ports auch mehrere Serverdienste bereitstehen.

Installation in FHEM

Um MQTT in FHEM zu nutzen, benötigt man (mindestens) einen MQTT-Server. Es gibt zwei Möglichkeiten: Man kann FHEM-externe Server-Software (oder auch einen oder mehrere im Internet bereitstehende MQTT-Server) verwenden oder man kann die MQTT-Serverkomponente aktivieren, die mit MQTT2_SERVER in FHEM direkt bereitsteht. Hier werden kurz beide Installationswege erläutert, zwingend ist nur einer, da eben mindestens ein MQTT-Serverdienst aktiv sein muß.

FHEM als MQTT-Server

Die mit dem Modul MQTT2_SERVER bereitstehende Serverkomponente kann z.B. wie folgt aktiviert werden:

defmod myBroker MQTT2_SERVER 1883 global

Dieses Gerät übernimmt dann die Kommunikation mit den externen Clients (und wird von diesen behandelt, wie jeder andere MQTT-Server auch) und verteilt die eingehenden Nachrichten als IO-Device[4] für die Client-Module MQTT2_DEVICE[5] und MQTT_GENERIC_BRIDGE. Ein weiterer Vorteil dieser Lösung besteht darin, dass man ein MQTT2_SERVER-Device mit Hilfe von allowed absichern kann, was auch SSL-verschlüsselte Kommunikation ermöglicht.


Info blue.png
Wenn Sie beabsichtigen, diese Variante zu verwenden, sollten Sie als nächstes die Praxisbeispiele zu den MQTT2-Modulen lesen, und ggf. später wieder hierher zurückkehren.


FHEM-externer Broker

Beispiel: mosquitto

Eine gern verwendete MQTT-Server-Software ist Mosquitto. Sie kann ohne weiteres auf dem Raspberry Pi, der bereits eine FHEM-Installation besitzt, installiert werden und wird keine größere CPU- oder Netzwerklast verursachen.

Eine Anleitung zur Installation findet sich beispielsweise in diesem Blogeintrag. Im wesentlichen beschränkt sich die Installation eines MQTT Servers aber auf wenige Arbeitsschritte. Bei stretch ist Mosquitto bereits in der Distribution enthalten und kann - zusammen mit dem client Befehl mosquito_sub, der weiter unten benötigt wird, wie folgt installiert und getestet werden[6]:

Info green.png Für ältere Distributionen (hier am Beispiel von jessie) muß ggf. aus einer zusätzlichen Paketquelle installiert werden:
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update

Danach kann die eigentliche Installation durchgeführt werden wie links für stretch beschrieben.

  sudo apt-get install mosquitto mosquitto-clients
 
 # MQTT Server Test
 sudo service mosquitto status

 # Start / Stop des Servers
 sudo service mosquitto stop
 sudo service mosquitto start
 
 # Perl Version ausgeben
 perl -v
 # Perl MQTT Module nachinstallieren (läuft ein paar Minuten)
 sudo cpan install Net::MQTT:Simple
 sudo cpan install Net::MQTT:Constants

Danach ist der RPi mit shutdown restart neu zu starten.

IO-Module für externe MQTT-Server

Damit FHEM mit dem MQTT-Server kommuniziert, muss noch ein IO-Device angelegt werden. Dabei stehen zwei Varianten zur Wahl, das Modul MQTT oder seit Ende 2018 MQTT2_CLIENT.

Beide Module können auch dazu genutzt werden, um Daten zwischen zwei FHEM-Installationen auszutauschen, wenn auf einer der beiden Installationen MQTT2_SERVER installiert ist. Darüber hinaus bestehen eine Vielzahl von Kombinationsmöglichkeiten der diversen IO-Module, wenn die Installation auf mehrere Server verteilt ist. Auf einer FHEM-Installation wird jedoch in der Regel nur eines der IO-Module benötigt.

MQTT2_CLIENT

Ein MQTT2_CLIENT-IO-Device wird z.B. angelegt mit

define myBroker MQTT2_CLIENT 10.0.0.5:1883 ## bitte EIGENE IP-Adresse eintragen


Info blue.png
Wenn Sie beabsichtigen, MQTT2_CLIENT zu verwenden, sollten Sie zuerst die Praxisbeispiele zu den MQTT2-Modulen lesen, und dabei die Hinweise im Artikel MQTT2_CLEINT beachten.


Ein MQTT2_CLIENT-Device kann ebenfals mit Hilfe von allowed abgesichert werden, um z.B. SSL-verschlüsselte Kommunikation zu ermöglichem. Client-Module zu diesem IO-Typ sind wiederum MQTT2_DEVICE und MQTT_GENERIC_BRIDGE.

MQTT (Modul)

Ein IO-Device des Typs MQTT wird z.B. angelegt mit

Info green.png Sofern der Broker mit FHEM über localhost kommuniziert, kann als IP 127.0.0.1 verwendet werden.
define myBroker MQTT 10.0.0.5:1883 ## bitte EIGENE IP-Adresse eintragen

Client-Device-Module zum Modul MQTT sind MQTT_DEVICE, MQTT_BRIDGE (veraltet) und MQTT_GENERIC_BRIDGE. Da MQTT_DEVICE payload im JSON-Format (im Unterschied zu MQTT2_DEVICE) nicht selbst verarbeiten kann wird hier zusätzlich das Modul 98_expandJSON.pm benötigt, um den JSON String zu filtern.


Info blue.png
Die nachfolgende Darstellung berücksichtigt die neueren IO-Module MQTT2_SERVER und MQTT2_CLIENT nicht mehr weiter, beachten Sie die diesbezüglichen Links oben.


Performancefragen...

...oder was sollte man als Lösung wählen, wenn man in die MQTT-Welt einsteigt[7]? Grundsätzlich sollte man davon ausgehen, dass innerhalb von FHEM die Verarbeitung derselben Daten näherungsweise denselben Aufwand bedeuten, unabhängig davon, welche der Implementierungen (MQTT2_CLIENT, MQTT oder MQTT2_SERVER) man konkret wählt. Ein externer Broker hat daher vor allem dann Vorteile, wenn die MQTT Daten überwiegend für was anderes (nicht FHEM) verwendet werden, oder MQTT zweckentfremdet wird (wie z.Bsp. für Musikübertragung). Nutzt man das MQTT-Protokoll dagegen vorwiegend innerhalb von FHEM, ist eher der Einsatz von MQTT2_SERVER in Betracht zu ziehen. Dieser soll Anfängern die Anbindung von MQTT Geraeten in FHEM einfacher machen. Wer später merkt, dass er doch einen externen Broker benötigt, kann dann immer noch auf MQTT2_CLIENT in Verbindung mit einem anderen Broker wechseln. Dagegen ist der Weg von MQTT_DEVICE zu MQTT2_DEVICE mit erheblich mehr Aufwand verbunden.


Kommunikation zu sonstigen FHEM-Geräten über MQTT

Möchte man Daten von einem Gerät (im FHEM-Sinn), das nicht vom Typ MQTT2_DEVICE oder MQTT_DEVICE (je nach IO-Modul) ist, per MQTT versenden (z.B. für eine andere Visualisierungslösung als FHEMWEB, oder als FHEM2FHEM-Ersatzlösung), oder diese sonstigen Geräte über MQTT-Anweisungen von außen steuern können, hat man mehrere Möglichkeiten:

MQTT_GENERIC_BRIDGE

Das Modul MQTT_GENERIC_BRIDGE ermöglicht es, sein jeweiliges IO-Modul-Gerät zu nutzen, um diesen Kommunikationsweg für beliebig viele andere FHEM-Geräte bereitzustellen. Dabei erfolgt am MQTT_GENERIC_BRIDGE-Gerät selbst nur eine Basiskonfiguration, im Übrigen durch Attribute an dem jeweiligen Gerät selbst. So kann z.B. ein Aktor des Typs CUL_HM an- oder ausgeschaltet werden oder auch einfach nur seinen aktuellen Schaltzustand per MQTT publizieren.

Dieses Modul kann seit November 2018 mit allen drei IO-Modul-Varianten zusammen eingesetzt werden, also sowohl mit MQTT2_SERVER bzw. MQTT2_CLIENT oder MQTT (00_MQTT.pm).

Dabei sollte man jedoch beachten, dass zur Verwendung mit den MQTT2-IO's unbedingt die autocreate-Funktion des betreffenden IOs ausgeschaltet wird und dies auch bleibt[8]! Weiter wird das Perl-Modul libmodule-pluggable-perl benötigt[9], damit im Hintergrund auch das Modul MQTT geladen werden kann.

Anwendungsfälle und -beispiele für das Modul sind diesem Thread zu entnehmen.

MQTT_BRIDGE

Dieses Modul kann nur zusammen mit einem IO-Gerät des Typs MQTT verwendet werden. Dabei wird pro weiterzuleitendem anderen FHEM-Gerät eine eigene Instanz dieses Moduls verwendet. Auf den Einsatz dieser Option sollte in neuen Installationen zugunsten von MQTT_GENERIC_BRIDGE verzichtet werden.

Per publish-Befehl am IO-Gerät

Alle drei IO-Module kennen direkte publish-Anweisungen, mit deren Hilfe beliebige payloads an beliebige topics gesendet werden können. Dies kann man z.B. in einem notify nutzen, um einzelne Events zu publishen.

RAW-Events am IO-Gerät (MQTT2.*)

Bei beiden MQTT2-IO-Modulen (MQTT2_SERVER und MQTT2_CLIENT) kann per regulärem Ausdruck festgelegt werden, welche Nachrichten ein Event erzeugen sollen, auf das dann wieder z.B. mit einem notify reagiert werden kann, z.B. um beliebige Schaltaktionen auszulösen.


MQTT-Clients (Beispiele)

Arduino-library

Zur Kommunikation mit dem Broker von Seiten eines Arduinos böte sich der PubSubClient an.

PC-Software

Um die Funktionalität des Brokers zu testen kann z.B. ein Analyse-Tool wie MQTT.fx verwendet werden.

Tasmota

Eine derzeit oft genutzte Möglichkeit für MQTT bilden die Sonoff-Geräte und weitere ESP8266-basierte Hardware, die unter vielen Handelsnamen erhältlich sind. Werden diese mit Tasmota (Theo Arends Sonoff MQTT Over The Air - einer offenen Firmware von arendst) geflasht, so kommunizieren sie über MQTT. Um diese Geräte einzubinden, ist wie folgt vorzugehen. Zuerst ist ein Serverdienst (Broker) bereitzustellen, wie oben beschrieben.

Unter Sonoff sind einige Topics voreingestellt. arendst stellt insbesondere drei Topic-Präfixe bereit, die seiner Meinung jedes Topic einleiten sollen (in den Eingabemasken als "%prefix%" notiert). Das sind einmal Kommandos (abgekürzt als cmnd), die dazu dienen, Befehle auszuführen. Daten werden mit tele und stat übertragen. Ein Topic besteht dann zuerst aus diesem Präfix und danach dem eigentlichen Topic. Wer also beispielsweise einem Sonoff_Switch einen Befehl senden will, sollte als Topic cmnd/Sonoff_Switch wählen. Wenn der Switch ein- und ausgeschaltet werden kann, muss der Topic noch das Wort POWER enthalten (in MQTT werden viele Kennworte komplett groß geschrieben). Der Topic lautet damit vollständig "cmnd/Sonoff_Switch/POWER/set"

Link zum Forum: MQTT FHEM Einrichtung (hier als MQTT_DEVICE!):

### FHEM Device mit MQTT verbinden ###
define Sonoff_Switch MQTT_DEVICE
attr Sonoff_Switch IODev myBroker
attr Sonoff_Switch devStateIcon ON:rc_GREEN:OFF OFF:rc_RED:ON
attr Sonoff_Switch icon hue_filled_br30
attr Sonoff_Switch publishSet ON OFF cmnd/TestSwitch/POWER
attr Sonoff_Switch room MQTT
attr Sonoff_Switch subscribeReading_Licht stat/Sonoff_Switch/POWER
attr Sonoff_Switch subscribeReading_Sensor tele/Sonoff_Switch/SENSOR
attr Sonoff_Switch subscribeReading_Status stat/Sonoff_Switch/STATUS
attr Sonoff_Switch webCmd ON:OFF

Der hier dargestellte Beispielcode realisiert die Kommunikation zwischen FHEM und dem sonoff Modul via MQTT Broker. Zu beachten ist hier, dass subscribeReading_Licht und subscribeReading_Status unterschiedliche Syntax des Topic Strings haben!

Sicherheit

Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der, im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.

meinHaus/Flur/Haustuer:open / close

ist da nicht wirklich schlau!

Abhilfe:

Username / Passwort

Zunächst kann man erst mal einen Username / Passwort vergeben, was alle IO-Device-Module unterstützen. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.

TLS

Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar. (Hier fehlt eine Anleitung für allowed usw.)

Probleme

- asynchrone Kommunikation: Rückgemeldetes Ergebnis kann von der gesendeten Anweisung abweichen - unbeabsichtigte Loops durch Fehler in der topic-Struktur

Links

Hinweise

  1. Teilnehmer in diesem Sinne kann ein Stück Hardware mit einer MQTT-fähigen firmware sein, ein auf einem Computer laufendes Script (einschließlich eines MQTT-Server-Dienstes wie mosquitto oder MQTT2_SERVER, kurz: alles mögliche sein. Dadurch kann auch ein einzelner Computer unter mehreren ClientID's am MQTT-Datenaustausch beteiligt sein.
  2. Aufgrund dieser Funktionsweise sollte allerdings darauf geachtet werden, die Möglichkeiten des jeweiligen Servers zur Sicehrung der Daten gegen unberechtigten Zugriff zu nutzen, insbesondere wenn die Art der Daten oder die sich hierdurch ergebenden Möglichkeiten, z.B. Schaltvorgänge in der realen Welt auszulösen, dies notwendig macht!
  3. Diese kann sich bei der Weitergabe der Nachricht ändern: Zunächst sendet ein Client eine Nachricht unter seiner ClientID, der MQTT-Server wird diese dann in der Regel durch seine Kennung ersetzten, wenn er die Nachricht an einen Abonnenten - der auch ein weiterer MQTT-Server sein kann - weitergibt.
  4. im Sinne des 2-stufigen Modulkonzepts
  5. Die Zahl 2 in den Modulnamen verweist nur darauf, dass es sich um eine neuere Modulfamilie handelt; die Kommunikation mit den externen Komponenten unterscheidet sich nicht zu den älteren Modulen, die vor dem Jahr 2018 genutzt werden konnten.
  6. Die für den Betrieb mit FHEM erforderlichen Perl-Module sind teilweise (noch) nicht in den Paketquellen verfügbar. Sie können dennoch statt mit cpan auch als Debian-Paket mit Hilfe von dh-make-perl installiert werden, wobei vorab das in den Paketquellen bereits vorhandene libmodule-pluggable-perl installiert werden sollte:
    sudo apt-get install dh-make-perl
    dh-make-perl --install --cpan Net::MQTT::simple
    dh-make-perl --install --cpan Net::MQTT::Constants
    sudo dpkg -i libnet-mqtt-simple-perl*.deb
    sudo dpkg -i libnet-mqtt-perl*.deb
  7. vgl. hierzu diesen Beitrag von Rudolf König
  8. siehe dazu diesen Thread zu den technischen Hintergründen
  9. Dieses kann über apt-get install libmodule-pluggable-perl installiert werden