Messages Filtern

Begonnen von rogerknop, 07 Februar 2022, 19:05:59

Vorheriges Thema - Nächstes Thema

rogerknop

Hallo,

ich wollte MQTT messages filtern und habe folgendes readingList angelegt:

mqtt:tele/stromzaehler/STATE:.* { my %p=json2nameValue($EVENT,'',$JSONMAP);; my %m=("SSId"=>"ssid","Signal"=>"rssi");; my %c=();; foreach my $k (keys %p) { Log 3, $k;; next if (!defined $m{$k});; $c{$m{$k}}=$p{$k};; } return %c;;}


Leider tauchen im Log dann folgende Fehler auf:

PERL WARNING: Reference found where even-sized list expected at (eval 22318) line 1.
2022.02.07 19:01:28 3: eval: my $CID=   $evalSpecials->{'%CID'};my $DEVICETOPIC=   $evalSpecials->{'%DEVICETOPIC'};my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $JSONMAP=   $evalSpecials->{'%JSONMAP'};my $NAME=   $evalSpecials->{'%NAME'};my $TOPIC=   $evalSpecials->{'%TOPIC'};{ my %p=json2nameValue($EVENT,'',$JSONMAP);;;; my %m=("SSId"=>"ssid","Signal"=>"rssi");;;; my %c=();;;; foreach my $k (keys %p) { Log 3, $k;;;; next if (!defined $m{$k});;;; $c{$m{$k}}=$p{$k};;;; } return %c;;;;}


Ich habe auch schon versucht am Ende eine Referenz auf den Hash mit return \%c;; zurückzuliefern, aber ohne Erfolg.

Hat jemand eine Idee, wo das Problem liegt?

Danke & Grüße,
Roger

TomLee

#1
Hallo,

auf die Gefahr hin das ich es total missverstehe, du willst doch nur die zwei Schlüssel umbenennen und nicht filtern, oder ?

Warum nicht mit dem Attribut jsonMap oder klappt da was nicht, habs selbst nicht nachvollzogen ?


edit:

Da passt doch schon was nicht:
my %p=json2nameValue($EVENT,'',$JSONMAP)

j2nv gibt ne Referenz zurück, keinen Hash ...

edit2:

Also ich dachte ich hätte wenigstens etwas verstanden, das man so die Referenz von j2nv angibt:

my $p=json2nameValue($EVENT,'',$JSONMAP)

Und entweder so:
foreach my $k ( keys %{$p})
oder so:
foreach $k ( keys % $p )

in der Schleife verweisen kann, aber Pustekuchen, da gibts gleich eine Meldung beim definieren:
Global symbol "%p" requires explicit package name (did you forget to declare "my %p"?) at (eval 438250) line 1.

betateilchen

@rogerknop: was willst Du eigentlich als Ergebnis erreichen?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rogerknop

Hallo,
ich habe eine Liste von verschachtelten Werten in der Message und möchte nur 2 rausziehen und auch die Readings gerne anders benennen.
Daher habe ich das Perl Coding eingebaut, da ich sonst keine Lösung gefunden habe.
Das Perl Coding ist eigentlich separat getestet. In dem m hash steht mein Mapping der Felder, die ich gerne hätte.
Grüße, Roger

Beta-User

Zum einen: json2nameValue gibt - soweit ich mich entsinne - eine Referenz auf einen Hash zurück.
Zum anderen: Wenn du nur bestimmte Werte haben willst, warum greifst du die dann nicht direkt raus?

Ungetestet:
tele/stromzaehler/STATE:.* { my $p=json2nameValue($EVENT,'',$JSONMAP);; my %m=( SSId=>"ssid",Signal=>"rssi");; my %c;; for my $k (keys %m) { $c{$m{$k}}=$p->{$k};; } return \%c;;}

Weitere Anmerkung: eine ClientID "mqtt" ist überdenkenswert... Da das Tasmota zu sein scheint: einfach die empfohlenen Defaults lassen, dann ist die Verwechslungsgefahr gebannt...
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

Alternativ: tele/stromzaehler/STATE:.* { json2nameValue($EVENT,'',$JSONMAP, "^(ssid|rssi)$") } und das jsonMap Attribut mit SSId:ssid Signal:rssi erweitern.
Auch ungetestet, mangels Input

TomLee

So denk ich sieht der JSON aus:
{"Time":"2022-02-09T10:52:45","Uptime":"0T00:05:09","UptimeSec":309,"Heap":22,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"on","POWER2":"off","POWER3":"off","POWER4":"off","Wifi":{"AP":1,"SSId":"Bla","BSSId":"BC:05:43:CA:4F:FG","Channel":13,"RSSI":48,"Signal":-76,"LinkCount":1,"Downtime":"0T00:00:03"}}


Damit zu beschäftigen hab ich heute keine Zeit.

rogerknop

So nun hab ich das alles mal konsolidiert und sogar 2 Lösungen parat :)

1. Meine Lösung funktioniert auch, aber ich hab eine falsche Annahme getroffen, dass json2nameValue einen Hash zurückliefert und nicht eine Referenz. Doof von mir. So gehts:

mqtt:tele/stromzaehler/STATE:.* { my %p=%{json2nameValue($EVENT,'',$JSONMAP)};; my %m=("Wifi_SSId"=>"ssid","Wifi_Signal"=>"rssi");; my %c=();; foreach my $k (keys %p) { next if (!defined $m{$k});; $c{$m{$k}}=$p{$k};; } return \%c;;}


2. Die Idee aber JSONMAP richtig zu nutzen hat mich dann aber dazu bewegt dies noch weiter zu prüfen. Die Signatur von json2nameValue ist: ($in, $prefix, $map, $filter, $negFilter). Was hierbei wichtig ist, dass der Filter erst nach dem Mapping angewendet wird! Somit erst den hash mit den Mappings angeben und dann die regexp für den Filter mit Bezug auf die umbenannten Felder. Ausserdem werden verschachtelte JSON Stukturen flachgeklopft mit dem Strukturnamen als Präfix (z.B. SSId in Unterstruktur Wifi wird zu Wifi_SSId). Also readingList sieht dann so aus:

mqtt:tele/stromzaehler/STATE:.* { json2nameValue($EVENT,"",{"Wifi_SSId"=>"ssid","Wifi_Signal"=>"rssi"},".*(ssid|rssi).*");; }


Danke nochmal für die Hilfe!

Grüße, Roger