"Der MQTT-Workshop (MQTT2-Module)"

Begonnen von Beta-User, 25 November 2020, 16:15:56

Vorheriges Thema - Nächstes Thema

Beta-User

Hallo zusammen,

vor einiger Zeit hatten wir in einem Mega-Thread mal erörtert, wie man denn am schnellsten in das Thema MQTT-Kommunikation allgemein und MQTT2-Module in FHEM (tiefer) einsteigen kann. Da heute "jemand" angemerkt hat, er habe tatsächlich mal testweise was aus diesem Programm in Betrieb genommen, nehme ich das einfach mal zum Anlass, den betreffenden Beitrag und über der Zeit dann noch ein paar weitere, die m.E. eigentlich ganz gute Zusammenfassungen zu manchen Themen sein sollten hier kurz zu zitieren.

Zum einen, dass man das ganze einfacher wiederfindet, zum anderen, um alles gesammelt beieinander zu haben. Ggf. kann oder mag ja jemand auch eine Art Wiki-Beitrag daraus machen.

Konkrete Verbesserungsvorschläge zum Inhalt oder wording oder Verständnisfragen zum wording dürfen gerne gestellt werden, aber benutzt bitte für individuelle Fragen lieber jeweils eigene Threads, ich bebsichtige, ggf. auch weitere Beiträge einfach nach hierhin zu zitieren, so dass man ggf. einfach einen schnellen Ein- und Überblick über die wesentlichen Fragen hat. Die "Praxisbeispiele im Wiki" sollte man bitte auch immer dazu zur Hand haben...

Los geht es mit dem ursprünglichen Workshop:
Zitat von: Beta-User am 06 März 2020, 14:40:45
[...]
Für den Stammtisch als Anregungen vielleicht:

Einstieg/Grundkurs:
Material:
Je einen "normalen" Shelly(-pm) und Tasmota (notfalls: 2 Tasmota oder Shelly) an einem Demo-FHEM

Ziel:
Einführung in die Basics zu MQTT2_SERVER, autocreate und MQTT2_DEVICE
- Vorher und danach kann man dann mit "set xy attrTemplate ?" anknüpfen: Da kommt nämlich die m.E. längste "Linkliste" an Projekten, die bereits erfolgreich mit FHEM+MQTT umgesetzt wurde... (Wenn ihr Verbesserungsvorschläge zu den desc haben solltet oder weitere Geräte, die da rein sollen: aufschreiben...).
- vorher/danach, um zu Erkennen, wie wegen passender "filter:" dann plötzlich weitere attrTemplate sichtbar werden, wenn man sie vielleicht benötigt;
- dann attrTemplate: Quelltext vom template vorher ansehen, darauf anwenden  und Ergebnis begutachten...
- jsonMap - Funktion (bei Tasmota, einschließlich "Ausknipsen" von unnötigen Zweigen/Teilinfos).

Aufbaukurs I:
Material:
2. FHEM, das mit MQTT2_CLIENT auf den MQTT2_SERVER am anderen FHEM lauscht
Ziel:
Unterschied, besondere Schwierigkeit bei MQTT2_CLIENT-Installationen kennenlernen, Lösungsansatz verstehen.
- "bridge-template" zum Vorsortieren wg. fehlender/irreführender CID ("Einheits-Sammeldevice" für "bekanntes" vermeiden)


Aufbaukurs II:
Material:
Ein (besser: Zwei) ESP32, geflasht als OpenMQTTGateway(s) (wenn 2: mit unterschiedlichen Namen), dazu ein, zwei gtags oä +  (mind.) einen "runden" BT-Xiaomi-Temp/Hum-Sensor (Summe Material: <30 Euro...)
Ziele:
- Funktionsweise/eigentliches Ziel von bridgeRegexp verstehen; (so ähnlich ticken auch weitere "bridge"-templates, insbes. für zigbee2mqtt, ebus, milight: Es gibt ein Zentraldevice, das dem jeweiligen ESP entspricht, der generiert dann ggf. weitere Devices, das OpenMQTTGateway hier dann sogar mehrstufig für die verschiedenen Sende-/Empfangswege...)
- am praktischen Beispiel nachzuvollziehen, wie man Topic-Strukturen mit Perl auswerten kann und daraus dann Reading-Namen etc. baut;
- "Spezialtemplates", die dann komplett neue Geräte generieren (für gtag bzw. den Temp-Sensor, der dann auch nur die passenden Readings bekommt).

Dann wißt ihr im Prinzip nach ca. 2 Stunden in etwa so viel wie ich, fehlt eigentlich nur noch das Nachladen von weiteren templates/myUtils-code (=> ebus, roborock)  :) .

Was im Wiki bzw. als gesammelte "Best-Practice" noch fehlt, wären neben dem publishen via script, das [...] angesprochen hat, noch "asynchrone" FHEM2FHEM-Verbindungen über MQTT2, Doku über SSL-Absicherung von SERVER nach außen zum allg. INet - da fehlt mir auch die Erfahrung, dto. zu eigentlichen MQTT-Vorteilen wie QoS etc..
[...]



FAQ: Gerne, aber das kuratiert dann gerne jemand anderes...

[...]
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#1
MQTT2_CLIENT und MQTT_GENERIC_BRIDGE

(Beides, und v.a. MQTT_GENERIC_BRIDGE ist eigentlich nicht meine Kernkompetenz, aber zumindest kam da bisher kein Widerspruch, dass das kompletter Unsinn wäre):
Zitat von: Beta-User am 29 Oktober 2020, 14:47:59
OK, dann versuchen wir das mal auszusortieren...

Wenn ich das richtig deute, schubst FHEM alle Readings usw. nach MQTT. Das sollte m.E. selektiver erfolgen (also eigentlich nicht via "globalPublish", sondern via mqttDefaults in der MGB und dann Einzelanweisungen an jedem Device) bzw. wenn, dann in jedem Fall auch auf einem dezidierten Unterpfad geschehen.
[...]
Besser wäre sowas wie:
attr mqttGeneric globalDefaults base=fhem/MGB/
(bin aber auch bei den Details zu MGB nicht durch, es gibt hier irgendwo einen Thread mit "Beispielen" zu diesem Modul).

Damit die nicht wieder in FHEM ankommen, beschränken wir die subscription des CLIENT:
attr lb_mosquitto ignoreRegexp fhem/MGB/out
[...]
Kurz zur angedachten Topic-Struktur:
fhem/MGB/out => alle Readings, die von FHEM über die MGB an den Broker übermittelt werden
fhem/MGB/in   => alle Anweisungen, die FHEM über die MGB erhalten und auswerten soll
loxberry/out  => alle Anweisungen, die von MQTT2_DEVICE-Geräten in FHEM empfangen werden sollen
loxberry/in    => alle Anweisungen, die FHEM (über MQTT2_DEVICE-Geräte) an Loxone senden soll;

