MQTT Einführung Teil 2: Unterschied zwischen den Versionen
Rince (Diskussion | Beiträge) |
Rince (Diskussion | Beiträge) K (→Filter) |
||
Zeile 134: | Zeile 134: | ||
=== Filter === | === Filter === | ||
AB HIER NOCH NICHT FERTIG | |||
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. | Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. | ||
Es gibt zwei Arten von Filtern: | |||
* Single Level Filter: + | |||
* Multi Level Filter: # | |||
Beispiele: | |||
* zuHause/state/1_OG/Kueche/Temperatur | |||
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur | |||
* zuHause/state/1_OG/Kueche/Licht | |||
* zuHause/state/1_OG/Wohnzimmer/Licht | |||
* zuHause/state/1_OG/Schlafzimmer/Licht | |||
Jetzt filtern wir: | |||
"#" => muss immer der letzte Filter sein | |||
* zuHause/state/# gibt uns alle oben genannten Topics zurück | |||
* zuHause/state/1_OG/+/Licht |
Version vom 27. März 2017, 11:30 Uhr
MQTT Teil 2
Konzepte und best practices
Vorwort
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.
Retained Messages
Szenario
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.
- Homematic
- Es wird jedes Gerät angesprochen und abgefragt:
- "Lieber Lichtschalter, was tust du grade?"
- "Ich lasse das Licht über dir leuchten mein User."
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein "retained Flag" gesetzt werden.
Das bedeutet
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:
- zuHause/1OG/Kueche/Licht/state "on" oder "off" + retained flag
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.
Fazit
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.
Last Will and Testament (LWT)
Szenario
Letzter Wille und Testament.
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden… Gründe für einen Sensorausfall gibt es durchaus. Was passiert in FHEM? Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße. Wie fängt man das ab?
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat.
Möglich.
MQTT Lösung
Der Letzte Wille, das Testament (LWT)
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden. Was bedeutet das für uns?
Zusätzlich zu:
- zuHause/1_OG/Kueche/Licht/state
- zuHause/1_OG/Kueche/Licht/set
könnten wir zusätzlich
- zuHause/1_OG/Kueche/Licht/status
definieren.
Beim Anmelden an den Broker schicken wir (mit retained flag) ein "online" Als LWT geben wir das gleiche Topic an, aber mit "offline" und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.
Vorsicht
LWT bezieht sich auf die Client ID. Was das schon wieder? Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat. LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!
- zuHause/1OG/Arduino_1
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)
Noch eine Falle
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!
Böse:
zuHause/MQTT/Status (<= nicht nachmachen)
Fazit
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen! Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)
Organisation der Topics
Basics, erlaubte Zeichen
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.
Außer:
- U+0001..U+001F control characters
- U+007F..U+009F control characters
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=> ü => ue...)
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.
Falsch:
- /zuHause/
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen
- zuHause//1_OG
Hier wird ein leeres Topic definiert. Das ist ungültig.
Basics, Strukturierung
MQTT kennt publishen und subscriben.
FHEM kennt für jedes Gerät einen "state" und ein "set" Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.
Unglücklich:
- zuHause/1_OG/Kueche/Lichtschalter
Wenn da ein "on" steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:
Etwas glücklicher (kann man machen, sollte man aber nicht)
- zuHause/1_OG/Kueche/Lichtschalter/set
- zuHause/1_OG/Kueche/Lichtschalter/state
Richtig schlau (warum, kommt bei den Filtern)
- set/zuHause/1_OG/Kueche/Lichtschalter
- state/zuHause/1_OG/Kueche/Lichtschalter/state
Jetzt wird es einfach:
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.
Aufbau eines Topics
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.
Ungünstig:
- zuHause/state/1_OG/Kueche
=> In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.
Besser:
- zuHause/state/1_OG/Kueche/Licht
- zuHause/state/1_OG/Kueche/Raumtemperatur
- zuHause/state/1_OG/Kueche/Luftfeuchte
- zuHause/state/1_OG/Kueche/Bewegungsmelder
=> Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.
Filter
AB HIER NOCH NICHT FERTIG
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme.
Es gibt zwei Arten von Filtern:
- Single Level Filter: +
- Multi Level Filter: #
Beispiele:
- zuHause/state/1_OG/Kueche/Temperatur
- zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur
- zuHause/state/1_OG/Kueche/Licht
- zuHause/state/1_OG/Wohnzimmer/Licht
- zuHause/state/1_OG/Schlafzimmer/Licht
Jetzt filtern wir:
"#" => muss immer der letzte Filter sein
- zuHause/state/# gibt uns alle oben genannten Topics zurück
- zuHause/state/1_OG/+/Licht