Mehrere Readings geschlossen als JSON publishen

Begonnen von vbs, 02 Januar 2025, 00:54:34

Vorheriges Thema - Nächstes Thema

vbs

Hi Ihr,

also ich habe Sensor-Devices in FHEM und einige Werte (z.B. Temperature und Humidity) werden zusammen upgedatet. Nun möchte ich die beiden nicht separat als 2 MQTT-Nachrichten verschicken, sondern nur als eine Nachricht mit JSON-body.
Außerdem würde ich gerne noch den Reading-Timestamp mit in die Nachricht schreiben, damit der erhalten bleibt und z.B. InfluxDB/telegraf nicht den Empfangszeitstempel nutzen muss. Das Ganze möchte ich eigentlich mit MQTT_GENERIC_BRIDGE machen.

Herausforderungen, die ich dabei sehe:
* Selbst den JSON-Body erzeugen
* Zwar mehrere Readings verarbeiten, aber nur einmal triggern für die "Gruppe"
* Die MQTT-Nachricht erst verschicken, wenn alle Nachrichten aus der Gruppe upgedatet sind.

Um nur einmal zu verschicken, obwohl mehrere Readings geupdatet werden, reagiert man nur auf _eines_ der Reading. Dafür gibt es nach meinem Verständnis zwei Varianten:
1. In dem Device werden die Readings, um die es geht, per Bulk-Update geupdatet. Hier ist es dann egal, auf welchem einen Reading man triggert.
2. In dem Device werden die Readings einzeln (ohne Bulk-Update) geupdatet. In dem Fall muss man die Reihenfolge kennen und dann auf das letzte Reading triggern.

Hier die erste Frage:
Gibt es einen guten Weg (ohne von jedem Modul den Quellcode zu studieren), um herauszufinden, ob das Modul für die entsprechenden Readings ein Bulk-Update nutzt? Oder alternativ, um herauszufinden, in welcher Reihenfolge die Readings gesetzt werden?

Anyway, ich bin momentan bei dieser Lösung als Attribut am Device:
define ku_thgr228n OREGON THGR228N_76_4
attr ku_thgr228n mqttPublish temperature:topic={"$base/$device"}\
temperature:expression={toJSON({"temperature"=>ReadingsVal($device, "temperature", undef), "humidity"=>ReadingsVal($device, "humidity", undef), "timestamp"=>::time_str2num(ReadingsTimestamp($device, "temperature", 0))})}

Also ich möchte temperature und humidity verschicken. Ich triggere nur auf temperature und hole mir dann im Trigger-Code die Reading-Vals von temperature und humidity per ReadingsVal. Außerdem noch den Timestamp von temperature.

Ergebnis sieht dann in MQTT so aus:
Topic: home/ku_thgr228n
{"humidity":44,"temperature":17.7,"timestamp":1735775068}

Seht ihr das auch alles so? Macht das Sinn? Kommentare oder Verbesserungsvorschläge? Danke euch!

Ähnliche Themen im Forum:
https://forum.fhem.de/index.php?topic=133675.0
https://forum.fhem.de/index.php?topic=114044.0

Beta-User

Da sich bisher keiner gemeldet hat: Du meinen Ausführungen in den zitierten Threads habe ich keine neuen Erkenntnisse, das was du geschreiben hast, paßt soweit auch zu meinem (möglicherweise unvollständigen) Verständnis...
Zitat von: vbs am 02 Januar 2025, 00:54:34Gibt es einen guten Weg (ohne von jedem Modul den Quellcode zu studieren), um herauszufinden, ob das Modul für die entsprechenden Readings ein Bulk-Update nutzt? Oder alternativ, um herauszufinden, in welcher Reihenfolge die Readings gesetzt werden?
Weiß nicht recht:
Man könnte per notify oä. die "changed"-Liste loggen, dann würde man ggf. sehen, was jeweils zusammen aktualisiert wird. Ob das im Ergebnis einfacher ist als das Studium der Readings+Quellcode-Schau sei dir überlassen.

Sowas wäre halt "generischer" und für normale User eventuell einfacher, da ohne Quellcode - verstehen muss man trotzdem, was eigentlich das zu lösende Problem ist, und ggf. muss man auch verstehen, welchen Einfluss gewisse Attribute am Device haben können...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

vbs

Was wäre, wenn man einfach in den Event-Monitor guckt und schaut, welches Reading dort als letztes auftaucht in der Gruppe? Dann kann es einem sogar egal sein, ob das Bulk war oder nicht.

Hab mir jetzt eine Hilfsfunktion gebaut zum Erzeugen des MQTT Body:
sub buildMqttBody($@) {
    my $device = shift;

    my %out;
    $out{"timestamp"} = ::time_str2num(ReadingsTimestamp($device, @_[0], 0));
    map { $out{$_} = ReadingsVal($device, "$_", undef) } @_;
    toJSON(\%out);
}

Nutze ich dann so:
humidity:topic={"$base/$device"}
humidity:expression={::buildMqttBody($device, "temperature", "humidity")}