Die letzten beiden Pfade gelten für die Dinge, die in Loxone "schon immer" exisitert haben und nicht mit FHEM zusammenhängen, die ersten beiden für alles, was in FHEM an _steuerbarer Hardware_ (oder an Messdatenerfassung) vorhanden ist und von Loxone aus erkannt und gesteuert werden soll. Wie du unschwer erkennen kannst, wird derzeit sehr viel mehr an mosquitto übertragen, als du eigentlich brauchst...
Falls du schon irgendwas von Loxone aus in Richtung MQTT angepaßt hattest, solltest du die Pfade dann auch entsprechend anpassen.

Danach kannst du die RAW-Definition von MQTT2_lb_mosquitto erst mal wegsichern und dann dieses Device in FHEM wieder löschen.
Nach einem Neustart des Mosquitto müßte dann wieder ein (deutlich kleineres) MQTT2_DEVICE mit diesem Namen erscheinen.

Den "notify-Pfad" würde ich erst mal hintanstellen, wie gesagt, ich meine, dass man den eigentlich besser nicht verwenden sollte, aber an der Stelle der Nachweis, dass das auch via MQTT2_DEVICE geht - dieses eine Device ersetzt dann die Kombination von MQTT_DEVICE und notify (allerdings ohne Log, aber das könnte man auch noch anflanschen...):
define MQTT2_Notify_replacement MQTT2_DEVICE n_replacement
fhem/SYS_MQTT/cmnd:.*  { fhem($EVENT) }

Das ganze ist aber ein einziges Sicherheitsloch (der Broker muss zumindest von Loxone her ohne TLS oä. auskommen, weil das plugin das nicht kann!), daher sollte man das - genau wie das globale publish von FHEM aus - SEIN LASSEN...

Danach müssen wir uns wieder um das "MQTT2_lb_mosquitto" kümmern:
- zum einen speicherst du die neue (RAW-)Konfiguration erst mal wieder weg und wendest dann das attrTemplate "MQTT2_CLIENT_general_bridge" an.
- Die damit erzeugte bridgeRegexp erweiterst du um eine Zeile:

attr MQTT2_lb_mosquitto bridgeRegexp [...]
[\b]fhem/MGB/in.*:.* ""


Das sollte dazu führen, dass alle über "fhem/MGB/in" eingehenden Messages an die MQTT_GENERIC_BRIDGE auch bei eingeschaltetem autocreate weitergegeben werden.

Jetzt kümmern wir uns noch um den Eingangspfad von den Loxone-Devices und erweitern die bridgeRegexp um eine weitere Zeile - hier mal angenommen, der Name des Geräts in Loxone steht hinter dem "out" als ein Element des Topic-Pfades:

attr MQTT2_lb_mosquitto bridgeRegexp [...]
[\b]loxberry/out/([^/]+).*:.* "lb_$1"


Das sollte bewirken, dass alles, was über diesen Pfad an Infos kommt dann auch an demselben MQTT2_DEVICE in FHEM ankommt. Die Namensgebung ist dann erst mal MQTT2_lb_<nameInLoxone>.

Damit haben wir folgendes Gesamtbild für die einzelnen Topics von oben (von FHEM aus gesehen):
fhem/MGB/out => werden von der ignoreRegexp am IO verworfen
fhem/MGB/in   => werden an die MGB weitergeleitet. Die Weiterverarbeitung in FHEM setzt jetzt voraus, dass am eigentlichen Zieldevice eine Auswertung definiert wird;
loxberry/out  => füllt je Unter-Topic-Pfad ein MQTT2_DEVICE in FHEM.
loxberry/in    => verwenden wir für die setList-Attribute an den betreffenden Devices. (Kommt noch).


Ist damit in etwa nachvollziehbar, wie das am Ende aussehen soll?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

"Gesprächige Geräte bändigen" - Teil 1: Klartext-Payload (ohne JSON)
Antw:Shelly: extrem gesprächig

ZitatMan könnte [...] den Usern den "richtigen Umgang" (falls es sowas überhaupt gibt...) mit den event-on.* und timestamp.*-Attributen zu vermitteln :P . Macht hier ja durchaus Sinn, da die Shelly ja (@MQTT) dankenswerterweise "Klartext" (und nicht JSON) sprechen. Oder dem Hersteller ein etwas differenzierteres Sendeverhalten vorzuschlagen, wenn man einen guten Draht hat und sowas auch sachlich differenziert vermitteln kann.

Wie dem auch sei, hier mal ein vorläufiges Zwischenergebnis@MQTT2 als Diskussionsgrundlage:
defmod Muster_Shelly1pm MQTT2_DEVICE shelly1pm_123456789012
attr Muster_Shelly1pm IODev MQTT2_FHEM_Server
attr Muster_Shelly1pm comment To get appropriate loadState values: Change the default limit "100" in readingList to your needs.
attr Muster_Shelly1pm devStateIcon {my $onl = ReadingsVal($name,"online","false") eq "false"?"10px-kreis-rot" : ReadingsVal($name,"new_fw","false") eq "true" ? "10px-kreis-gelb" : "10px-kreis-gruen";;;; my $light = ReadingsVal($name,"state","off");;;; my $cons = ReadingsVal($name,"relay_0_power","unknown");;;; my $total = ReadingsVal($name,"relay_0_kWh","unknown");;;; my $temp = ReadingsVal($name,"temperature","-100");;;;"<a href=\"http://".ReadingsVal($name,"ip","none")." \"target=\"_blank\">".FW_makeImage($onl)."</a> <a href=\"/fhem?cmd.dummy=set $name toggle&XHR=1\">".FW_makeImage($light)."</a><div>Verbrauch: $cons / Total: $total/ Temp: $temp °C</div>"}
attr Muster_Shelly1pm event-on-change-reading state,temperature:0.2,online,loadState,overtemperature,Verbrauch_Total_kWh,relay_0_.*,relay0,input0
attr Muster_Shelly1pm event-on-update-reading stat[ERT].*
attr Muster_Shelly1pm model shelly1_w_energy_meassuring
attr Muster_Shelly1pm readingList shellies/shelly1pm-123456789012/relay/0:.* state\
  shellies/shelly1pm-123456789012/relay/0:.* relay0\
  shellies/shelly1pm-123456789012/input/0:.* input0\
  shellies/shelly1pm-123456789012/online:.* online\
  shellies/announce:.* { $EVENT =~ m,..id...shelly1pm-123456789012...mac.*, ? json2nameValue($EVENT) : return }\
  shellies/shelly1pm-123456789012/announce:.* { json2nameValue($EVENT) }\
  shellies/shelly1pm-123456789012/relay/0/power:.* relay_0_power\
  shellies/shelly1pm-123456789012/relay/0/power:.* { my $compare = $EVTPART0 < 100 ? "off":"on";; ReadingsVal($NAME,"loadState","off") ne $compare ? { 'loadState' => $compare } : return }\
  shellies/shelly1pm-123456789012/temperature:.* temperature\
  shellies/shelly1pm-123456789012/overtemperature:.* overtemperature\
  shellies/shelly1pm-123456789012/relay/0/energy:.* relay_0_energy\
  shellies/shelly1pm-123456789012/relay/0/energy:.* {'relay_0_kWh' => sprintf("%.2f",$EVENT/60/1000)}\
  shellies/shelly1pm-123456789012/longpush/0:.* longpush_0\
  shellies/shelly1pm-123456789012/temperature_f:.* {}\
  shellies/shelly1pm-123456789012/input_event/0:.* { json2nameValue($EVENT) }
