Modul-Vorstellung: MQTT_GENERIC_BRIDGE

Begonnen von hexenmeister, 31 August 2018, 20:53:56

Vorheriges Thema - Nächstes Thema

hexenmeister

Guten Abend allerseits,

schon vor langer Zeit aus einer Idee geboren, entwickelt, gemeinsam diskutiert und getestet (https://forum.fhem.de/index.php/topic,81418.0.html) und jetzt endlich als ausreichend stabil zu bezeichnen.
Hier ist ein Modul, das die Integration von MQTT-Geräteschaften in FHEM vereinfacht (heute in das offizielle Verzeichnis übernommen, ab morgen per Update verfügbar).
Der Grundgedanke dabei ist auf die zusätzlichen MQTT-DEVICE/BRIDGE Module möglichst zu verzichten und die beliebigen FHEM-Geräte direkt um die MQTT-Fähigkeiten zu erweitern. Die GenericBridge muss nur einmal definiert werden, dabei bekommen andere Geräte ein paar zusätzlichen Attribute, mit deren Hilfe alle Readings des jeweiligen Gerätes per MQTT versendet bzw. vom MQTT-Server gespeist werden können.


Hier ist die Beschreibung aus dem Commandref incl. ein Paar Beispiele:


MQTT_GENERIC_BRIDGE

Dieses Modul ist eine MQTT-Bridge, die gleichzeitig mehrere FHEM-Devices erfasst und deren Readings per MQTT weiter gibt bzw. aus den eintreffenden MQTT-Nachrichten befuellt oder diese als 'set'-Befehl an dem konfigurierten FHEM-Geraet ausfuert.
Es wird ein MQTT-Geraet als IODev benoetigt.

Die (minimale) Konfiguration der Bridge selbst ist grundsaetzlich sehr einfach.

Definition:

Im einfachsten Fall reichen schon zwei Zeilen:

defmod mqttGeneric MQTT_GENERIC_BRIDGE [prefix] [devspec]
attr mqttGeneric IODev


Alle Parameter im Define sind optional.

Der erste ist ein Prefix fuer die Steuerattribute, worueber die zu ueberwachende Geraete (s.u.) konfiguriert werden. Defaultwert ist 'mqtt'. Wird dieser z.B. als 'hugo' redefiniert, heissen die Steuerungsattribute entsprechend hugoPublish etc.

Der zweite Parameter ('devspec') erlaubt die Menge der zu ueberwachenden Geraeten zu begrenzen (sonst werden einfach alle ueberwacht, was jedoch Performance kosten kann). s.a. devspec

get:
- version
Zeigt Modulversion an.

- devlist [<name (regex)>]
Liefert Liste der Namen der von dieser Bridge ueberwachten Geraete deren Namen zu dem optionalen regulaerem Ausdruck entsprechen. Fehlt der Ausdruck, werden alle Geraete aufgelistet.

- devinfo [<name (regex)>]
Gibt eine Liste der ueberwachten Geraete aus, deren Namen zu dem optionalen regulaerem Ausdruck entsprechen. Fehlt der Ausdruck, werden alle Geraete aufgelistet. Zusätzlich werden bei 'publish' und 'subscribe' verwendete Topics angezeigt incl. der entsprechenden Readinsnamen.

readings:

- device-count
Anzahl der ueberwachten Geraete

- incoming-count
Anzahl eingehenden Nachrichten

- outgoing-count
Anzahl ausgehende Nachrichten

- updated-reading-count
Anzahl der gesetzten Readings

- updated-set-count
Anzahl der abgesetzten 'set' Befehle

- transmission-state
letze Uebertragunsart

Attribute:

folgende Attribute werden unterstuetzt:

- IODev
Dieses Attribut ist obligatorisch und muss den Namen einer funktionierenden MQTT-Modulinstanz enthalten. Modul MQTT2_SERVER wird nicht unterstuetzt.

- disable
Wert 1 deaktiviert die Bridge

Beispiel:
attr <dev> disable 1

- globalDefaults
Definiert Defaults. Diese greifen in dem Fall, wenn in dem jeweiligen Geraet definierte Werte nicht zutreffen. s.a. mqttDefaults.

- globalAlias
Definiert Alias. Diese greifen in dem Fall, wenn in dem jeweiligen Geraet definierte Werte nicht zutreffen. s.a. mqttAlias.

- globalPublish
Definiert Topics/Flags fuer die Uebertragung per MQTT. Diese werden angewendet, falls in dem jeweiligen Geraet definierte Werte nicht greifen oder nicht vorhanden sind. s.a. mqttPublish.

Fuer die ueberwachten Geraete wird eine Liste der moeglichen Attribute automatisch um mehrere weitere Eintraege ergaenzt. Sie fangen alle mit vorher in der Bridge definiertem Prefix an. Ueber diese Attribute wird die eigentliche MQTT-Anbindung konfiguriert.
Defaultmaessig werden folgende Attributnamen verwendet: mqttDefaults, mqttAlias, mqttPublish, mqttSubscribe.
Die Bedeutung dieser Attribute wird im Folgenden erklaert.

- mqttDefaults
Hier wird eine Liste der "key=value"-Paare erwartet. Folgende Keys sind dabei moeglich:
  -- 'qos'
  definiert ein Defaultwert fuer MQTT-Paramter 'Quality of Service'.
  -- 'retain'
  erlaubt MQTT-Nachrichten als 'retained messages' zu markieren.
  -- 'base'
  wird als Variable ($base) bei der Konfiguration von konkreten Topics zur Verfuegung gestellt. Sie kann entweder Text oder eine Perl-Expression enthalten. Perl-Expression muss in geschweifte Klammern eingeschlossen werden. In einer Expression koennen folgende Variablen verwendet werden: $reading = Original-Readingname, $device = Devicename und $name = Readingalias (s. mqttAlias. Ist kein Alias definiert, ist $name=$reading).

Alle diese Werte koennen durch vorangestelle Prefixe ('pub:' oder 'sub') in ihrer Gueltigkeit auf nur Senden bzw. nur Empfangen begrenzt werden (soweit sinnvoll). Werte fuer 'qos' und 'retain' werden nur verwendet, wenn keine explizite Angaben darueber fuer ein konkretes Topic gemacht worden sind.

  Beispiel:
attr <dev> mqttDefaults base={"/TEST/$device"} pub:qos=0 sub:qos=2 retain=0

  - mqttAlias
  Dieses Attribut ermoeglicht Readings unter einem anderen Namen auf MQTT-Topic zu mappen. Eigentlich nur sinnvoll, wenn Topicdefinitionen Perl-Expressions mit entsprechenden Variablen sind. Auch hier werden 'pub:' und 'sub:' Prefixe unterstuetzt (fuer 'subscribe' gilt das Mapping quasi umgekehrt).
  Alias fuer subscribe ist derzeit nicht implementiert!

  Beispiel:
attr <dev> mqttAlias pub:temperature=temp

  - mqttPublish
  Hier werden konkrette Topics definiet und den Readings zugeordnet (Format: <reading>:topic=<topic>). Weiterhin koennen diese einzeln mit 'qos'- und 'retain'-Flags versehen werden.
  Topics koennen auch als Perl-Expression mit Variablen definiert werden ($reading, $device, $name, $base).
  Werte fuer mehrere Readings koennen auch gemeinsam gleichzeitig definiert werden, indem sie, mittels '|' getrennt, zusammen angegeben werden.
  Wird anstatt eines Readingsnamen ein '*' verwendet, gilt diese Definition fuer alle Readings, fuer die keine explizite Angaben gemacht wurden.
  Es koennen auch Expressions (reading:expression=...) definiert werden.
  Die Expressions koenne sinnvollerweise entweder Variablen ($value, $topic, $qos, $retain, $message) veraendern, oder einen Wert != undef zurrueckgeben.
  Der Rueckhgabe wert wird als neue Nachricht-Value verwendet, die Aenderung der Variablen hat dabei jedoch Vorrang.
  Ist der Rueckgabewert undef, dann wird das Setzen/Ausfuehren unterbunden.
  Ist die Rueckgabe ein Hash (nur 'topic' und 'stopic'), werden seine Schluesselwerte als Topic verwendet, die Inhalte der Nachrichten sind entsprechend die Werte aus dem Hash.
Option 'resendOnConnect' erlaubt eine Speicherung der Nachrichten, wenn keine Verbindung zu dem MQTT-Server besteht. Die zu sendende Nachrichten in einer Warteschlange gespeichet. Wird die Verbindung aufgebaut, werden die Nachrichten in der ursprungichen Reihenfolge verschickt.
    Moegliche Werte:
    none - alle verwerfen
    last - immer nur die letzte Nachricht speichern
    first - immer nur die erste Nachricht speichern danach folgende verwerfen
    all - alle speichern, allerdings existiert eine Obergrenze von 100, wird es mehr, werden aelteste ueberzaelige Nachrichten verworfen.

  Beispiele:
attr <dev> mqttPublish temperature:topic={"$base/$name"} temperature:qos=1 temperature:retain=0 *:topic={"$base/$name"} humidity:topic=/TEST/Feuchte
attr <dev> mqttPublish temperature|humidity:topic={"$base/$name"} temperature|humidity:qos=1 temperature|humidity:retain=0
attr <dev> mqttPublish *:topic={"$base/$name"} *:qos=2 *:retain=0
attr <dev> mqttPublish *:topic={"$base/$name"} reading:expression={"message: $value"}
attr <dev> mqttPublish *:topic={"$base/$name"} reading:expression={$value="message: $value"}
attr <dev> mqttPublish *:topic={"$base/$name"} reading:expression={"/TEST/Topic1"=>"$message", "/TEST/Topic2"=>"message: $message"}


  - mqttSubscribe
  Dieses Attribut konfiguriert das Empfangen der MQTT-Nachrichten und die entsprechenden Reaktionen darauf.
  Die Konfiguration ist aehnlich der fuer das 'mqttPublish'-Attribut. Es koennen Topics fuer das Setzen von Readings ('topic') und Aufrufe von 'set'-Befehl an dem Geraet ('stopic') definiert werden.
  Mit Hilfe von zusaetzlichen auszufuehrenden Perl-Expressions ('expression') kann das Ergebnis vor dem Setzen/Ausfueren noch beeinflusst werden.
  In der Expression sind folgende Variablen verfügbar: $device, $reading, $message (initial gleich $value). Die Expression kann dabei entweder Variable $value veraendern, oder einen Wert != undef zurueckgeben. Redefinition der Variable hat Vorrang. Ist der Rueckgabewert undef, dann wird das Setzen/Ausfuehren unterbunden (es sei denn, $value hat einen neuen Wert).
  Ist die Rueckgabe ein Hash (nur fuer 'topic' und 'stopic'), dann werden seine Schluesselwerte als Readingsnamen bzw. 'set'-Parameter verwendet, die zu setzenden Werte sind entsprechend die Werte aus dem Hash.
  Weiterhin kann das Attribut 'qos' angegeben werden ('retain' macht dagegen keinen Sinn).
  In der Topic-Definition koennen 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 ($device (nur fuer globale Definition in der Bridge), $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).
  Die Variable $name wird im Unterschied zu $reading ggf. ueber die in 'mqttAlias' definierten Aliases beeinflusst. Auch Verwendung von $base ist erlaubt.
  Bei Verwendung von 'stopic' wird das 'set'-Befehl als 'set <dev> <reading> <value>' ausgefuert. Fuer ein 'set <dev> <value>' soll als Reading-Name 'state' verwendet werden.

  Beispiele:
attr <dev> mqttSubscribe temperature:topic=/TEST/temperature test:qos=0 *:topic={"/TEST/$reading/value"}
attr <dev> mqttSubscribe desired-temperature:stopic={"/TEST/temperature/set"}
attr <dev> mqttSubscribe state:stopic={"/TEST/light/set"} state:expression={...}
attr <dev> mqttSubscribe state:stopic={"/TEST/light/set"} state:expression={$value="x"}
attr <dev> mqttSubscribe state:stopic={"/TEST/light/set"} state:expression={"R1"=>$value, "R2"=>"Val: $value", "R3"=>"x"}


  - mqttDisable
        Wird dieses Attribut in einem Geraet gesetzt, wird dieses Geraet vom Versand bzw. Empfang der Readingswerten ausgeschlossen.

Beispiele:

        Bridge fuer alle moeglichen Geraete mit dem Standardprefix:
defmod mqttGeneric MQTT_GENERIC_BRIDGE
attr mqttGeneric IODev mqtt


        Bridge mit dem Prefix 'mqtt' fuer drei bestimmte Geraete:
defmod mqttGeneric MQTT_GENERIC_BRIDGE mqtt sensor1,sensor2,sensor3
attr mqttGeneric IODev mqtt


        Bridge fuer alle Geraete in einem bestimmten Raum:
defmod mqttGeneric MQTT_GENERIC_BRIDGE mqtt room=Wohnzimmer
attr mqttGeneric IODev mqtt


        Einfachste Konfiguration eines Temperatursensors:
defmod sensor XXX
attr sensor mqttPublish temperature:topic=/haus/sensor/temperature


        Alle Readings eines Sensors (mit ihren Namen wie sie sind) per MQTT versenden:
defmod sensor XXX
attr sensor mqttPublish *:topic={"/sensor/$reading"}


        Topicsdefinition mit Auslagerung von dem gemeinsamen Teilnamen in 'base'-Variable:
defmod sensor XXX
attr sensor mqttDefaults base={"/$device/$reading"}
attr sensor mqttPublish *:topic={$base}


        Topicsdefinition nur fuer bestimmte Readings mit deren gleichzeitigen Umbennenung (Alias):
defmod sensor XXX
attr sensor mqttAlias temperature=temp humidity=hum
attr sensor mqttDefaults base={"/$device/$name"}
attr sensor mqttPublish temperature:topic={$base} humidity:topic={$base}


        Beispiel fuer eine zentralle Konfiguration in der Bridge fuer alle Devices, die Reading 'temperature' besitzen:
defmod mqttGeneric MQTT_GENERIC_BRIDGE
attr mqttGeneric IODev mqtt
attr mqttGeneric defaults sub:qos=2 pub:qos=0 retain=0
attr mqttGeneric publish temperature:topic={"/haus/$device/$reading"}


        Beispiel fuer eine zentralle Konfiguration in der Bridge fuer alle Devices
        (wegen einer schlechten Übersicht und einer unnoetig grossen Menge eher nicht zu empfehlen):
defmod mqttGeneric MQTT_GENERIC_BRIDGE
attr mqttGeneric IODev mqtt
attr mqttGeneric defaults sub:qos=2 pub:qos=0 retain=0
attr mqttGeneric publish *:topic={"/haus/$device/$reading"}


        Beispiel für Zerlegung einer JSON-Kodierten Nachricht in EInzelreadings.
        Sendet man jetzt z.B. folgende JSON: {"jtest1":"jval1","jtest2":"jval2"} dann werden zwei Readings (jtest1 und jtest2) entsprechend angelegt/aktualisiert.
xyz:topic=/TEST/json xyz:expression={json2nameValue($message)}

Einschraenkungen:
- Wenn mehrere Readings das selbe Topic abonieren, sind dabei keine unterschiedlichen QOS moeglich.
- Wird in so einem Fall QOS ungleich 0 benoetigt, sollte dieser entweder fuer alle Readings gleich einzeln definiert werden, oder allgemeinguetltig ueber Defaults. Ansonsten wird beim Erstellen von Abonements der erst gefundene Wert verwendet.
- Abonements werden nur erneuert, wenn sich das Topic aendert, QOS-Flag-Aenderung alleine wirkt sich daher erst nach einem Neustart aus.
- Nicht kompatibel mit neuen Modulen MQTT2_SERVER / MQTT2_DEVICE (Schleife über MQTT2_SERVER->MQTT->MQTT_GENERIC_BRIDGE ist vermutlich möglich, jedoch nicht sinnvoll, da ineffizient)
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

SamNitro

(Intel-Nuc Proxmox) (Homematic) (EnOcean) (CUL868) (CUL433) (Zigbee2MQTT) (ESP8266) (Echo) (DUOFERN)

Billy

Zitat von: hexenmeister am 31 August 2018, 20:53:56
Der Grundgedanke dabei ist auf die zusätzlichen MQTT-DEVICE/BRIDGE Module möglichst zu verzichten und die beliebigen FHEM-Geräte direkt um die MQTT-Fähigkeiten zu erweitern.

Vielen Dank für Deine Mühe.

ZitatLimitations:

If several readings subscribe to the same topic, no different QOS are possible.
If QOS is not equal to 0, it should either be defined individually for all readings, or generally over defaults.
Otherwise, the first found value is used when creating a subscription.
Subscriptions are renewed only when the topic is changed, so changing the QOS flag onnly will only work after a restart of FHEM.

Habe ich richtig verstanden, dass die bisherigen MQTT-DEVICE/BRIDGE Module diese Einschränkung nicht haben?

Gruß Billy
FHEM immer akt. auf 3 BeagleBoneBlack: 2xHMLAN 2xJeelink ;10x HM-CC-TC, 13x HM-CC-VD, 1x HM-ES-PMSw1-Pl, 3x HM-LC-SW1-PL2, viele ESP8266, Tasmota Scripting, Mqtt*

hexenmeister

Eher doch. Bei dem Nr. 1.  bin ich mir nicht sicher, dass es dort funktioniert, die 2. ist keine wirkliche Einshränkung, muss man ggf. nur beachten, ist jedoch spezifisch für GenericBridge. Die 3. gilt für alte Module meines Wissens genauso.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Billy

Hatte ich schon fast vermutet, dass die Einschränkung auch für die alten Module gilt.
Die Frage ist nun: Braucht man die alten Module noch, oder ist mit deiner Weiterentwicklung alles erschlagen?
Billy
FHEM immer akt. auf 3 BeagleBoneBlack: 2xHMLAN 2xJeelink ;10x HM-CC-TC, 13x HM-CC-VD, 1x HM-ES-PMSw1-Pl, 3x HM-LC-SW1-PL2, viele ESP8266, Tasmota Scripting, Mqtt*

hexenmeister

Die Frage kann nur jeder für sich beantworten ;D
Das neue Modul macht praktisch dsas gleiche, nur anders (und aus meiner sicht etwas einfacher und bequemer).
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Billy

Zitat von: hexenmeister am 01 September 2018, 12:05:47

Das neue Modul macht praktisch das gleiche, nur anders (und aus meiner sicht etwas einfacher und bequemer).
Das deckt sich mit meinen Erfahrungen mit Deinem Modul.  :)
Ich wollte das von dir als Fachmann bestätigt haben damit es Neueinsteiger einfacher haben.

