Im Perl-Modus von DOIF gibt es ja die Möglichkeit Instanzvariablen zu verwenden, welche von Trigger zu Trigger erhalten bleiben.
Im Userreading habe ich es über den Umweg "setreading" versucht aber da erscheint im Log "'setreading xxx xxx called form userReadings is prohibited".
Gibt es eine vergleichbare Möglichkeit auch für Userreadings?
sleep 0.1; setreading Device Readingname Wert
Aber aufpassen: NICHT auf das Reading welches wieder das userReading triggert! -> "Schleife"! Und daher natürlich einen sehr engen Trigger beim userReading!
EDIT: eben wegen solcher Schleife ist es "verboten"... Was willst du denn eigentlich tun?
Gruß, Joachim
DOIF hat eigene Funktionen und Attribute dafür. Siehe:
https://fhem.de/commandref_DE.html#DOIF_DOIF_Readings
Ich hab einen Zisternenfüllstandssensor, den ich über HTTPMOD auslese um den Abstand zur Wasseroberfläche zu bekommen.
Leider liefert er zwischendurch mal komische Werte, also hab ich ein Reading angelegt, das den plausibelsten Wert enthält.
Ich schau nach, ob die Abweichung zum letzten Wert größer ist als 2% und wenn ja, dann gebe ich den alten Wert zurück und starte eine neue Abfrage.
Das funktioniert bereits super. Wenn sich FHEM aber mal, aus welchem Grund auch immer, aufhängt, wird das Reading nicht mehr upgedated, weil die Abweichung inzwischen oft größer als 2% ist.
Somit wollte ich eine neue Funktion einbauen: Wenn die Abweichung 10 mal hintereinander gleich groß ist, soll der Wert ins Userreading übernommen werden, obwohl er mehr als 2% abweicht.
Es scheitert am Counter, wie oft die Abweichung bereits gleich war, weil ich nicht weiß wie so ein Wert zwischen den Userreading-Events "am Leben" bleibt.
So funktionierts jedenfalls nicht:
$cwp = aktueller Wasserpegel, der gerade ausgelesen wurde,
$pwp = Plausibilisierter, aktuell gültiger Wasserpegel
Abstand_Wasserpegel_vorherigerWert {
OldReadingsVal("Zisternenfuellstand", "Abstand_Wasserpegel_extracted", "n/v");
},
Abstand_Wasserpegel {
my $cwp = ReadingsVal("Zisternenfuellstand", "Abstand_Wasserpegel_extracted", 0);
my $pwp = ReadingsVal("Zisternenfuellstand", "Abstand_Wasserpegel", 0);
my $abwcount = ReadingsVal("Zisternenfuellstand", "gleicheAbweichungAnz", 0);
my $pcwp = ReadingsVal("Zisternenfuellstand", "letzteAbweichung", 0);
($cwp) = $cwp =~ /(\d+)/; #extract number
($pwp) = $pwp =~ /(\d+)/; #extract number
my $diff = abs($pwp - $cwp);
my $pct_deviation = 100 / $cwp * $diff;
Log3 ("$name", 5, "$name: Now I have \$cwp=$cwp, \$pwp=$pwp, \$diff=$diff, \$pct_deviation=$pct_deviation");
if ($pct_deviation > 2) {
Log3 ("$name", 1, "$name: Abweichung mit $pct_deviation Prozent ist zu hoch. Übernehme vorherigen Wert und starte erneute Abfrage des Werts.");
fhem("set Zisternenfuellstand reread");
$abwcount++;
if (not $pcwp == $cwp) {
Log3 ("$name", 5, "$name: Abweichung unterscheidet sich von letzter Abweichung! Abweichungscounter wird zurückgesetzt!");
$abwcount = 0;
}
fhem("setreading Zisternenfuellstand gleicheAbweichungAnz $abwcount");
Log3 ("$name", 5, "$name: Gleiche Abweichung schon $abwcount mal!");
if ($abwcount >= 10) {
Log3 ("$name", 1, "$name: Abweichung war jetzt $abwcount mal gleich hoch. Somit nehme ich an, dass der Wert passt und übernehme ihn!");
$abwcount = 0;
return $cwp;
}
fhem("setreading Zisternenfuellstand letzteAbweichung $pcwp");
return $pwp;
}
return $cwp;
}
Ich versuch jetzt mal ein "sleep" davor...
sleep 0.1 vor dem setreading bringt nichts, da erscheint trotzdem die prohibited-Meldung im Log.
Im DOIF gibt es für Ausreißer eine Funktion, z. B.:
[Zisternenfuellstand:Abstand_Wasserpegel_extracted:med5]
siehe: https://fhem.de/commandref_DE.html#DOIF_Reading_Funktionen
Danke, übers DOIF wäre das sowieso kein Problem, ich würde es aber gerne direkt im Userreading lösen, damit ich nicht noch ein Device brauche.
Gibts dafür auch eine Möglichkeit?
Wie geschrieben sehe ich keinen Trigger beim userReadings.
Ob damit das "prohibited" weg geht weiß ich nicht.
Auslagern des userReadings-Codes in eine myUtils und dort mit globaler Variable?
Gruß, Joachim