attr Muster_Shelly1pm room Steuerung->Test
attr Muster_Shelly1pm setList relay0:on,off,toggle shellies/shelly1pm-123456789012/relay/0/command $EVTPART1\
  off:noArg shellies/shelly1pm-123456789012/relay/0/command off\
  on:noArg shellies/shelly1pm-123456789012/relay/0/command on\
  x_update:noArg shellies/shelly1pm-123456789012/command update_fw\
  x_mqttcom shellies/shelly1pm-123456789012/command $EVTPART1
attr Muster_Shelly1pm setStateList on off
attr Muster_Shelly1pm timestamp-on-change-reading state,online,loadState,overtemperature
attr Muster_Shelly1pm userReadings relay_0_energy_total:relay_0_energy:.* monotonic {ReadingsNum("$name","relay_0_energy",0)}, Verbrauch_Total_kWh:relay_0_kWh:.* monotonic {ReadingsNum("$name","relay_0_kWh",0)}
attr Muster_Shelly1pm webCmd :
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Als Diskussionsgrundlage:
Was versteht der User Beta-User unter einem gut konfigurierten Client (= ein Gerät, das Daten via MQTT z.B. an FHEM publisht):

(Kann sein, dass meine hier dargestellten Ansichten dazu korrekturbedürftig sind, aber was besseres ist mir dazu bisher auch nicht eingefallen...)

ZitatWas mich "ungenau" stört: Das Verhalten von Shelly ist (wie das von Tasmota auch, aber da haben wir auch einigen Aufwand reingesteckt, um die Auswirkungen sinnvoll zu begrenzen...) mMn. nicht 100% "MQTT"-like.

Ich zitiere mal aus der Doku zu 3.1.1 (http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html)
ZitatMQTT is a Client Server publish/subscribe messaging transport protocol. It is light weight, open, simple, and designed so as to be easy to implement. These characteristics make it ideal for use in many situations, including constrained environments such as for communication in Machine to Machine (M2M) and Internet of Things (IoT) contexts where a small code footprint is required and/or network bandwidth is at a premium.

Immer alles zu senden, ist nicht "light weight", hier hatte ich dazu auch schon mal etwas mehr geschrieben:
Zitat von: Beta-User am 27 April 2020, 12:37:53
[...] Das "Grundproblem" ist m.E. ein anderes: Nach meinem Verständnis ist MQTT ein Protokoll, das mal dafür gemacht war, Zustände ausfallsicher zu übermitteln. Es gibt daher zu jedem Informationspunkt in meiner Gedankenwelt optimalerweise genau eine Information, die in der Auswahl recht beschränkt ist, und irgendwelche Elemente nach dem Muster "0/1/on/off/missing/offline/failure..." haben sollte. Mit JSON weicht man das Prinzip etwas auf, was auch noch solange ok ist, als die Datenpunkte und Werte irgendwie zuordenbar bleiben.

Dinge wie Grafiken (valetudo) oder Konfigurationen (homeassistant-discovery-Meldungen) zu übertragen, sind für mich "abuse", das ist nicht "schlank und schnell" (=MQTT-like=maschinenlesbar), sondern "fett" (Webpage-like=menschenlesbar).

[...]
Vielleicht kurz zum Hintergrund: Mein "gedanklicher Prototyp" für den Einsatz von MQTT ist eine Ölpipeline. Für sowas wurde das afaik mal entwickelt:
Hardwareüberwachung unter Extrembedingungen. Lange Stecken, ständig zu befürchtende Verbindungsabbrüche, widrige externe Umstände wie Hitze/Staub/Kälte/Wasser. Also: Wenig Info, eigentliche Auswertung der Info erfolgt "hinter dem Broker".

Ich hoffe, das ist nachvollziehbar und hilft ggf. auch beim Design (imo) "guter" MQTT-Implementierungen?
Kurzform: Ein optimales MQTT-Device sendet mMn. immer nur genau die Infos, die jemand in einem Kontrollzentrum braucht oder haben will. Das erfordert eigentlich entsprechende Konfigurationsmöglichkeiten auf dem Device selbst, die allerdings afaik teils nicht vorhanden sind (?).
Meine Erwartung, an das, was zu senden wäre, wäre daher in etwa das hier:
- LWT => zeigt an, ob das Gerät überhaupt erwartungsgemäß kommunizieren kann. Sollte JEDES MQTT-Gerät können. Intervall sollte einstellbar sein, per Default eher lang (in einem typischen Hausautomatisierungsumfeld reichen 5-15 Minuten oder so).
- Bestätigungen für erhaltene Anweisungen (schalte Relay xy ein)
- Messwerte wie Temperaturen oder Luftfeuchtigkeit: regelmäßig, Intervall einstellbar, optimalerweise noch mit Schwellenwerten für schnellere Änderungen)
- Basisinfos nur beim Starten (IP-Adresse, firmwareversion usw.)
- sonstige Statusinfos nur auf Anfrage
Zu ergänzen wäre noch:
Unterschiedliche Topics für Sende- und Empfangsweg (siehe einen der vorherigen Beiträge).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

"Gesprächige Geräte bändigen" - Teil 2a: JSON-Payload

Man nehme einen zweikanaligen Tasmota-Aktor und schaue sich das Ergebnis des aktuellen "split"-Tasmota-attrTemplate an. Hintergründe sind rudimentär rund um diesen Beitrag zu finden, im wesentlichen geht es um jsonMap (und event-on... wie bei "Klartext"-Payload aus Teil 1)...
Zitat von: Beta-User am 19 Februar 2020, 09:24:23Moin.

Zu jsonMap gibt es nicht allzuviel Lesestoff, und ich habe auch "etwas" gebraucht, um zu sehen, wozu man es z.B. im Tasmota-Kontext verwenden kann und sollte. Das wesentliche scheint ja angekommen zu sein: Man kann damit Readings umbenennen, die sich aus dem JSON sonst ergeben würden, und man kann einzelne Informationen aus dem JSON "ausschalten". Das betrifft aber nur die Empfangsrichtung!

