Reading ignorieren falls leer

Begonnen von tomix, 23 Juli 2022, 01:31:14

Vorheriges Thema - Nächstes Thema

tomix

Hallo zusammen

Ich habe ein «Digitizer - AI on the edge» (https://github.com/jomjol/AI-on-the-edge-device/wiki)

Kann die Zahl nicht abgelesen werden, wird via MQTT ein leeres Reading gesendet. Ich habe nun mal versucht dieses nachträglich rauszufiltern. Mit folgendem neuen userReadings scheint es zu klappen:
attr MQTT2_watermeter userReadings ..., zaehlerstand_korr:value.* { ReadingsVal("MQTT2_watermeter","value",0)>0 ? ReadingsVal("MQTT2_watermeter","value",0) : ReadingsVal("MQTT2_watermeter","zaehlerstand_korr",0) }


Mir wäre aber lieber es würde gar nichts passieren, wenn nichts gesendet wird (also auch nicht, dass value auf NULL gesetzt wird).

RAW Definition

defmod MQTT2_watermeter MQTT2_DEVICE watermeter
attr MQTT2_watermeter IODev MQTT2_FHEM_Server
attr MQTT2_watermeter alias Wasseruhr
attr MQTT2_watermeter devStateIcon {my $onl = ReadingsVal($name,"error",0) eq "" ? "rot" : "gruen";; $onl = FW_makeImage("10px-kreis-$onl");; my $ip = 'wasseruhr.fritz.box';;\
qq(<div><a href="http://$ip" target="_blank">$onl</a>). \
  "</div><div>" \
    . sprintf(\
    "Zählerstand korrigiert: %.0f Liter, %.3f m3",\
    ReadingsVal($name,"zaehlerstand_korr",0),\
    ReadingsVal($name,"zaehlerstand_korr",0)/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "Zählerstand: %.0f Liter, %.3f m3",\
    ReadingsVal($name,"value",0),\
    ReadingsVal($name,"value",0)/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "Tagesverbrauch: %.0f Liter, %.3f m3",\
    ReadingsVal($name,"value",0) - ReadingsVal($name,"tageswert",0),\
    (ReadingsVal($name,"value",0) - ReadingsVal($name,"tageswert",0))/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "(Gestern: %.0f Liter, %.3f m3)",\
    ReadingsVal($name,"diff_tageswert",0),\
    ReadingsVal($name,"diff_tageswert",0)/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "Error: %s",\
    ReadingsVal($name,"error",0),\
    )\
    . "</div>"\
  }
attr MQTT2_watermeter icon sani_water_tap
attr MQTT2_watermeter readingList watermeter:wasserzaehler:.* zaehlerstand\
watermeter:wasserzaehler/error:.* error\
watermeter:wasserzaehler/connection:.* connection\
watermeter:wasserzaehler/uptime:.* uptime\
watermeter:wasserzaehler/freeMem:.* freeMem\
watermeter:wasserzaehler/wifiRSSI:.* wifiRSSI\
watermeter:wasserzaehler/main/value:.* value\
watermeter:wasserzaehler/main/error:.* error\
watermeter:wasserzaehler/main/rate:.* rate\
watermeter:wasserzaehler/main/raw:.* raw\
watermeter:wasserzaehler/main/timestamp:.* timestamp\
watermeter:wasserzaehler/main/json:.* { json2nameValue($EVENT) }\
watermeter:wasserzaehler/main/changeabsolut:.* changeabsolut
attr MQTT2_watermeter room Haus,MQTT2_DEVICE
attr MQTT2_watermeter userReadings d_dt_value:value.* differential { ReadingsVal("MQTT2_watermeter","value",0)*60 }, diff_value:value.* difference { ReadingsVal("MQTT2_watermeter","value",0) }, diff_tageswert:tageswert.* difference { ReadingsVal("MQTT2_watermeter","tageswert",0) }, zaehlerstand_korr:value.* { ReadingsVal("MQTT2_watermeter","value",0)>0 ? ReadingsVal("MQTT2_watermeter","value",0) : ReadingsVal("MQTT2_watermeter","zaehlerstand_korr",0) }


Gruss
tomix

Nobbynews

#1
Zitat von: tomix am 23 Juli 2022, 01:31:14
Ich habe ein «Digitizer - AI on the edge» (https://github.com/jomjol/AI-on-the-edge-device/wiki)
Bei der Firmware 10.5.2 kann ich dieses Verhalten nicht bestätigen.
In der config habe ich "ErrorMessages" aktiviert und auf "true" stehen.
Hier mal ein Logauszug bei einem Fehler:
.2022-07-21T09:13:24: task_autodoFlow - next round - Round #31209
2022-07-21T09:13:24: FlowControll.doFlow - ClassFlowMakeImage
2022-07-21T09:13:32: FlowControll.doFlow - ClassFlowAlignment
2022-07-21T09:13:47: FlowControll.doFlow - ClassFlowCNNGeneral
2022-07-21T09:14:01: FlowControll.doFlow - ClassFlowCNNGeneral
2022-07-21T09:14:11: FlowControll.doFlow - ClassFlowPostProcessing
2022-07-21T09:14:11: FlowControll.doFlow - ClassFlowMQTT
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=62014, wasserzaehler/connection, connected
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=34049, wasserzaehler/uptime, 7490450
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=6465, wasserzaehler/freeMem, 3064963
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=56866, wasserzaehler/wifiRSSI, -70
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=41641, wasserzaehler/main/error, Rate too high - Read: 32.9116 - Pre: 732.9016
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=29517, wasserzaehler/main/raw, .9116
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=59924, wasserzaehler/main/timestamp, 2022-07-21T09:09:32
2022-07-21T09:14:11: sent publish successful in MQTTPublish, msg_id=13843, wasserzaehler/main/json, {"value":"","raw":".9116","error":"Rate too high - Read: 32.9116 - Pre: 732.9016","rate":"","timestamp":"2022-07-21T09:09:32"}
2022-07-21T09:14:11: task_autodoFlow - round done 


Nur im Json steht ein leeres "value", aber Json werte ich nicht aus.
Deshalb habe ich den Eintrag
wasser:wasserzaehler/main/json:.* { json2nameValue($EVENT) }
aus dem Attribut readingList gelöscht.
Das sieht also so aus:
attr MQTT2_wasser readingList wasser:wasserzaehler/connection:.* connection\
wasser:wasserzaehler/uptime:.* uptime\
wasser:wasserzaehler/freeMem:.* freeMem\
wasser:wasserzaehler/main/error:.* error\
wasser:wasserzaehler/main/raw:.* raw\
wasser:wasserzaehler/main/value:.* value\
wasser:wasserzaehler/main/rate:.* rate\
wasser:wasserzaehler/main/timestamp:.* timestamp\
wasser:wasserzaehler/wifiRSSI:.* wifiRSSI 


Und ganz wichtig ist dann noch:
attr MQTT2_wasser autocreate 0

Beta-User

Wenn man den JSON vorab bereinigt, geht das schon - dann kann man den Rest auch beerdigen (=> weniger Events). Auszug aus dem readingList-Attribut:

watermeter/main/(error|rate|raw|timestamp|value):.* {}
watermeter/main/json:.* { my $rets = json2nameValue($EVENT,'',$JSONMAP);; my %cleaned = map { $_,$rets->{$_} } grep { $rets->{$_} ne '' } keys %{$rets}; return \%cleaned }
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

Nobbynews

#3
Zitat von: Beta-User am 23 Juli 2022, 07:23:53
Wenn man den JSON vorab bereinigt, geht das schon - dann kann man den Rest auch beerdigen (=> weniger Events).
Genial! Funktioniert super.
Wie lange muss man sich mit Linux, Perl und FHEM beschäftigt habe, um so etwas zu beherrschen??
Danke.

Beta-User

 :)
Schön, dass das Anklang findet.

Hier mal das (fast) komplette (aktualisierte) RAW-listing:
defmod Wasserzaehler MQTT2_DEVICE wasser
attr Wasserzaehler icon measure_water_meter
attr Wasserzaehler jsonMap value:readout timestamp:0
attr Wasserzaehler readingList watermeter/connection:.* connection\
watermeter/uptime:.* uptime\
watermeter/freeMem:.* freeMem\
watermeter/main/(error|rate|raw|timestamp|value):.* {}\
watermeter/main/json:.* { my $rets = json2nameValue($EVENT,'',$JSONMAP);; my %cleaned = map { $_,$rets->{$_} } grep { $rets->{$_} ne '' } keys %{$rets};; return \%cleaned }\
watermeter/wifiRSSI:.* rssi\
watermeter/main/changeabsolut:.* changeabsolut
attr Wasserzaehler stateFormat readout m²


Die "Säuberung" des Hashes aus json2nameValue() sind eigentlich nur "a few roots, replated" von Rudi... ;) Wiederfinden macht halt Freude, aber wenn man weiß, nach was man in der mqtt2.template-File suchen muss,  ist es eigentlich auch keine große Sache mehr 8) .
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

