Aktualisierung Readings innerhalb eines DOIF-Zweigs

Begonnen von jepter, 14 August 2020, 10:24:19

Vorheriges Thema - Nächstes Thema

jepter

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

Otto123

#1
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

Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

jepter

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

Otto123

#3
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.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

amenomade

#4
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.
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

jepter

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