Dass es im jsonMap von POWER2 jetzt "0" heißt (also: ausgeschaltet) und nicht "state", hat damit zu tun, dass sonst die Zeitstempel nicht passen - der JSON wird nämlich regelmäßig aktualisiert, auch wenn sich gar nichts ändert. Das finde ich nicht gut, deswegen sollte in der readingsList für POWER2 auch das state-Topic abboniert sein, und nichts anderes (was aber bei dir erwartungswidrig der Fall zu sein scheint, warum auch immer; das template sollte jedenfalls genau das machen).

Allerdings ist POWER2 beim 4-kanaligen auch speziell, weil das 4-kanalige template die ersten beiden Kanäle im wesentlichen über das 2ch-split konfiguriert... Will nicht ausschließen, dass dabei was schief geht.
[...]
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

"Spezielle Payloads" - Teil 1 - "eocr direkt"

a) "normale Payloads"
8channel_ethernet_board_split
Das Device liefert bei jedem Schaltvorgang die Zustände von allen 8 Ausgängen als Bitfolge (z.B. 10010110 oder 01101011). Das attrTemplate greift sich für jeden Kanal nur das relevante Bit, wandelt es in das FHEM-typische "on/off" um und vergleicht das Ergebnis mit dem aktuellen Schaltzustand. Das Reading wird nur (triggernd) aktualisiert, wenn eine Änderung vorliegt.

b) JSON
6channel_ethernet_board_6input_split
Ähnlich, aber es wird für jedes Relay bzw. jeden input der Datenpunkt ein JSON-Paar geliefert. Der JSON-String wird vorbehandelt (true wird zu on usw.), und dann via map-Vergleichsroutine geprüft, ob bzw. welche Änderungen vorliegen (Hauptkanal). In den Nebenkanälen wird der JSON direkt durchsucht und dann nur der zum Kanal gehörende Teil berücksichtigt.

(Mir ist klar, dass das Exotendevices sind, aber wer ähnliche Probleme hat, findet bei diesen beiden attrTemplates die Prototypen für andere Dinge, die hier dann noch kommen werden. Die Infos zu den originalen Payloads etc. sind über die im Template-Code verlinkten Threads zu finden...)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Und hier  ein Beitrag von Otto123, den ich hier gerne wie angeregt aufnehme :) :

Entfernten MQTT-Server (mit MQTT2_CLIENT) anzapfen und eigene Devices via bridgeRegexp basteln. Einzig die Ausführungen zum escapen der slashes in bridgeRegexp etc. sind nicht ganz optimal, siehe Anmerkung von Rudi im Original-Thread.

Wer "funktionierende" (aber ggf. auch noch vereinfachbare) Beispiele für bridgeRegexp sucht, findet dazu z.B. auch was in "MQTT2_CLIENT_Bridge"; auch da wird viel mit "alles, aber nicht diese(s) Zeichen" gearbeitet.

Zitat von: Otto123 am 06 Dezember 2020, 00:26:50
Mal sehen: vielleicht wird das ein Teil vom MQTT2 Workshop, eine Anleitung oder nur eine Mitschrift. Am Ende brauche ich bestimmt noch Ideen und Hilfe.
Ich will erstmal ohne Template auskommen, ich tue mal so als gibt es noch keins für meinen Fall.
Ich mag es simpel und "generisch" - also MQTT2 :) und ein bisschen FHEM - aber nicht noch viele Geräte dazu.
Mein Ziel: Anwesenheit an bestimmten Orten feststellen.
Zutaten: Smartphone, Owntracks, MQTT Server in der Cloud
Die bisherigen Ansätze mit owntracks und Livetracking hier im Forum habe ich gelesen ;)
Der erste Schritt:
ein MQTT2_CLIENT zu meiner MQTT Cloud Instanz mit der der Owntracks Dienst auf meinem Smartphone auch verbunden ist. Er sollen Geräte per autocreate erzeugt werden:
define mqtt2Cloud MQTT2_CLIENT ...
attr mqtt2Cloud clientId fhem1
attr mqtt2Cloud autocreate simple

Und jetzt in der App mal eine Nachricht senden (im Hauptmenu der Pfeil nach oben)
Es entsteht sofort ein spannendes Device :)
defmod MQTT2_fhem1 MQTT2_DEVICE fhem1
attr MQTT2_fhem1 IODev mqtt2Cloud
attr MQTT2_fhem1 readingList fhem1:owntracks/user/device:.* { json2nameValue($EVENT) }
attr MQTT2_fhem1 room MQTT2_DEVICE

mit einer Reihe Readings über den aktuellen Standort.
Bridgedevice
Alles von diesem MQTT2_CLIENT mqtt2Cloud landet jetzt in diesem Device. Das will ich nicht, also muss ich den Datenstrom irgendwie lenken: bridgeRegexp
Damit werden die MQTT Nachrichten neu aufteilt und dabei nach Geräten sortiert. Wie mach ich das? Wo muss ich schauen?
Wie sieht denn die Nachricht/der Topic aus? offenbar so: owntracks/UserName/DeviceName - gibt es eine Doku dazu? Ja! Und auch die Json Beschreibung.
Subscription: owntracks/+/+ weitere Topic cmd, waypoints, event, info
Ein bridgeRegexp müsste also folgendes tun: owntracks ermitteln (wäre ein fester String), UserName DeviceName dynamisch ermitteln
Hilfsmittel https://regex101.com/ - und regExp Lernprogramm ;)
Beim probieren und etwas suchen lerne ich diesen Ausdruck:  [^/:]
Die Zeichenmenge / und : ([/:] match auf diese Zeichen) aber durch ^ wird umgekehrt: match auf alles außer / und :
Die Webseite sagt: man muss die / schützen -> \/
owntracks\/([^\/:]+)\/([^\/:]+).*:.*
Die Klammern() extrahieren das, was innerhalb gefunden wird, in Variablen $1 $2 $3 usw.
Eine neue Bridge und das ursprüngliche Device wird gelöscht
define MQTT2_owntracks_bridge MQTT2_DEVICE
attr MQTT2_owntracks_bridge IODev mqtt2Cloud
attr MQTT2_owntracks_bridge bridgeRegexp  owntracks\/([^\/:]+)\/([^\/:]+).*:.* "owntracks_$1_$2"
attr MQTT2_owntracks_bridge room MQTT2_DEVICE
delete MQTT2_fhem1,FileLog_MQTT2_fhem1

Die nächste Aktualisierung legt ein neues Gerät an, welches mit Ausnahmen des Namens genau wie oben aussieht. Das will ich jetzt noch weiter konfigurieren, z.B. Steuerelemente einbauen:
readingList ergänzen:
Die readingList kann sich automatisch noch mit anderen Topics füllen.
Der erste Eintrag verhindert genau dies, schreibt aber die Raw Payload in ein Reading zum experimentieren und verstehen.
Die beiden anderen Topics kenn ich aus der Doku oder sie sind schon automatisch entstanden, der event zur Standortanzeige und waypoints zum -einlesen aus der App.
owntracks/user/device.* raw
owntracks/user/device/event:.* { json2nameValue($EVENT,'',$JSONMAP) }
owntracks/user/device/waypoints:.* { json2nameValue($EVENT) }