tomix

#5
Lese wohl das JSON-Reading aus.

Ich habe nun mal das Device umgeschrieben. Aktuell wird kein value mehr gesendet (erkennt aber auch nichts, da die erste Ziffer gerade durchdreht)

Im Moment sieht es so aus:

defmod MQTT2_watermeter MQTT2_DEVICE watermeter
attr MQTT2_watermeter IODev MQTT2_FHEM_Server
attr MQTT2_watermeter alias Wasseruhr
attr MQTT2_watermeter autocreate 0
attr MQTT2_watermeter comment icon sani_water_tap
attr MQTT2_watermeter devStateIcon {my $onl = ReadingsVal($name,"error",0) eq "" ? "rot" : "gruen";; $onl = FW_makeImage("10px-kreis-$onl");; my $ip = 'wasseruhr.fritz.box';;\
qq(<div><a href="http://$ip" target="_blank">$onl</a>). \
  "</div><div>" \
    . sprintf(\
    "Zählerstand: %.0f Liter, %.3f m³",\
    ReadingsVal($name,"value",0),\
    ReadingsVal($name,"value",0)/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "Tagesverbrauch: %.0f Liter, %.3f m³",\
    ReadingsVal($name,"value",0) - ReadingsVal($name,"tageswert",0),\
    (ReadingsVal($name,"value",0) - ReadingsVal($name,"tageswert",0))/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "(Gestern: %.0f Liter, %.3f m3)",\
    ReadingsVal($name,"diff_tageswert",0),\
    ReadingsVal($name,"diff_tageswert",0)/1000,\
    )\
    . "<br />"\
    . sprintf(\
    "Error: %s",\
    ReadingsVal($name,"error",0),\
    )\
    . "</div>"\
  }