Hilfreich wäre in der Commandref der Satz: dieses Modul vereinigt die Funktionalität der
Mqtt-Device und Mqtt-Bridge Module.

Billy
FHEM immer akt. auf 3 BeagleBoneBlack: 2xHMLAN 2xJeelink ;10x HM-CC-TC, 13x HM-CC-VD, 1x HM-ES-PMSw1-Pl, 3x HM-LC-SW1-PL2, viele ESP8266, Tasmota Scripting, Mqtt*

hexenmeister

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

gitarero

Hey,
danke für das Modul.
Leider habe ich einen Bug entdeckt.
Das Modul scheint ein Problem mit ":" im Publish-Payload zu haben.

Ich habe ein "at" für einen Wecker. Da wollte ich das Reading "state" publishen. Im Falle von "inactive" klappt das auch. Im Fall von "Next: 08:15" nicht.
Durch das Attribut:
*:topic={"zuHause/System/Wecker/$reading"}
habe ich in MQTT.fx rausgefunden, dass in Falle von "Next: 08:15" das Topic "Next" ist und nicht wie erwartet "state".

Genauso verhält es sich mit einem Dummy, der eine Zeit für die Laufzeit des Weckers beinhaltet.
Wenn ich den Dummy auf "Test" setze, kommt das ganze mit dem (End-)Topic "state" an. Besitzt der Dummy aber den Wert "02:10:00" heisst das Topic "02" und der Payload ist nur noch ":10:00".