setList setzen:
Um komplette Json Beispiele aus der Doku in die Kommandozeile zu werfen und testen.
x_raw_payload:textField { my $payload = $EVENT;$payload =~ s/$EVTPART0 //; qq(owntracks/user/device/cmd $payload)}
getList verwenden
ein get Befehl ist vom Inhalt her genauso wie ein set Befehl - aber er wartet darauf, dass das Reading (welches in readingList erscheinen muss) gesetzt wird.
getList cmd reading [topic|perl]
Man kann sich in dem Fall mit dem raw Reading behelfen, wenn man "hole" Befehle nicht in die setList sondern in die getList schreiben will.
location:noArg raw owntracks/user/device/cmd {"_type":"cmd","action":"reportLocation"}
waypoints:noArg raw owntracks/user/device/cmd {"_type":"cmd","action":"waypoints"}

userReadings für die Ermittlung
Mein Ziel könnte ich mit dem Reading Place erreichen, welches entweder einen meiner Standorte(Waypoints) oder das Wort "away" enthält.
Das Gerät erzeugt zwei Events:

       
  • enter
  • leave
Also schreibe ich das Reading place bei jedem Event
place:event.* {my $evt=ReadingsVal($name,'event','');;my $desc=ReadingsVal($name,'desc','nowhere');;if ($evt eq 'leave'){$desc='away'};;return $desc}

Das weitere wird noch Feintuning, aber bis hierher läuft es schon?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#7
JSON-Payloads nur teilweise aufdröseln

Aus gegebenem Anlass auch noch eine kleine Anleitung, wie man Code-Experimente machen kann, um etwas anderes zu erhalten als das was json2NameValue() per default liefert.

Ausgangsbasis war ein über ein FileLog eingefangener JSON (stammt aus Zigbee2MQTT - Template für Thermostat, da ist auch erklärt, wie man "json_raw" erzeugt):
2020-12-08 15:28:32 MQTT2_DEVICE MQTT2_zigbee_0xbc33acfffe45850a json_raw: {"auto_lock":"MANUAL","away_mode":"OFF","away_preset_days":1,"away_preset_temperature":15,"boost_time":300,"child_lock":"UNLOCKED","comfort_temperature":20,"current_heating_setpoint":"23.0","eco_temperature":15,"force":"normal","holidays":[{"hour":134,"minute":0,"temperature":20},{"hour":8,"minute":0,"temperature":15},{"hour":11,"minute":30,"temperature":15},{"hour":12,"minute":30,"temperature":15},{"hour":17,"minute":30,"temperature":20},{"hour":22,"minute":0,"temperature":15}],"linkquality":154,"local_temperature":"23.0","local_temperature_calibration":"-1.0","max_temperature":35,"min_temperature":5,"position":100,"preset":"manual","system_mode":"manual","week":"5+2","window_detection":"OFF","window_detection_params":{"minutes":10,"temperature":5},"workdays":[{"hour":6,"minute":0,"temperature":20},{"hour":8,"minute":0,"temperature":15},{"hour":11,"minute":30,"temperature":15},{"hour":12,"minute":30,"temperature":15},{"hour":17,"minute":30,"temperature":20},{"hour":22,"minute":0,"temperature":15}]}
Man nehme einen MQTT2_SERVER und lasse den "rückwärts publishen":
defmod m2server MQTT2_SERVER 2883 global
attr m2server rePublish 1


Dann setzt man einen passenden Topic vor den JSON und publisht:
set m2server publish ztm_thermostat/json {"auto_lock":"MANUAL","away_mode":"OFF","away_preset_days":1,"away_preset_temperature":15,"boost_time":300,"child_lock":"UNLOCKED","comfort_temperature":20,"current_heating_setpoint":"23.0","eco_temperature":15,"force":"normal","holidays":[{"hour":134,"minute":0,"temperature":20},{"hour":8,"minute":0,"temperature":15},{"hour":11,"minute":30,"temperature":15},{"hour":12,"minute":30,"temperature":15},{"hour":17,"minute":30,"temperature":20},{"hour":22,"minute":0,"temperature":15}],"linkquality":154,"local_temperature":"23.0","local_temperature_calibration":"-1.0","max_temperature":35,"min_temperature":5,"position":100,"preset":"manual","system_mode":"manual","week":"5+2","window_detection":"OFF","window_detection_params":{"minutes":10,"temperature":5},"workdays":[{"hour":6,"minute":0,"temperature":20},{"hour":8,"minute":0,"temperature":15},{"hour":11,"minute":30,"temperature":15},{"hour":12,"minute":30,"temperature":15},{"hour":17,"minute":30,"temperature":20},{"hour":22,"minute":0,"temperature":15}]}

Aktiviertes autocreate vorausgesetzt, hat man dann ein Device mit ziemlich vielen Readings, die in der Form eher nicht so einfach nutzbar sind:
defmod MQTT2_WEB_127.0.0.1_57818 MQTT2_DEVICE WEB_127.0.0.1_57818
attr MQTT2_WEB_127.0.0.1_57818 IODev m2server
attr MQTT2_WEB_127.0.0.1_57818 readingList WEB_127.0.0.1_57818:ztm_thermostat/json:.* { json2nameValue($EVENT) }
attr MQTT2_WEB_127.0.0.1_57818 room MQTT2_DEVICE


Der Name ist etwas ungeschickt, und auch die ClientID brauchen wir eigentlich nicht für's weitere Testen, dafür aber ggf. jsonMap. Also löschen, ändern und ergänzen:
rename MQTT2_WEB_127.0.0.1_57818 ztm_thermostat
attr ztm_thermostat readingList ztm_thermostat/json:.* { json2nameValue($EVENT,'',$JSONMAP) }
deletereading ztm_thermostat .*


Dann nehme man etwas "Magie von Rudi" (aus dem owntracks-Thread von Otto123):
Zitat von: rudolfkoenig am 07 Dezember 2020, 13:59:20
{ my (%h,$cnt);; $EVENT=~ s/(\{[^[]*?})/$h{"Readings".++$cnt}=$1/ge;; \%h }
und bastle das mit Hilfe von https://regex101.com/ so um, dass wir die Temperaturlisten-Arrays als separate subgroups in einer loop verarbeiten können.

Also erst mal auf https://regex101.com "Match 1" und "Match 2" ermitteln:
("(holidays|workdays)":.([^]]+))

Und tada, raus kommt dann in etwa sowas:
attr ztm_thermostat readingList ztm_thermostat/json:.*
{ my %h;; my $temp = $EVENT;; $temp =~ s/,?("(holidays|workdays)":.([^]]+))./$h{$2}=$3/ge;; $EVENT =~ s/,?("(holidays|workdays)":.([^]]+)).//g;; my $h2 = json2nameValue($EVENT,'',$JSONMAP);; %h = (%h,%$h2);; \%h }