attr MQTT2_watermeter icon measure_water_meter
attr MQTT2_watermeter jsonMap value:readout timestamp:0
attr MQTT2_watermeter readingList watermeter/connection:.* connection\
watermeter/uptime:.* uptime\
watermeter/freeMem:.* freeMem\
watermeter/main/(error|rate|raw|timestamp|value):.* {}\
watermeter/main/json:.* { my $rets = json2nameValue($EVENT,'',$JSONMAP);; my %cleaned = map { $_,$rets->{$_} } grep { $rets->{$_} ne '' } keys %{$rets};; return \%cleaned }\
watermeter/wifiRSSI:.* rssi\
watermeter/main/changeabsolut:.* changeabsolut
attr MQTT2_watermeter room Haus,MQTT2_DEVICE
attr MQTT2_watermeter stateFormat readout Liter
attr MQTT2_watermeter userReadings d_dt_value differential { ReadingsVal("MQTT2_watermeter","value",0)*60 }, diff_value difference { ReadingsVal("MQTT2_watermeter","value",0) }, diff_tageswert difference { ReadingsVal("MQTT2_watermeter","tageswert",0) }


Zitat von: Beta-User am 23 Juli 2022, 12:02:02
attr Wasserzaehler stateFormat readout m²[/code]
? m² → m³

Gruss
tomix

tomix

Ich kapier nicht ganz was da wie gesendet wird. Das Webfrontend (jomjol - AI on the edge) sagt mir folgendes:
Value:
{leeres Feld}
Previous Value:
2006449
Raw Value:
00006449
Error:
Neg. Rate - Read: - Raw: 00006449 - Pre: 2006449
Last Page Refresh:23:01:54
Status: Flow finished (22:59:47)

