Hallo,
ich verwende ein DOIF um mir den Status meine Waschmaschine zu überwachen und nach Beendigung über Telegram eine Meldung mit den Verbrauchswerten auszugeben.
Hierfür werden innerhalb eines DOIF-Zweiges berechnete Werte in Dummy-Readings geschrieben, die dann Ausgegeben werden sollen.
Für mich sieht es so aus, als ob die Readings nicht zur Laufzeit aktualisiert werden, da die berechneten Werte (die nach Beendigung des DOIFs in den Readings stehen) nicht mit denen übereinstimmen, welche durch den Telegrammbot übermittelt werden.
Falls das so ist, wie kann ich dafür sorgen, dass zur Laufzeit eine Aktualisierung der Werte erfolgt?
defmod ActWama DOIF (([FritzStecker:state] eq "off") or (([FritzStecker:power:d] == 0) and ([dmyWama:myWamaState] eq "on")))\
(attr FritzBox polltime 120;;\
deleteattr FritzStecker event-on-update-reading;;\
setreading dmyWama myWamaActive 0;;\
setreading dmyWama myWamaState off;;\
)\
DOELSEIF (([FritzStecker:state] eq "on") and ([FritzStecker:power:d] > 4))\
(attr FritzBox1 polltime 30;;\
attr FritzStecker event-on-update-reading .*;;\
setreading dmyWama myWamaActive 1;;\
setreading dmyWama myWamaState on;;\
setreading dmyWama myEnergyStart [FritzStecker:energy:d];;\
setreading dmyWama myWaterStart [Wasserzaehler:count:d];;\
)\
DOELSEIF (([FritzStecker:state] eq "on") and ([FritzStecker:power:d] < 3.65) and ([dmyWama:myWamaState] eq "on") and ([dmyWama:myWamaActive] eq "1"))\
(setreading dmyWama myWamaActive 0;;\
)\
DOELSEIF (([FritzStecker:state] eq "on") and ([FritzStecker:power:d] < 3.65) and ([dmyWama:myWamaState] eq "on") and ([dmyWama:myWamaActive] eq "0"))\
(setreading dmyWama myWamaState off;;\
setreading dmyWama myEnergyStop [FritzStecker:energy:d];;\
setreading dmyWama myWaterStop [Wasserzaehler:count:d];;\
setreading dmyWama myEnergy {([dmyWama:myEnergyStop:d]-[dmyWama:myEnergyStart:d])};;\
setreading dmyWama myWater {([dmyWama:myWaterStop:d]-[dmyWama:myWaterStart:d])};;\
sleep 0.1;;\
set fhem_bot message @999999999 Wäsche fertig \n Verbrauch Strom [dmyWama:myEnergy] kWh \n Verbrauch Wasser [dmyWama:myWater] Liter;;\
)
Danke und viele Grüße
Hi,
der Eventmonitor würde Dir helfen zu verstehen was da genau passiert.
Mal als Ansatz zum nachdenken:
Du konfigurierst die Events innerhalb des DOIFs um - arbeitest aber im gleichen DOIF mit ihnen. Was da genau passiert? Kann eventuell niemand vorher sagen. Man sieht ja auch nicht was sonst an event-on attributen gesetzt ist.
Klingt nach dem Problem mit Münchhausen, der sich selbst an den eigenen Haaren aus dem Sumpf zieht.
Oder: Wer die Events verhindert darf sich nicht wundern wenn sie nicht kommen :)
Gruß Otto
Hallo Otto,
vielen Dank für Deinen Denkanstoß.
Habe nochmal versucht die Problematik in einem Testszenario nachzustellen.
Dummyswitch dmySw1 löst bei "on" den DOIF actTest2 aus, welches dann in DummyDevice dmyTest1 Readings ausließt bzw. schreibt. Werte aus Reading test1 + test2 werden in test3-x geschrieben
Readings:
test1 - wird manuell verändert,
test2 - wird in DOIF Wert zugewiesen
test3-1 - wird in DOIF aus [dmytest1:test1]+[dmytest1:test2] berechnet
test3-2 - wird in DOIF aus [$SELF:test3int] welches in
Attribut DOIF-Readings test3int:([dmytest1:test1]+[dmytest1:test2]) berechnet wird
Im Doif wird nach Wertzuweisung von test2 ein sleep ausgeführt.
Tests:
test1 manuell geändert - aktualisierung ok
test2 Wert in DOIF geändert - test3-1,test3-2 nicht aktualisiert
DOIF initialisiert/checkall - test3-1 ok - test3-2 nicht aktualisiert
test2 Wert in DOIF geändert - test3-1 nicht aktualisiert - test3-2 jetzt mit altem Wert aktualisiert
Im Eventmonitor stehen die Timestamps von test3-x jeweils mit dem aktuellsten Wert - werden also aktualisiert. Auch der test2 Wert wird korrekt aufgeführt. Jedoch wird für die Berechnung von test3 der alte test2 Wert verwendet.
Wie du ja geschrieben hast wir der neue test2-Wert wohl nicht innerhalb des Zweiges aktualisiert.
Aber wie kann ich jetzt für eine Aktualisierung sorgen oder muss ich die Verwendung des aktuellen test3-Wertes aus dem Zweig in ein anderes Notify/Doif auslagern?
defmod dmyTest1 dummy
attr dmyTest1 event-on-update-reading .*
attr dmyTest1 userReadings test3 {ReadingsVal("dmyTest1","test1",0)+ReadingsVal("dmyTest1","test2",0)}
setstate dmyTest1 2020-08-20 11:18:44 test1 11
setstate dmyTest1 2020-08-20 11:40:43 test2 2
setstate dmyTest1 2020-08-20 11:40:43 test3 13
setstate dmyTest1 2020-08-20 11:40:43 test3-1 31
setstate dmyTest1 2020-08-20 11:40:43 test3-2 31
defmod dmySw1 dummy
attr dmySw1 setList on na off
attr dmySw1 webCmd on:na:off
defmod ActTest2 DOIF ([dmySw1:state] eq "on") (\
setreading dmyTest1 test2 2;;\
sleep .1;;\
setreading dmyTest1 test3-1 {([dmyTest1:test1]+[dmyTest1:test2])};;\
setreading dmyTest1 test3-2 [$SELF:test3int];;\
)
attr ActTest2 DOIF_Readings test3int:([dmyTest1:test1]+[dmyTest1:test2])
attr ActTest2 addStateEvent 1
attr ActTest2 do always
Alles schwer zu verstehen - aber :
der Syntax von sleep ist
sleep 0.1; tue etwas Deine Variante:
sleep 0.1, (zeilenumbruch)
tue was findet irgendein Parser nicht so schick.
Hintergrund: FHEM sleep ist ein "fragiler" Befehl, er nimmt den nachfolgenden FHEM Befehl und erzeugt damit ein temporäres at. Fehler im semikolon und in den Befehlen führen eventuell nicht zu logischen Syntaxfehlern sondern zu eigentümlichen Effekten in der Ausführung :)
Gruß Otto
Nachtrag: Dein event-on-update-reading .* ist für mich irgendwie eine null Nummer. Zitat aus der Doku
Zitatevent-on-update-reading
Wenn nicht gesetzt, erzeugt jede Veränderung eines "readings" ein Ereignis, welches z.B. von notify oder FileLog berücksichtigt wird. Wenn gesetzt erzeugen nur Aktualisierungen der eingetragenen "readings" ein Ereignis.
1. DOIF_Readings werden erst aktualisiert, wenn die Trigger davon triggern, sprich bei einer Änderung von dmyTest1:test1 oder test2. Setzt Du manuell diese, wird test3int sofort aktualisiert. ABER: DOIF unterbindet endlose Schleifen. Das heisst, eine Änderung von test2 innerhalb eines Zweigs triggert nicht wiederum test3int, und test3int wird dadurch nicht aktualisiert.
2. sleep ist wie ein at: der nachfolgende Befehl wird nach der Wartezeit ausgeführt. Inzwischen macht das DOIF weiter. Du siest das besser, wenn Du ein sleep 5 nutzt. test3-1 wird nach x Sekunden aktualisiert. test3-2 aber dagegen sofort, mit der Anmerkung in 1: test3int hat sich nicht geändert.
Beispiel: Ausgangssituation:
dmyTest1
READINGS:
2020-08-20 22:47:43 test1 10
2020-08-20 23:10:01 test2 10
2020-08-20 23:10:01 test3 20
2020-08-20 23:07:38 test3-1 12
2020-08-20 23:07:33 test3-2 20
ActTest2
READINGS:
2020-08-20 22:55:27 test3int 20
Ergebnis nach "Betätigung" von dmySw1 um 23:11:36:
READINGS:
2020-08-20 22:47:43 test1 10
2020-08-20 23:11:36 test2 2
2020-08-20 23:11:41 test3 12
2020-08-20 23:11:41 test3-1 12
2020-08-20 23:11:36 test3-2 20
READINGS:
2020-08-20 22:55:27 test3int 20
- test3int hat sich nicht geändert da das DOIF sich selbst nicht triggert
- test2 wurde sofort aktualisiert, und damit test3 auch
- test3-1 wurde nach 5s aktualisiert. Damit wurde das userReading test3 wieder getriggert und wieder aktualisiert
- test3-2 wurde sofort aktualisiert, mit dem ungeänderten Wert von test3int.
EDIT: dein Waschmaschine Beispiel funktioniert nicht, weil Du nicht das richtige Trennzeichen zwischen Befehlen nutzt. In DOIF ist es Koma und nicht Semikolon.
Beispiel: ([dmySw1:state] eq "on") (
setreading dmyTest1 test2 2; #hier mit Semikolon
setreading dmyTest1 test2 {([dmyTest1:test2] + 2)}
)
Mit der gleichen Ausgangssituation wie oben (test2=10) hat man am Ende 12 in test2.
([dmySw1:state] eq "on") (
setreading dmyTest1 test2 2, #hier mit Koma
setreading dmyTest1 test2 {([dmyTest1:test2] + 2)}
)
Hier hat man 4 in test2 am Ende.
DOIF verhält sich anders bei der Evaluierung von [dmyTest1:test2]. Im ersten Fall interpretiert er beide setreadings als einen einzigen Befehl und macht die Evaluierung vorher. Im zweiten Fall als 2 nachfolgende Befehle, und die Evaluierung für den 2. Befehl erfolg erst nach dem ersten Befehl
So zumindest meine Verständnis. Vielleicht korrigiert noch Damian etwas
Fazit: Koma statt Semikolon, und statt sleep, lieber das Attribut wait von DOIF. Und die attr innerhalb eines Befehls lieber nicht manipulieren.
Das war es!
Super Analyse - herzlichen Dank!
Habe mich mit dem Problem schon länger beschäftigt, aber darauf wäre ich wohl noch nicht so schnell gekommen...
... auch wenn alles natürlich in der Befehlsreferenz steht. :-[
https://fhem.de/commandref_DE.html#DOIF_Angaben_im_Ausfuehrungsteil
https://forum.fhem.de/index.php/topic,58732.msg501105.html#msg501105