EDIT: Code geändert, man muss da zwei Variablen verwenden, denn zum einen landet der Rückgabewert der Funktion wieder in der Variable (for the records: das scheint hier $3 zu sein), und zum anderen sollte auch ein 100% gültiger JSON nach dem Wegschneiden verbleiben (also der Match zu kurz war). Prüfen kann man das z.B. mit https://jsoneditoronline.org.

Wer mag, kann ja selbst testen, was da als Reading/Readingwert so alles rauskommt, man braucht dafür keine Hardware ;D .
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

JSON-Payloads - direkt verwertet...

Manchmal braucht man nicht erst Readings, auf die man dann wieder mit einem Eventhandler reagiert, sondern hin und wieder könnte man auch direkt die empfangenen Nachrichten auswerten.

Bildchen von der betreffenden Fernbedienung ist unten angehängt, der Code dafür ist hier zu finden (das bezieht sich auf die 99_attrT_MiLight_Utils.pm -Version):
https://forum.fhem.de/index.php/topic,103493.msg972085.html#msg972085

Was die betreffende Remote sendet, sind zum einen pure Differenz-Meldungen, die nur aus einem key-value-Paar bestehen und daneben (auf dem nicht verwendeten Topic) der komplette Status mit vielen key-Value-Paaren (das wird dann für ein anderes Device die Fortsetzung).

Hier erst mal das MQTT2_DEVICE-Device, vielleicht wird dann schon klarer, was man mit so einer billigst-Fernbedienung so alles anstellen kann...
Zitat von: Beta-User am 05 November 2020, 07:51:10
...das Ergebnis sieht dann in etwa so aus:
defmod MiLight_RC_WZ MQTT2_DEVICE milight_0x5D47_0
attr MiLight_RC_WZ readingList milight/updates/0x5D47/fut089/0:.* { FHEM::attrT_MiLight_Utils::MPDcontrol('myMPD',$EVENT, 'Yamaha_Main') }\
milight/updates/0x5D47/fut089/1:.* { FHEM::attrT_MiLight_Utils::FUT_to_RGBW('Licht_Stehlampe_links',$EVENT) }\
milight/updates/0x5D47/fut089/2:.* { FHEM::attrT_MiLight_Utils::FUT_to_RGBW('Licht_Stehlampe_rechts',$EVENT) }\
milight/updates/0x5D47/fut089/3:.* { FHEM::attrT_MiLight_Utils::four_Lights_matrix($EVENT, 'Licht_WoZi_Vorn_Aussen', 'Licht_WoZi_Vorn_Mitte', 'Licht_WoZi_Hinten_Aussen', 'Licht_WoZi_Hinten_Mitte') }\
milight/updates/0x5D47/fut089/4:.* { FHEM::attrT_MiLight_Utils::shuttercontrol('Jalousie_WZ',$EVENT) }\
milight/updates/0x5D47/fut089/5:.* { FHEM::attrT_MiLight_Utils::shuttercontrol('Rollladen_WZ_SSO',$EVENT) }\
milight/updates/0x5D47/fut089/6:.* { FHEM::attrT_MiLight_Utils::shuttercontrol('Rollladen_WZ_SSW',$EVENT) }\
milight/updates/0x5D47/fut089/7:.* {}\
milight/updates/0x5D47/fut089/8:.* {}\
milight/states/0x5D47/fut089/[0-8]:.* {}
attr MiLight_RC_WZ stateFormat CommandSet


Im ersten Post die zugehörige neue myUtils - gleich im package-Format.

Die ausgeführten Kommandos bzw. Infos über empfangene, aber noch nicht zugewiesene JSON-Elemente finden sich in dem Reading "CommandSet".

So langsam ist das wohl aus dem [WIP]-Status raus... 8)

...und so langsam habe ich das meiste eigene Pulver für den workshop hier verschossen, einen habe ich noch im Hinterkopf, aber dann wärt ihr mal wieder dran... ;D
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

"Gesprächige Geräte bändigen" - Teil 2b: JSON-Payload
und
"Spezielle Payloads" - Teil 2 - "eocr direkt reloaded - including userReadings"

Es geht um eine firmware, die sehr viele Infos in JSON verpackt, und dann alle 5 Sekunden (!) den kompletten Datensatz versendet.
Das ganze ist noch nicht abschließend fertig (eigentlich sollte man vor prozentualen oder absoluten Abweichungen noch prüfen, ob der Wert nicht einfach identisch ist), und evtl. baue ich das auch noch für den zigbee2mqtt-Thermostat-Code um (das wäre m.E. etwas weniger speziell als die konkrete Anwendung hier und dann auch einfacher für andere Anwendungsbereiche zu adaptieren), aber als Basis ist es m.E. gut zu gebrauchen:

Das war der Einstieg:
Zitat von: Beta-User am 06 November 2020, 17:07:24
Oh yeah, das ist ja gruselig...