Das gleiche Verhalten scheint bei der MQTT-Bridge vorzuliegen.
Kann man da was gegen tun?

Viele Grüße,
Ingo

hexenmeister

Ich konnte den Fehler nachstellen. Versuche in den nächsten Tage die Ursache finden.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

kpl

Hallo Hexenmeister,

mit der Version die Heute im Update verteilt wird werden die readings beim Subscript nicht mehr aktualisiert.
Nach dem einspielen der vorherigen Version Funktioniert es wieder Problemlos.
Anbei eine Beispiel Geräte Definition.

Internals:
   NAME       WS_Buero
   NR         385
   STATE      T: 22.66° H: 50%<br>P: 990.46
   TYPE       dummy
   Helper:
     DBLOG:
       battery:
         NAS1DB:
           TIME       1535975734.04262
           VALUE      2.977
       humidity:
         NAS1DB:
           TIME       1535975720.86372
           VALUE      50
       pressure:
         NAS1DB:
           TIME       1535975734.08432
           VALUE      990.46
       temperature:
         NAS1DB:
           TIME       1535975720.82657
           VALUE      22.66
   READINGS:
     2018-09-03 13:55:34   battery         2.977
     2018-09-03 13:55:34   humidity        50
     2018-09-03 13:55:34   pressure        990.46
     2018-09-03 13:55:33   temperature     22.66
Attributes:
   DbLogExclude state
   event-on-change-reading .*
   genericDeviceType thermometer
   icon       temperature_humidity
   mqttSubscribe *:topic={"Home/Ruuvi/Buero/$reading"}
   room       Büro
   stateFormat T: temperature° H: humidity%<br>P: pressure


Gruß,
Peter

gitarero

Hey,

Zitat von: hexenmeister am 02 September 2018, 23:17:31
Teste mal bitte die angehängte Version

Damit funktioniert's, danke!

Viele Grüße,
Ingo

hexenmeister

Zitat von: kpl am 03 September 2018, 14:08:16
mit der Version die Heute im Update verteilt wird werden die readings beim Subscript nicht mehr aktualisiert.
Gesucht->gefunden-gefixt->eingecheckt ;)
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy