Hallo,
ich möchte alle Readings eines Gerätes als Attribute in einer JSON Nachricht auf meinem MQTT Server veröffentlichen.
Hierzu habe ich mir ein notify angelegt, welches grundsätzlich auch funktioniert (d.h. die JSON Nachricht korrekt zusammenbaut und auf dem MQTT Server veröffentlicht.
defmod not_DB23 notify FriedrStr.* set MQTT_Broker publish fhem/DB23/attributes {(\
my $d="$NAME";;;;\
my $hash = $defs{$d};;;;\
my $readings = $hash->{READINGS};;;;\
my $message="{ \"connection\": \"Friedr\",";;;;\
foreach my $a ( keys %{$readings} ) {\
if ( substr($a, -1, 1) == 3 ) {\
my $b = $a;;;;\
chop($b);;;; chop($b);;;;\
$message .= toJSON($b)." : ".toJSON(ReadingsVal($d,$a,"error"))." ," \
}\
};;;;\
chop($message);;;;
{
"connection": "Friedr",
"travel_note_text": "Aktuelle Informationen liegen vor",
"travel_note_error": "none",
"plan_arrival": "09:57",
"plan_arrival_delay": "0",
"travel_note": "achtung",
"travel_destination": "Berlin Friedrichstraße (S) - Gl. 12",
"travel_price": "VBB ab 3,60 EUR ",
"plan_departure_delay": 1,
"plan_connection": "RE, S",
"plan_travel_change": "1",
"travel_vehicle_nr": "RE 92408 | S 2",
"travel_departure": "Rangsdorf - Gl. 2\n\nBlankenfelde(Teltow-Fläming)\n\n\n\nFußweg\n3 Min.\n\n\n\nBlankenfelde (S)\nab 09:20 Gl. 3",
"plan_departure": "09:04",
"plan_travel_duration": "0:52"
}
Allerdings erhalte ich jedesmal, wenn das Notify ausgeführt wird, pro Notify zig (~ 100) Einträge
2020.09.04 08:57:35 1: PERL WARNING: Argument "e" isn't numeric in numeric eq (==) at (eval 3752) line 7.
2020.09.04 08:57:35 1: PERL WARNING: Argument "r" isn't numeric in numeric eq (==) at (eval 3752) line 7.
2020.09.04 08:57:35 1: PERL WARNING: Argument "e" isn't numeric in numeric eq (==) at (eval 3753) line 7.
2020.09.04 08:57:35 1: PERL WARNING: Argument "r" isn't numeric in numeric eq (==) at (eval 3753) line 7.
in meinem Logfile und gefühlt deutliche Performanceeinbussen / Hänger im System.
Kann mir jemand einen Tipp geben, was an meinem Code falsch ist?
Hat ggfs jemand eine alternative Lösung, die JSON Nachricht mit den Readings zusammen zu bauen?
Danke & viele Grüße
Thorsten
Der Zahlenvergleich in perl (==) beschwert sich, wenn einer der Argumente kein Zahl ist.
=> Nicht jeder Reading(name) der ausloesenden Eintraege endet in einem Ziffer.
Das klingt logisch. Hätte ich wahrscheinlich eher im Perl-Anfängerforum posten sollen.
Danke @rudolfkoenig für den Hinweis.
Hi,
sorry, dass ich jetzt diesen alten Thread wieder öffne, aber ich habe leider nichts passenderes im Forum gefunden aber das ist genau das was ich gesucht habe.
Ich nutze MAX! Heizthermostate und möchte für jeden Thermostat einen JSON formatierte Attributliste auf MQTT publishen.
Was ich bis jetzt erreicht habe:
DMHAVE
define myBroker MQTT2_CLIENT <IP>:1883
setuuid myBroker 662bfcba-f33f-c92d-b418-5c9bc23c90828bcc
attr myBroker alias MQTT Broker
attr myBroker clientId fhem
attr myBroker devStateIcon .*active:none:disconnect .*disconnected:none:connect
attr myBroker icon mqtt
attr myBroker ignoreRegexp ignoreRegexp cmnd/[^:"]+:|homeassistant/[^:"]+/config:|shellies/[^:"]+/command:|zigbee2mqtt/[^/]+/set:|milight/0x[0-9a-fA-F]{1,4}/.*/[0-8]:|tasmota/discovery/|ems-esp/|fhem/
attr myBroker keepaliveTimeout 60
attr myBroker msgAfterConnect -r fhem/connection/status connected
attr myBroker msgBeforeDisconnect -r fhem/connection/status disconnected
attr myBroker qosMaxQueueLength 100
attr myBroker room MQTT
attr myBroker username <USERNAME>
define mqttBridge MQTT_GENERIC_BRIDGE mqtt room=MAX
setuuid mqttBridge 662c08d5-f33f-c92d-bf5a-bf944ab5ecbb36a9
attr mqttBridge alias MQTT generic bridge
attr mqttBridge globalDefaults sub:qos=2 pub:qos=0 retain=1 base={"fhem/$device"}
attr mqttBridge globalPublish state|desiredTemperature|temperature|valveposition|battery|mode:topic={"$base"} state|desiredTemperature|temperature|valveposition|battery|mode:expression={toJSON({$name=>$value})}
attr mqttBridge icon mqtt_bridge_2
attr mqttBridge room MQTT
attr mqttBridge stateFormat in: incoming-count out: outgoing-count devices: device-count
attr mqttBridge verbose 5
Dadurch bekomme ich sowas
{"state":"16.0"}
{"desiredTemperature":"16.0"}
{"battery":"ok"}
{"mode":"manual"}
aber eigentlich möchte ich sowas:
{
"state":"16.0"
"desiredTemperature":"16.0"
"battery":"ok"
"mode":"manual"
}
Das ganze sieht ja eigentlich genau nach dem aus was hier geteilt wurden,
aber ich verstehe das nicht mit dem notify.
Grüße
Tamas
ZitatDas ganze sieht ja eigentlich genau nach dem aus was hier geteilt wurden,
Vielleicht auf dem ersten Blick.
Das notify oben erstellt beim Eintreffen eines beliebigen Events fuer FriedrStr.* ein JSON fuer eine Reihe von Readings per Hand(*), und versendet das Ergebnis auf einmal per publish.
(*) Statt toJSON(X) haette man im Perl-Skript oben auch "X" schreiben koennen.
Im zweiten Fall versendet MQTT_GENERIC_BRIDGE (MGB) fuer jedes der aufgefuehrten Events jeweils ein JSON (nur) mit dem eingetroffenen Event.
Soweit ich weiss, laesst sich das Gewuenschte nur mit Perl-Code bewerkstelligen.
Ich wuerde in 99_myUtils.pm Folgendes einbauen:
sub
readings2json($@)
{
my $in = $defs{shift()}{READINGS};
my %out;
map { $out{$_} = $in->{$_}{VAL} } @_;
return toJSON(\%out);
}
Aufruf mit readings2json($device, "state","desiredTemperature","battery","mode")
Vielen Dank für die schnelle Hilfe, dass war genau das was ich gesucht habe.
Nach dem ich verstanden habe wie das mit dem 99_myUtils.pm so funktioniert, klappt das genau so wie ich es mir gewünscht habe.
Zur Vollständigkeit hier mein 99_myUtils.pm
##############################################
## $Id: myUtilsTemplate.pm 21509 2020-03-25 11:20:51Z rudolfkoenig $
##
## Save this file as 99_myUtils.pm, and create your own functions in the new
## file. They are then available in every Perl expression.
package main;
use strict;
use warnings;
sub
myUtils_Initialize($$)
{
my ($hash) = @_;
}
sub
readings2json($@)
{
my $in = $defs{shift()}{READINGS};
my %out;
map { $out{$_} = $in->{$_}{VAL} } @_;
return toJSON(\%out);
}
1;
Beim Aufruf sieht dass dann so aus
attr mqttBridge globalPublish state|desiredTemperature|temperature|valveposition|battery|mode:topic={"$base"} state|desiredTemperature|temperature|valveposition|battery|mode:expression={main::readings2json($device, "state","desiredTemperature","temperature","valveposition","battery","mode")}
Zitat von: tbk am 05 Mai 2024, 21:29:59klappt das genau so wie gewünscht
Du solltest dir ggf. mal ansehen, ob die Häufigkeit des Sendens auch so klappt wie gedacht ;) .
Falls es zu viel ist: ggf. einfach nur (vermeintlich) das letzte durch das bulk-update (nehme ich zumindest an, dass die Readings per bulk befüllt werden) aktualisierte Reading "versenden" (also eigentlich: als trigger für den Code innerhalb MGB verwenden).
PS @tbk: Da dein Problem zwar ähnlich ist, aber doch anders und der eigentliche TE sein Problem gelöst hatte (aber nicht als solches markiert...), wäre es m.E. besser gewesen, einen neuen Thread aufzumachen und ggf. hierauf zu verweisen.