Eigentlich sollte man die Jungs da bei [...] fragen, ob die nicht eine etwas weniger gesprächige firmware liefern können, alle 5 Sekunden die WiFi-SSID, das braucht m.E. kein Mensch... Sowas will man doch nur wissen, wenn es sich ändert, und meinetwegen beim Starten der Box oder was auch immer das ist >:( .

Na ja, wie dem auch sei, anbei der Versuch, das, was json2NameValue() mit Hilfe von jsonMap macht, sowie einen Teil der (bisherigen) userReadings in Code zu verlagern - das kommt "ganz normal" in das Modulverzeichnis (typ. opt/fhem/FHEM).

Kann aber sein, dass da ggf. eine ganze Anzahl Denkfehler drin sind, aber zumindest einen kurzen Test hat es überstanden, das passende Device sieht so aus:
defmod go_echarger MQTT2_DEVICE go-echarger
attr go_echarger IODev m2server
attr go_echarger readingList go-eCharger/002227/status:.* { FHEM::attrT_go_e_Utils::j2rN_extended("go_echarger",$EVENT) }
attr go_echarger room MQTT2_DEVICE


Tendenziell würde ich jetzt ein weiteres Reading anlegen, das den Zeitpunkt der letzten vollständigen Aktualisierung enthält und erst mal alle "Neben-Readings" verwerfen, die jünger sind wie z.B. eine Stunde. Nach Ablauf der Zeit dann einen vollst. Check, ob es Änderungen gab und alles verwerfen, was nicht geändert war (oder von vorneherein gar keinen Wert enthält...) und das "Zeit-Reading" neu setzen.

Für die relativen Vergleiche der Hauptreadings sind ein paar Funktionen vorbereitet, aber die eigentliche Prüfschleife dazu müßte man erst noch bauen. Vielleicht findet sich auch ein Mitstreiter dafür, aus der Ferne ist das nicht so einfach, und über einige interne Abhängigkeiten und Effizienzfragen müßte man auch noch brüten, und die commandref überlasse ich dann definitiv euch...

Und das ist das vorläufige Zwischenergebnis:
Zitat von: Beta-User am 09 November 2020, 14:29:23
Hmm, also...

Jetzt habe ich noch zwei "Zeitschleifen" dazu gebastelt, und hoffe, damit haben wir das Spielmaterial jetzt wirklich beieinander:
- Die Zeiten sollten einstellbar sein, das war die Absicht hinter dem %toCompare und dem Ergänzen dieses Hashes mit Parametern aus dem Funktionsaufruf (default sind 10 Minuten);
- bei den "stündlichen" habe ich das weiter dahingehend eingeschränkt, dass nur Events kommen, wenn es da Änderungen gab, die Kombination ist aber ein logisches UND, was für diese Art Readings ok ist, aber nicht einfach so für andere übernommen werden sollte;
- erstmals berücksichtigt sind absolute bzw. relative Vergleiche in der "voltage"-Schleife. Falls das aus eurer Sicht tauglich ist, müßte man das dann noch für die anderen Typen ergänzen bzw. ändern, indem man die Verweise auch in %toCompare ergänzt. Hier ist es ein logisches "oder", womit sich die Frage stellt, ob man das für den anderen Fall (Zeit ist abgelaufen) ganz oder in Teilen dann weiter mit einer "eocr"-Logik einschränken möchte oder nicht.

Sieht zwar recht abstrakt aus, aber ich hoffe, ihr könnt euch halbwegs in dem Code orientieren...?

Die myUtils hängt an dem unteren der Beiträge.

Wer also eine Lösung sucht, um ziemlich spezielle Koppelungen zwischen irgendeiner (selbstgestrickten) firmware und FHEM-Aktionen herzustellen, könnte eventuell mit diesem kleinen Baukasten was anfangen.
Testen kann man das, was der myUtils-Code da anstellt, auf dieselbe Weise wie im Vorbeitrag dargestellt.

Viel Erfolg bei euren Projekten ;)

und erst mal noch einen geruhsamen Abend,

Beta-User.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#10
mosquitto_pub - Special
mosquitto_pub ist (wie mosquitto_sub, mit dem man den MQTT-Verkehr auch gut abhören kann) Teil des debian-Pakets "mosquitto-clients". Damit werden Nachrichten gepublisht, so dass das Tool recht unkompliziert dazu genutzt werden, alles mögliche rund um MQTT auszutesten. Außerdem kann man es auf Linux-Maschinen einfach installieren und dann in scripts dazu verwenden, Dinge per MQTT zu versenden. @xenos1984 hat hier z.B. ein Perl-script gezeigt, mit dem man ähnliches machen kann wie sysmon.

Es hat aber einen kleinen Haken: Es erzeugt im default für jede neue Message auch eine neue, (in Teilen) zufällige ClientID, was iVm. "autocreate" am MQTT2_SERVER dazu führen würde, dass sehr schnell eine unübersichtliche Vielzahl von MQTT2_DEVICE-Geräten erstellt würde. Daher führt MQTT2_SERVER für die betreffenden Messages - soweit sie unter zufälligen ClientID's gesendet werden - kein autocreate aus.

Man kann nun natürlich das betreffende Gegenstück als MQTT2_DEVICE auch manuell erstellen - was kein allzu großes Problem ist, wenn man die Topics kennt, unter denen gesendet wird. Das ist aber - vor allem bei dynamisierten fremden Scripts - nicht immer der Fall (s.u.). In diesen Fällen kann man autocreate aber dann verwenden, wenn man die ClientID selbst setzt bzw. mosquitto_pub anweist, eine bestimmte ClientID zu verwenden. Dazu ist der Parameter (EDIT:) "-i" gedacht, näheres ist der manpage zu mosquitto_pub zu entnehmen.

In SMA Wechselrichter ueber SBFspot und Mqtt auszulesen /  kein autocreate ist ein Beispiel für ein solches script zu finden:
###   MQTT Settings start  ###

MQTT_Publisher=/usr/bin/mosquitto_pub

# MQTT Broker in Fhem
MQTT_Host=192.168.1.97
MQTT_Port=1883

MQTT_Topic=sbfspot_{serial}

# Format of message items to be sent
# JSON: MQTT_ItemFormat="{key}": {value}
# TEXT: MQTT_ItemFormat={key}:{value}
# XML:  MQTT_ItemFormat=<item name="{key}" value="{value}" />
MQTT_ItemFormat="{key}": {value}

MQTT_ItemDelimiter=comma

# JSON: MQTT_PublisherArgs=-h {host} -t {topic} -m "{{message}}"
# TEXT: MQTT_PublisherArgs=-h {host} -t {topic} -m "{message}"
# XML : MQTT_PublisherArgs=-h {host} -t {topic} -m "<mqtt_message>{message}</mqtt_message>"
MQTT_PublisherArgs=-h {host} -t {topic} -m "{{message}}"

# Data to be published (comma delimited)
MQTT_Data=Timestamp,SunRise,SunSet,InvSerial,InvName,InvTime,InvStatus,InvTemperature,InvGridRelay,EToday,ETotal,PACTot,UDC1,UDC2,IDC1,IDC2,PDC1,PDC2

###   MQTT Settings end  ###

Interessant sind hier v.a. die Angaben MQTT_Publisher und MQTT_PublisherArgs.
Der "Trick" besteht nun darin, MQTT_PublisherArgs passend zu ergänzen. Der TE hat mit meinem dort zu findenden Vorschlag einen Teilerfolg erzielt und war damit glücklich, ich halte ihn für verbesserungsfähig; leider hat der TE den Thread geschlossen, so dass wir bis auf weiteres auf die Antwort warten müssen, ob das hier besser oder schlechter ist und noch weiter optimiert werden kann...:
MQTT_PublisherArgs=-h {host} -t {topic} -i sbfspot_{serial} -m "{{message}}"

Vermutlich sollte man sich auch den Topic ("MQTT_Topic=SMA_Converters/sbfspot_{serial}"?) und die Auswertungsanweisung "{ json2nameValue($EVENT) }" nochmal ansehen, ich vermute, dass es im Interesse "guter Reading-Namen" hilfreich wäre, hier die "vereinfachte complex"-Variante von json2nameValue() zu verwenden. Dann könnte evtl. sowas rauskommen:
attr DEVICE readingList SMA_Converters/1100245644:.* { json2nameValue($EVENT,'',$JSONMAP) }
attr DEVICE jsonMap bad_reading1:good_reading1 not_needed1:0 [tbc]


