MQTT-DEVICE: Readings dynamisch umbenennen

Begonnen von h002, 30 Dezember 2023, 23:03:36

Vorheriges Thema - Nächstes Thema

h002

Ich bekomme von meinem MQTT-Broker beispielhaft folgende Topics bereitgestellt.

e3dc/pvi/current/string_1 342.2
e3dc/pm/power/L3 23.4
e3dc/solar/power 50.00
e3dc/grid/power 502.00
...

Über ein MQTT2_DEVICE wird durch das Attribut bridgeRegexp und dem Wert e3dc.* "e3dc_$1" für jede unterschiedliche Topic ein eigenes Devices angelegt, da z.B. wie oben "power" unterschiedlich interpretiert werden kann.

Am Ende habe ich 10-20 Devices. Mein Ziel ist, in einem Device alles zusammen zu führen.

Das MQTT-Device soll e3dc_mqtt heißen und ich möchte die Readings und dazugehörigen Werte dynamisch erstellen lassen wie z.B.:

e3dc_pvi_current_string_1 342.2
e3dc_pm_power_L3 23.4
e3dc_solar_power 50.00
e3dc_grid_power 502.00

Da mir kein zusammengefasstes json geliefert wird, wollte ich wissen, wie ich das realisieren kann? Kann ich dies in der readingList des Devices mit Perl realisieren  - nach folgender Logik und auf Basis des unten aufgeführten MQTT Traffics:

- Nimm $EVENT und ersetze "/" mit "_" und verwende es als Reading
- Nimm $EVTPART0 als Wert für das Reading

Hier noch ein Auszug des Outputs von "Show MQTT traffic" des MQTT Clients.

22:51:37.994 RCVD e3dc/solar/power 0
22:51:37.996 RCVD e3dc/battery/power 0
22:51:37.998 RCVD e3dc/home/power 416
22:51:38.001 RCVD e3dc/grid/power 416
22:51:38.004 RCVD e3dc/addon/power 0
22:51:38.006 RCVD e3dc/battery/soc 0
22:51:38.009 RCVD e3dc/pm/power/L1 177

Falls es über das readingList geht, kann mir jemand exemplarisch ein Code-Ansatz liefern?

Viele Dank für kommende Anregungen :-)

LuckyDay

defmod testDevice MQTT2_DEVICE

attr testDevice readingList e3dc/solar/power:.* solarPower
e3dc/battery/power:.* batteryPower
e3dc/home/power:.* homePower
e3dc/grid/power:.* gridPower

usw.
du kannst ,wenn du willst alle topic in einem device zusammenlegen, musst dir nur sinnvolle einmalige readingsnamen geben
Beispiele habe ich gezeigt.

h002

Danke für den Hinweis. Manuell hatte ich es auch schon hinbekommen. Da es über 200 Readings sind, wollte ich was "dynamisches" nutzen. Vielleicht läuft es am Ende wirklich auf den manuellen Weg hinaus und ich konzentriere mich auf die für mich interessanten Readings und benenne sie manuell passend um.

h002

Vielleicht sollte ich die Frage auch anders formulieren.

Ich bekomme die Topic e3dc/history/2022/solar/energy mit einem Wert geliefert. Wie kann ich den Namen des Readings mit Hilfe einer Bedingung in Perl bei Erstellung des MQTT-Devices umbenennen.

Nach dem Prinzip, wenn Text solar/energy in der Topic enthalten ist, dann soll das Reading energy_solar im Device lauten.

Beta-User

Ist "nur" etwas Perl in der readingList.

Mit "split" ein Array aus $TOPIC bilden, (den ersten Teil wegwerfen), und dann wieder mit "join" zusammenkleben und einen Hash mit dem Testergebnis und $EVENT zurück geben.

Bitte selbst versuchen und ggf. dann den Zwischenstand wieder hier Posten....
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

h002

In welche readingList soll ich den Code einsetzen bzw. wie funktioniert das mit der automatischen Erzeugung der Devices?

Mein MQTT2_DEVICE mit der bridgeRegexp e3dc/history/([^/]+).* "e3dc_history_$1" erstellt automatisch Devices in Form von MQTT2_e3dc_history_2020, MQTT2_e3dc_history_2021, ... . Diese Devices enthalten die Readings, die ich gerne umbenennen möchte. Wie erreiche ich, dass der zu erstellende Perl-Code für die Readings mit in das Device z.B. MQTT2_e3dc_history_2021 übergeben wird und dort das Reading wie gewünscht geändert wird? So wie:

e3dc/history/2021/solar/energy -> energy_solar
e3dc/history/2021/home/energy -> energy_home

Ich möchte nicht manuell den Code zur Umwandlung in jedes History-Device kopieren. Wenn zu den jährlichen Werten noch die monatlichen Werte kommen würden, muss ich viele Devices ändern.


Ausschließen kann ich auch nicht, dass ich irgendwo noch ein generelles Verständisproblem habe. ;-)

Beta-User

Mach nicht zu viel auf einmal....

Erst mal "einfach nur" den Perl-code für eines der Devices. Dann sehen wir weiter.

M.E. braucht man weder viele Devices (bridgeRegexp), noch (am Ende) viele Zeilen in der readingList.
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

define 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...
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

h002

