UserReadings Modifier Bug?

Begonnen von scuba, 29 Januar 2018, 11:36:11

Vorheriges Thema - Nächstes Thema

scuba

Hallo,

Ich bin bei der Inbetriebnahme meines Wasser (und Strom) Sensors auf ein seltsames Verhalten des "userReading modifiers" monotonic gestoßen.
Hierzu hats schon mal vor Jahren einen Eintrag gegeben der aber anscheinend unbeantortet geblieben ist. https://forum.fhem.de/index.php/topic,20082.0.html

Die Ursache und einen Workaround hab ich gefunden. Vermute aber, dass das Verhalten eher ein Bug ist und nicht so sein sollte.
Vielleicht kann da ein Entwickler einen Blick drüber werfen.

Problem
Mein Sensor liefert seinen Wert ans Reading "pulses".
Mittels  "total:pulses.* monotonic {ReadingsVal($name,"pulses",0)} wird dieser Wert im Reading"total" aufsummiert und überlebt somit auch einen Neustart meines Sensors (pulses werden hierbei auf 0 gesetzt).

Nach einem Neustart von Fhem kommt es nun zu dem Verhalten ,dass das Reading "total" nicht korrekt weitersummiert wird  bzw. Werte verloren gehen.

Ursache:

Auszug aus fhem.pl

           elsif($modifier eq "monotonic") {
           $oldvalue = $value if( !defined($oldvalue) );
           $result = ReadingsVal($name,$reading,$value);
           $result += $value - $oldvalue if( $value > $oldvalue );
           }

Der Modifier "monotonic" benötigt für seine Berechnung den zuletzt gespeicherten Wert vom Reading "pulses" in der Variable $oldvalue .
Bei Einem Neustart (shutdown restart)von FHEM ist diese Variable allerdings leer(!!!). Erst bei der nächsten Wertänderung beim nächsten Update des Readings ist sie wieder befüllt und ab da an wird auch wieder korrekt weitergerechnet.
Sendet der Sensor nach dem Neustart von FHEM einen neuen Wert geht dieser in der Kalkulation verloren.

Beispiel:

[u]Nach neustart: [/u]

Letzter Wert ($oldvalue) =  NULL [Da nach FHEM Neustart nicht befüllt]
Neuer Wert  ($value) = 100
Reading total (ReadingsVal(...))= 99

$oldvalue = 100 if( !defined($oldvalue) ); // Ergebnis=>$oldvalue = 100; Bedingung erfüllt
$result = 99  // Wert von Reading "total"
$result += 100 - 100 if( $100 > $100 ); // Ergbenis => 0; Bedingung nicht erfüllt
// $result = 99 -> Ergebnis wird auf Reading "total" geschrieben

----------------------------------------------------------

[u]nächster Durchlauf:[/u]

Letzter Wert ($oldvalue) =  100
Neuer Wert  ($value) = 101
Reading total (ReadingsVal(...))= 99

$oldvalue = 101 if( !defined($oldvalue) ); // Ergebnis=>$oldvalue = 100 ; Bedingung nicht erfüllt
$result = 99  // Wert von Reading "total"
$result += 101 - 100 if( $101 > $100 ); // Ergebnis => 1 ; Bedingung erfüllt
// $result = 100 -> Ergebnis wird auf Reading "total" geschrieben 

// Somit ist ein Wert verloren gegangen


Workaround

$oldvalue wird ,soweit ich das verstanden habe, nur befüllt, wenn sich der Wert des Readings ändert.
Ein Versuch nach einem Neustart ein "setreading" mit dem ursprünglichen Wert abzusetzen war somit erfolglos.

Attribut "event-on-update-reading" setzen.

Folgenden Workaround führe ich nun mittels DOIF nach einem Neustart durch:
- Wert von "pulses" um 1 subtrahieren // Wert hat sich somit geändert und die Variable $oldvalue ist wieder befüllt.
- Wert von total um 1 subtrahieren // "pulses" wird im nächsten schritt um 1 erhöht. "total" wird dann automatisch miterhöht und steht wieder am Originalwert
- Wert von "pulses um 1 erhöhen" //ursprünglicher Zustand wieder hergestellt. Die kummulierung wird ohne Werteverlust weitergeführt.

- Wert von "pulses" updaten // mit unverändertem Wert beschreiben und die Variable $oldvalue ist wieder befüllt.


define init_Wasserzaehler DOIF ([global:"INITIALIZED"]) {fhem "setreading mqtt_Wasserzaehler pulses ".int(ReadingsVal("mqtt_Wasserzaehler","pulses",0)-1);fhem "setreading mqtt_Wasserzaehler total ".int(ReadingsVal("mqtt_Wasserzaehler","total",0)-1);fhem "setreading mqtt_Wasserzaehler pulses ".int(ReadingsVal("mqtt_Wasserzaehler","pulses",0)+1);}




Wenn ich das richtig gesehen habe müsste  das Verhalten alle Modifier von userReadings betreffen.
Hab ich was grundlegendes übersehen was meinen Workaround sowieso obsolet macht?




scuba

#1
... Eine Sache hab ich tatsächlich übersehen:

mit dem Attribut "event-on-update-reading" wird $oldvalue auch bei einem Update des Readings (kein neuer Wert) gefüllt.
Somit entfällt de Kopfstand mit Subtrahieren und Addieren...

Neues doif mit reinem Update:

define init_Wasserzaehler DOIF ([global:"INITIALIZED"]) (setreading mqtt_Wasserzaehler pulses [mqtt_Wasserzaehler:pulses])


Würde mein Sensor also nach einem FHEM Neustart den Wert unverändert updatet, kommt es auch ohne Reinitialisierung zu keinem Datenverlust.
Nichtsdestotrotz benötige ich das DOIF da ich dies nicht garantieren kann.