Wer speziell für Solaranlagen Anregungen sucht, wie jsonMap "gut" zu setzen ist, findet evtl. bald dazu was hier: Frevel: Die Idee einheitlicher Devicenamen und Readings. Jedenfalls, was Reading-Namen angeht, bin ich starker Befürworter einer einheitlichen (und internationalisierten!) Namensgebung. Das macht es z.B. auch einfacher, wenn es z.B. um die Anbindung von Sprachsteuerungssystemen geht.
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Spezielle Payloads Teil 3 - Readingnamen aus JSON-Payload erzeugen

OK, ich gebe zu, eigentlich ist das hier schon ein paar Mal indirekt Thema gewesen, aber da es recht gut zum vorigen Thema paßt, hier eine kleine wiederholende Zusammenfassung: [gelöst] MQTT2_device nur werte mit bestimmten Inhalten in readings schreiben
Das Problem: Jemand hat uns ein script geliefert, das alle Infos gebündelt im JSON-Format an einen einzigen Topic schickt. Da sind aber Infos zu vielen unterschiedlichen Geräten drin, die irgendwie jeweils ein eigenes Reading oder ein eigenes Gerät (so die ursprüngliche Idee des TE) bekommen müßten, aber ohne Anpassung landet alles in einem Gerät und die neue Info von Gerät B überschreibt die alte Info von Gerät A usw..

Hier kann man entweder viele Geräte anlegen, und dann erst bei allen diesen Geräten den JSON durchsuchen, ob was passendes dabei ist. M.E. eleganter und weniger Last für' System ist es, wenn man den zweiten Parameter von json2nameValue() einsetzt, um für jedes Gerät einen per regex ermittelten Präfix an das Reading zu hängen:
Zitat von: Beta-User am 20 November 2020, 13:01:38
Hier noch die (ungetestete) Präfix-Variante für den universellen Einsatz (alles in einem Device):
opnsense/OPNsense\x2efritz\x2ebox/net:.* { $EVENT =~ m,interface...([^"]+), ? json2nameValue($EVENT, "${1}_" ) : return }
Wer die Hintergründe verstehen will: Die Rohdaten sind im verlinkten Thread zu finden, leider ist der TE da auch "still", was mich vermuten läßt, dass er zufrieden ist, und dass ggf. Verbesserungs- oder Erweiterungsvorschläge nicht erwünscht sind....



Exkurs - überholte Readings:
Vermutlich wird uns diese Konstruktion das "Problem" beschehren, dass sich über der Zeit sehr, sehr viele Readings bilden, die irgendwann auch überholt sind. Wie bekommt man die nun weg?

Ein Lösungsansatz wäre, regelmäßig zu schauen, ob das betreffende Reading veraltet ist und dann eben zu löschen, wenn das der Fall ist. Man kann sowas wie immer auf vielerlei Weise lösen, mAn. am elegantesten geht es mit MQTT2_DEVICE-Bordmitteln (aus OpenMQTTGateway_BT_scanner):
attr DEVICE setList\
  [...]
  deleteReadings:noArg {fhem "deletereading -q $NAME (?!associatedWith|attrTemplateVersion).* 86400"}
attr DEVICE periodicCmd deleteReadings:1440

Ergebnis: einmal alle 24h werden alle Readings gelöscht, die älter als 24h sind, bis auf "associatedWith" und "attrTemplateVersion".

(deletereading mit maxAge als Parameter ist sehr neu, also nicht wundern, wenn euch das seither entgangen ist).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

rudolfkoenig

Zitateine bestimmte ClientID zu verwenden. Dazu ist der Parameter "-c" gedacht, näheres ist der manpage zu mosquitto_pub zu entnehmen.

Bei mir steht dazu:
Zitat-c, --disable-clean-session
           Disable the 'clean session' flag....
-i, --id
           The id to use for this client. If not given, a client id will be generated ...

Beta-User

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Lange nichts mehr passiert hier, aber weil das die letzte Zeit ein paar Mal hier im Forum aufgetaucht ist:
Man habe einen Dienst, der z.B. verschiedene Devices verwaltet, und dann hinter seinem "Haupttopic" immer dieselbe Sub-Topic-Struktur anlegt (frigate und e3dc wären die Stichworte). Per bridgeRegexp könnte man für jedes sub-Device eigene MQTT2_DEVICE-Instanzen anlegen, muss oder will man aber uU. nicht...
Wie dem auch sei: Man kann automatisch aus dem Topic passende Reading-Namen ableiten, auch wenn der etwas tiefer gestuft ist und FHEM ansonsten per autocreate "hinten" immer dasselbe Reading erstellen würde...

Schwierig zu verstehen? Ein Beispiel:

Zitat von: Beta-User am 02 Januar 2024, 08:47:16define test_split MQTT2_DEVICE
attr test_split readingList e3dc/[^:]+:.* { my @toptree = split m{/}x, $TOPIC;; shift @toptree;; my $rname = join q{_}, @toptree;; return {$rname => $EVENT}}
#  FUUID      6593b6ca-f33f-d171-be2c-3b3b95a8c3ed1361
#  IODev      MQTT2_FHEM_Server
#  LASTInputDev MQTT2_FHEM_Server
#  MQTT2_FHEM_Server_CONN MQTT2_FHEM_Server_127.0.0.1_43302
#  MQTT2_FHEM_Server_MSGCNT 15
#  MQTT2_FHEM_Server_TIME 2024-01-02 08:45:49
#  MSGCNT    15
#  NAME      test_split
#  NR        773
#  STATE      ???
#  TYPE      MQTT2_DEVICE
#  eventCount 15
#  .DT:
#    DEVICETOPIC test_split
#  .attraggr:
#  .attrminint:
#  READINGS:
#    2024-01-02 08:10:02  IODev          MQTT2_FHEM_Server
#    2024-01-02 08:45:42  pvi_current_string_1 55
#    2024-01-02 08:45:49  pvi_current_string_2 55
#
setstate test_split 2024-01-02 08:10:02 IODev MQTT2_FHEM_Server
setstate test_split 2024-01-02 08:45:42 pvi_current_string_1 55
setstate test_split 2024-01-02 08:45:49 pvi_current_string_2 55

Hoffe, das hilft dir weiter...
Es wird also einfach der Topic in seine Einzelteile zerlegt, der erste Teil verworfen (das Basistopic "e3dc"), und dann der Rest als Reading-Namen verwendet.

Könnte man dahingehend ausbauen, dass man z.B. den letzten Teil (der hier oft (oder immer?) "state" lautet), dann auch noch verwirft (ungetestet):
attr test_split readingList e3dc/[^:]+:.* { my @toptree = split m{/}x, $TOPIC;; shift @toptree;; pop @toptree if $toptree[-1] eq 'state' ;; my $rname = join q{_},
@toptree;; return {$rname => $EVENT}}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files