Somit hätte ich ein value von 2006449 erwartet in FHEM. FHEM meint:

setstate MQTT2_watermeter 2006449 Liter
setstate MQTT2_watermeter 2022-07-27 23:19:51 IODev MQTT2_FHEM_Server
setstate MQTT2_watermeter 2022-07-27 23:19:49 changeabsolut 0
setstate MQTT2_watermeter 2022-07-27 23:19:49 connection connected
setstate MQTT2_watermeter 2022-07-27 23:14:53 d_dt_value 0
setstate MQTT2_watermeter 2022-07-27 23:19:49 diff_tageswert 0
setstate MQTT2_watermeter 2022-07-27 23:19:49 diff_value 0
setstate MQTT2_watermeter 2022-07-27 23:19:49 error Neg. Rate - Read:  - Raw: 00006449 - Pre: 2006449
setstate MQTT2_watermeter 2022-07-27 23:19:49 freeMem 3133343
setstate MQTT2_watermeter 2022-07-22 22:53:51 json2nameValueErrorText error parsing 'N002647,"raw":"0N002647","error":"","rate":"","timestamp":""'
setstate MQTT2_watermeter 2022-07-22 22:53:51 json2nameValueInput {"value":0N002647,"raw":"0N002647","error":"","rate":"","timestamp":""}
setstate MQTT2_watermeter 2022-07-27 22:54:48 rate 0.000000
setstate MQTT2_watermeter 2022-07-27 23:19:49 raw 00006449
setstate MQTT2_watermeter 2022-07-27 22:54:48 readout 2006449
setstate MQTT2_watermeter 2022-07-27 23:19:49 rssi -46
setstate MQTT2_watermeter 2022-07-26 23:59:50 tageswert 2004805
setstate MQTT2_watermeter 2022-07-25 23:33:33 timestamp 2022-07-25T21:02:50
setstate MQTT2_watermeter 2022-07-27 23:19:49 uptime 55853
setstate MQTT2_watermeter 2022-07-26 00:00:18 value 2004805


Warum stimmt state, aha readout wird verwendet. Wird value evtl. nur neu gesetzt, falls alle Ziffern erkannt werden?

Alles auf readout umschreiben scheint zu funktionieren? Kann mir die Zeile jemand erklären:

attr MQTT2_watermeter jsonMap value:readout timestamp:0

value wird nach readout umgeschrieben? timestamp nach ???

Wie kann ich state nutzen? Also zum Beispiel hier:
sprintf(\
    "Zählerstand: %.0f Liter, %.3f m³",\
    ReadingsVal($name,"readout",0),\
    ReadingsVal($name,"readout",0)/1000,\
    )

Logischer wäre "Zählerstand: %s Liter, %.3f m³", {STATE}, ReadingsVal($name,"readout",0)/1000

Gruss
tomix

Beta-User

Sorry, dass ich mein raw gepostet habe...

Also: "readout" war früher mal das "Basisreading", wenn ich heute damit anfangen  würde, würde ich das auf "value" lassen oder nach "sum" oder so mappen. Ist jetzt (bei mir) halt so...
"timestamp" braucht keiner als separates Reading, deswegen wird es verworfen (siehe commandref zu m2d); wenn, müßte man das beim readingsUpdate mit verarbeiten; das geht hier aber nicht so einfach, und es ist auch nicht so wichtig, wenn da ein paar "Sekunden" Versatz sind zwischen Messung auf dem ESP und der Auswertung in FHEM.

stateFormat (worauf bezieht sich die Frage? eher nicht state? sondern STATE?) kann jeder machen, wie er lustig ist, zwischenzeitlich habe ich auch die Einheit angepaßt; wenn da die "aktuelle Veränderung" rein soll, muss man halt "rate" mit heranziehen, m³ in l umzurechnen (?) ist dagegen m.E. nicht so informativ.

PS: Wenn jemand einen aktuellen "allgemein vermittelbaren" Stand als attrTemplate bereitstellt, checke ich das ein...
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