Viele Dank für deinen Input. Muss deine Code-Zeile mal durchdenken und etwas rumprobieren, ob dies auch für meinen Fall passen würde.

Zwischenzeitlich habe ich quick and dirty eine erste Lösung für ein History-Device:

e3dc/history/2020.* 
{my $topic = "$TOPIC";
$topic =~ /.*grid.*in/ ? $topic = "in_grid" : 0;
$topic =~ /.*grid.*out/ ? $topic = "out_grid" : 0;
$topic =~ /.*home.*energy/ ? $topic = "energy_home" : 0;
$topic =~ /.*solar.*energy/ ? $topic = "energy_solar" : 0;
$topic =~ /.*energy\/charge.*/ ? $topic = "charge" : 0;
$topic =~ /.*energy\/discharge.*/ ? $topic = "discharge" : 0;
$topic =~ /.*consumed.*/ ? $topic = "consumed" : 0;
$topic =~ /.*autarky.*/ ? $topic = "autarky" : 0;
{"$topic" => "$EVENT"};}

Jetzt muss ich noch weiter überlegen, wie dieser Part in die automatisch erstellen Device "e3dc/history/2021", "e3dc/history/2022", ... übernommen werden kann, da ich dafür jedes Jahr ein Gerät möchte und die Readings evtl. um die Monatswerte erweitert werden sollen.

h002

Ich habe eben deine Zeile mal eingebaut und das geht prima. ;D  Jetzt habe ich die Jahreswerte in einem Device. Ein guter Anfang, der mir auf jeden Fall weiter hilft.

Kannst du mir kurz erklären wie die Syntax split m{/}x, $TOPIC; zu verstehen ist? Was split tut ist mir klar und auch das offenbar nach "/" gesplittet wird. Aber die Kurzschreibweise m{/}x verstehe ich nicht. Danke


Beta-User

Zitat von: h002 am 02 Januar 2024, 11:12:45Kannst du mir kurz erklären wie die Syntax split m{/}x, $TOPIC; zu verstehen ist? Was split tut ist mir klar und auch das offenbar nach "/" gesplittet wird. Aber die Kurzschreibweise m{/}x verstehe ich nicht. Danke
Es wird an allen "/" gesplittet und die Fragmente dann in einem Array zwischengespeichert. "m" ist einfach die Anweisung an den Compiler, dass jetzt ein pattern-match erwünscht ist, dann kommt in den Klammern (man kann statt des "FHEM-üblichen" Trenners "/", der hier wegen der Übereinstimmung mit dem Suchpattern "blöd" wäre, auch z.B. "<>" verwenden) der pattern, an dem gesplittet werden soll, und "x" ist einfach eine weitere Anweisung, wie der pattern zu interpretieren ist. Seit ich über alle meine codes Perlcritic drüber laufen lasse, ist das halt mein Standard, bei https://perldoc.perl.org/perlre#/x-and-/xx (bzw. perlcritic.com) wären auch mehr Infos 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

h002

Deinen Teil
readingList e3dc/[^:]+:.* { my @toptree = split m{/}x, $TOPIC;; shift @toptree;; my $rname = join q{_}, @toptree;; return {$rname => $EVENT}}habe ich minimal angepasst und sieht nun so aus
e3dc/history/[^:]+:.* { my @toptree = split m{/}x, $TOPIC;; shift @toptree;; shift @toptree;; my $rname = join q{_}, @toptree;; return {$rname => $EVENT}}
Damit werden in dem Device folgende Readings angelegt.
2020_home_energy
2020_solar_energy
2020_battery_energy_discharge
2020_battery_energy_charge
2021_home_energy
2021_solar_energy
2021_battery_energy_discharge
2021_battery_energy_charge
u.s.w. angelegt. Das gefällt mir schon sehr gut. :-)

Später möchte ich das um die Monate erweitern. Allerdings werden mir das zu viele Readings in dem Device MQTT2_e3dc_history, was ja nun alle Jahre enthält und zusätzlich um je 12 Monate wachsen würde.

Was müsste ich tun, damit z.B. automatisch ein Device MQTT2_e3dc_history_2020 angelegt wird (bridgeRegexp) und gleich die readingsList ähnlich der jetzigen mit übernommen wird? Geht das überhaupt? Sind das dann die s.g. Templates?

Beta-User

Zitat von: h002 am 03 Januar 2024, 22:25:50Was müsste ich tun, damit z.B. automatisch ein Device MQTT2_e3dc_history_2020 angelegt wird (bridgeRegexp) und gleich die readingsList ähnlich der jetzigen mit übernommen wird? Geht das überhaupt? Sind das dann die s.g. Templates?
Moin.
Teil 1 ist richtig, per bridgeRegexp kannst du dir separate Devices anlegen lassen.

Der Werkzeugkasten "attrTemplate" ist aber nicht dazu gedacht, automatisch Attribute zu vergeben, da müßte man manuell eingreifen.

Für einen Automatismus gäbe es z.B, "archetype", da sind auch ein paar andere Varianten in der commandref verlinkt.

PS: Ich würde die Jahreszahl aus den Readingnamen raus lassen, wenn du separate Devices hast. Zur Visualisierung ist zwar so oder so Handarbeit angesagt, aber ohne diese Info kannst du zumindest für jedes Device dann wieder denselben Code zur Nachbearbeitung nehmen...
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