MQTT GENERIC BRIDGE
MQTT_GENERIC_BRIDGE | |
---|---|
Zweck / Funktion | |
Stellt für beliebige Geräte eine Schnittstellt zum MQTT-Protokoll zur Verfügung | |
Allgemein | |
Typ | Gerätemodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | MQTT |
Modulname | 10_MQTT_GENERIC_BRIDGE.pm |
Ersteller | hexenmeister (Forum ) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
An dieser Seite wird momentan noch gearbeitet. |
Einführung
Das Modul MQTT_GENERIC_BRIDGE stellt eine zentrale Schnittstelle zum MQTT-Protokoll für beliebig viele andere FHEM-Geräte bereit. Es wird für eine FHEM-Installation jeweils nur ein erreichbarer MQTT-Server sowie eine Instanz der MQTT_GENERIC_BRIDGE benötigt.
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), und seit Rev. 23514 (Jan. 2021) wird für MQTT_GENERIC_BRIDGE iVm. den MQTT2-IO-Modulen keine zusätzliche Software mehr benötigt.
Dabei erfolgt an dem zentralen MQTT_GENERIC_BRIDGE-Gerät selbst nur eine Basiskonfiguration, die Standardwerte für alle anzubindenden Geräte bereitstellt, alle übrigen Einstellungen erfolgen durch Attribute an dem jeweiligs anzubindenden Gerät selbst.
Beispiel: ein Aktor des Typs CUL_HM kann über MQTT-Kommandos an den für ihn passenden Topic an- oder ausgeschaltet werden oder auch einfach nur seinen aktuellen Schaltzustand per MQTT-Protokoll publizieren.
Installation
Vorbereitung
Im folgenden wird als MQTT-Server mosquitto verwendet, der in aktuellen Linux-Distributionen über die Paketverwaltung angeboten wird. Hier die Installation für Raspberry Pi OS:
sudo apt-get update sudo apt-get upgrade sudo apt-get install mosquitto
Es kann aber auch ein bereits vorhandener MQTT2_SERVER verwendet werden.
Grundsätzliche Konfiguration
Definition der Schnittstelle zum MQTT-Server (hier: auf demselben Raspberry):
defmod mqtt_io MQTT2_CLIENT 127.0.0.1:1883 attr mqtt_io alias MQTT Broker attr mqtt_io devStateIcon .*active:none:disconnect .*disconnected:none:connect attr mqtt_io group MQTT attr mqtt_io icon mqtt attr mqtt_io room IO_Devices
Wer möchte, kann den Status des FHEM-Servers per MQTT LWT mitteilen:
Für MQTT2_CLIENT:
attr mqtt_io lwt system/<fhem-name>/connection/status connection lost attr mqtt_io lwtRetain 1 attr mqtt_io msgAfterConnect -r system/<fhem-name>/connection/status connected attr mqtt_io msgBeforeDisconnect -r system/<fhem-name>/connection/status disconnected
Alternativ: für MQTT
attr mqtt last-will retain:1 system/<fhem-name>/connection/status connection lost attr mqtt on-connect retain:1 {Log3("mqtt",3,"connected to MQTT server");;1} system/<fhem-name>/connection/status connected attr mqtt on-disconnect retain:1 {Log3("mqtt",3,"disconnected from MQTT server");;1} system/<fhem-name>/connection/status disconnected
Definition der Generic Bridge
Der Name mqttGenericBridge kann dabei frei gewählt werden:
defmod mqttGenericBridge MQTT_GENERIC_BRIDGE attr mqttGenericBridge IODev mqtt_io attr mqttGenericBridge alias MQTT generic bridge attr mqttGenericBridge group MQTT attr mqttGenericBridge room IO_Devices attr mqttGenericBridge stateFormat dev: device-count in: incoming-count out: outgoing-count
Damit sind die wesentlichen Vorarbeiten abgeschlossen, und die MQTT_GENERIC_BRIDGE kann bereits dafür genutzt werden, beliebige Reading- oder Attribut-Änderungen von FHEM-Devices über MQTT zu publishen oder entsprechende Anweisungen umzusetzen. Es wird jedoch empfohlen, zunächst noch einige grundlegende Einstellungen vorzunehmen. Hierfür - sowie dann auch für die Konfiguration der weiteren Devices, die an MQTT angebunden werden sollen, steht als Hilfsmittel attrTemplate zur Verfügung.
Hinweis: Eventuell muss erst noch (einmalig) der zugehörige attrTemplate-Satz gelesen werden. Dies erfolgt mittels
{AttrTemplate_Initialize()}
Basisangaben in der MQTT_GENERIC_BRIDGE selbst
Zunächst konfigurieren wir daher die Basisangaben zur Struktur der zu verwendenden MQTT-Topics sowie - bei Verwendung eines MQTT2-Interface-Moduls - die clientOrder:
set mqttGenericBridge attrTemplate base_settings_to_MQTT_GENERIC_BRIDGE
Dies kann direkt über die Detailansicht des Geräts mqttGenericBridge erfolgen, siehe der nebenstehende screenshot, aus dem auch zu entnehmen ist, was das attrTemplate an Änderungen der Konfiguration vornehmen wird. Dies sind zwei Aspekte: Zum einen wird eine Variable namens $base in Sende- und in Empfangsrichtung festgelegt. In Senderichtung (pub:) besteht diese nur aus dem Namen der MQTT_GENERIC_BRIDGE, in Empfangsrichtung (sub:) aus dem Namen sowie dem Topic-Anteil set. Diese Angaben können im Prinzip beliebig geändert werden, es muss lediglich darauf geachtet werden, dass die Angaben unterschiedlich sind, sonst kann es zu unbeabsichtigten Schleifen kommen! Zum anderen wird - sofern ein MQTT2_CLIENT und MQTT2_SERVER als Interface verwendet wird - je nach Wahl des Nutzers in dem dann erscheinenden Dialogfeld - die clientOrder festgelegt. Sofern Sie hier unschlüssig sind, wählen Sie die empfohlene Variante, um Probleme im Zusammenspiel mit der autocreate-Funktion dieser Interface-Typen möglichst zu vermeiden.
Weitere Konfigurationsschritte
(Noch nachzubearbeiten, aus dem Thread Anwendungsfälle und Beispiele für MQTT_GENERIC_BRIDGE - https://forum.fhem.de/index.php/topic,91642.msg841367.html#msg841367)
eine Reading an einem beliebigen Device per MQTT setzen (für State-Reading soll state verwendet werden) Code: [Auswählen]
attr <device-name> mqttSubscribe <reading-name>:topic=<topic>
(anstatt 'topic' kann für eine bessere Lesbarkeit 'readings-topic' verwendet werden)
ein Set-Befehl an einem beliebigen Device mit dem per MQTT gesendeten Wert ausführen (für set ohne namen (set on, set off) soll state verwendet werden) Code: [Auswählen]
attr <device-name> mqttSubscribe <set-befehl>:stopic=<topic>
(anstatt 'stopic' kann für eine bessere Lesbarkeit 'set-topic' verwendet werden)
ein Attribut an einem beliebigen Device per MQTT setzen Code: [Auswählen]
attr <device-name> mqttSubscribe <attribut-name>:atopic=<topic>
(anstatt 'atopic' kann für eine bessere Lesbarkeit 'attr-topic' verwendet werden)
eine Änderung eines Readings per MQTT senen Code: [Auswählen]
attr <device-name> mqttPublish <readings-name>:topic=<topic>
eine Änderung eines Attributes per MQTT senen
Code: [Auswählen]
attr <device-name> mqttPublish <attribut-name>:atopic=<topic>
Verwendung von Variablen
Es können mit dem Attribute mqttDefaults Variablen definiert werden, die in mqttPublish und mqttSubscribe verwendet werden können:
Code: [Auswählen]
attr <device-name> mqttDefaults base={"allgemeinerPfad/"} ... attr <device-name> mqttPublish <reading-name>:topic={"$base/irgendEinName"}
Weiterhin können in Topics folgende vordefinierte Variablen verwendet werden: $reading - aktuell zu verarbeitende Reading $device - aktulles Gerät $name - Die Variable $name wird im Unterschied zu $reading ggf. ueber die in 'mqttAlias' definierten Aliases beeinflusst. (s. Commandref für mqttAlias) Code: [Auswählen]
attr <device-name> mqttPublish <reading-name>:topic={"$base/$device/$name"}
Mehrere Readings auf einmal
Es können für einen Topic (sinnigerweise mit Variablen) auch mehrere Readings gleichzeitig angegeben werden. Diese müssen in diesem Fall durch ein | getrennt werden:
Code: [Auswählen]
attr <device-name> mqttPublish <reading-name1>|<reading-name2>:topic={"$base/$device/$name"}
Wildcards
mit einem * kann ein Topic für alle Readings zusammen definiert werden:
Code: [Auswählen]
attr <device-name> mqttPublish *:topic={"$base/$device/$name"}
Beim Subscribe können in der Topic-Definition auch MQTT-Wildcards (+ und #) verwendet werden.
Falls der Reading-Name mit einem '*'-Zeichen am Anfang definiert wird, gilt dieser als 'Platzhalter'. Der tatsaechliche Name der Reading (und ggf. des Geraetes) wird dabei durch Variablen aus dem Topic definiert ($reading, $name). Im Topic wirken diese Variablen als Wildcards, macht natuerlich nur Sinn, wenn Reading-Name auch nicht fest definiert ist (also faengt mit '*' an).
Sensoren-Werte von einer FHEM-Instanz in eine andere übertragen
Definition für ein HomeMatic-Device (Dirk's-Sensor + Verwendung von DevPoint-Modul): (es werden gezielt bestimmte Werte übertragen) Code: [Auswählen]
defmod <sensor-device-name> CUL_HM xxxxxx attr <sensor-device-name> model HB-UW-Sen-THPL-I ... attr <sensor-device-name> mqttDefaults base=haus/wohnzimmer attr <sensor-device-name> mqttPublish humidity|luminosity|dewpoint|absoluteHumidity:topic={"$base/klima/$name"}
Definition eines Empfänger-Dummy:
(es werden alle Werte bei passenden Topics empfangen)
Code: [Auswählen]
defmod <dummy-device-name> dummy attr <dummy-device-name> readingList absoluteHumidity dewpoint humidity luminosity temperature vapourPressure attr <dummy-device-name> mqttDefaults base=haus/wohnzimmer attr <dummy-device-name> mqttSubscribe *:topic={"$base/klima/$reading"}
« Letzte Änderung: 11 Januar 2019, 21:31:38 von hexenmeister »
Aktoren, die in einer FHEM-Instanz definiert sind, aus einer anderen schalten Switch
Definition eines Schalters (EnOcean FSR14) Code: [Auswählen]
defmod <actor-device-name> EnOcean 0000000B attr <actor-device-name> IODev FGW14 attr <actor-device-name> alias Licht attr <actor-device-name> devStateIcon off:light_light_dim_00@gray on:light_light_dim_100@yellow .*:hourglass attr <actor-device-name> eep A5-38-08 attr <actor-device-name> group Beleuchtung attr <actor-device-name> gwCmd switching attr <actor-device-name> icon light_downlight attr <actor-device-name> manufID 00D attr <actor-device-name> mqttPublish state:topic=haus/wohnzimmer/licht/top/state attr <actor-device-name> mqttSubscribe state:stopic=haus/wohnzimmer/licht/top/set attr <actor-device-name> room Wohnzimmer attr <actor-device-name> subDef 0010000B attr <actor-device-name> subType gateway attr <actor-device-name> webCmd on:off
Aktoren, die in einer FHEM-Instanz definiert sind, aus einer anderen schalten Dimmer
Aktor-Definition: Code: [Auswählen]
defmod <actor-device-name> CUL_HM xxxxxx attr <actor-device-name> model HM-LC-Dim1TPBU-FM ... attr <actor-device-name> mqttPublish pct:topic=haus/wohnzimmer/licht/level state:topic=haus/wohnzimmer/licht/state attr <actor-device-name> mqttSubscribe pct:stopic=haus/wohnzimmer/licht/set
Aktoren, die in einer FHEM-Instanz definiert sind, aus einer anderen schalten Shutters / Blinds
Aktor-Definition: Code: [Auswählen]
defmod <actor-device-name> CUL_HM xxxxxx attr <actor-device-name> model HM-LC-Bl1PBU-FM ... attr <actor-device-name> mqttPublish pct:topic=haus/wohnzimmer/rollo/all/position state:topic=haus/wohnzimmer/rollo/all/state attr <actor-device-name> mqttSubscribe pct:stopic=haus/wohnzimmer/rollo/all/set
FAQ
Das ist so nicht vorgesehen, ein reading = ein Topic.
a) beim device-count werden nur Geräte gezählt, die mit eigenen mqtt*-Attributen versehen sind. Bei einer globalen Definition 'globalPublish' kann die Bridge nicht (ohne weiteres) wissen, welche Geräte angesprochen werden sollen. Daher wird auch nichts gezählt.
b) mqttSubscribe ist gedacht für diejenigen Geräte, die per MQTT 'versorgt' werden sollen. Die Bridge selbst gehört nicht dazu. Aus technischen Gründen kann es sein, dass diese Attribute trotzdem vom FHEM angeboten werden, gesetzt werden können sie jedoch nicht, die Bridge 'währt' sich dagegen. Ein 'globalSubscribe' gibt es nicht. Ich habe mich entschieden, diese Festure nicht anzubieten. Bei unbedachten Verwendung könnte ein großes Sicherheitsrisiko entstehen. Einfach diese Attribute an den gewünschgten Devices erstellen.
Die Definition lautet 'fhem room=MQTT_BRIDGE_DEVICES'. Der erste Parameter (wie im Commandref steht) ist der Prefix für die Optionsattribute. Ist für Sonderfälle gedacht, wenn mehr als eine Bridge im System vorhanen ist. Deine Parameter heißen also 'fhemSubscribe' etc.
Bin nun draufgekommen das dieses fehlerhafte Verhalten (Bridge geht nicht nach restart so lange bis man im User Interface DEF und "modify" geklickt hat) nur dann auftritt wenn device-count = 0 ist. Nun hab ich ein Device mit einem "fhemSubscribe" Attribut ausgestattet ... und nun lebt die Bridge auch nach einem Restart.
Du kannst aber mit * alle Readings greifen und dann mit Perlmitteln in der expression filtern.
irgendwie so (ungetestet): Code: [Auswählen]
desired-temp!info:expression={if($reading=~/SMAEM12345678.*/){$value}else{undef})}