Hallo,
ich bitte um Hilfe bei einem DOIF mit bedingter Wiederholung, welches leider nicht funktioniert. Den Code habe ich aus der commandref zu DOIF "Anwendungsbeispiele mit bedingter Wiederholung einer Ausführung" übernommen und erweitert.
Das ursprüngliche Beispiel-DOIF sieht so aus:
defmod di_window DOIF {if ([window:state] eq "open") {set_Exec("timer",'300+$count*60','fhem("echo speak window open")','$count < 9')} else {del_Exec("timer")}}
Mein DOIF sieht so aus:
defmod Herdwarnung DOIF {if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {set_Exec("timer",'60','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"),'fhem("set Snips say Herd wurde abgeschaltet")','fhem("set Herd off")'}}
Im List und Logfile sehe ich zwar einen Error und eine Warnunug, kann aber mit den Hinweisen leider nichts anfangen.
Internals:
DEF {if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {set_Exec("timer",'60','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"),'fhem("set Snips say Herd wurde abgeschaltet")','fhem("set Herd off")'}}
FUUID 5c7019e2-f33f-17f9-dfd0-8bcaa954a9ecb3e4
MODEL Perl
NAME Herdwarnung
NOTIFYDEV BM_Kueche,Herd,global
NR 285
NTFY_ORDER 50-Herdwarnung
STATE cmd_2
TYPE DOIF
VERSION 21224 2020-02-18 18:45:49
READINGS:
2020-11-26 22:35:46 Device Herd
2020-11-26 22:35:46 block_01 executed
2020-11-26 22:35:46 e_Herd_Herd_Status ein
2020-11-26 22:36:46 error in fhem("set Snips say Achtung Herd ist eingeschaltet"): Undefined subroutine &DOIF::fhem("set Snips say Achtung Herd ist eingeschaltet") called at (eval 3350470) line 1.
2020-11-26 22:34:53 mode enabled
2020-11-26 19:25:50 state cmd_2
2020-11-26 22:35:46 warning condition c01: Useless use of a constant ("fhem(\"set Snips say Herd wurde "...) in void context
Regex:
accu:
cond:
BM_Kueche:
0:
&STATE ^BM_Kueche$
Herd:
0:
Herd_Status ^Herd$:^Herd_Status:
attr:
cmdState:
repeatcmd:
waitdel:
condition:
0 if (::ReadingValDoIf($hash,'Herd','Herd_Status') eq "ein" and ::InternalDoIf($hash,'BM_Kueche','STATE') eq "noMotion") {set_Exec("timer",'60','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"),'fhem("set Snips say Herd wurde abgeschaltet")','fhem("set Herd off")'}
helper:
DEVFILTER ^global$|^Herd$|^BM_Kueche$
NOTIFYDEV global|Herd|BM_Kueche
event Herd_Status: ein
globalinit 1
last_timer 0
sleeptimer -1
triggerDev Herd
triggerEvents:
Herd_Status: ein
triggerEventsState:
Herd_Status: ein
internals:
all BM_Kueche:STATE
perlblock:
0
ptimer:
timer:
name timer
param $count < 3
subname fhem("set Snips say Achtung Herd ist eingeschaltet")
time 1606426606.95767
hash:
readings:
all Herd:Herd_Status
trigger:
uiState:
uiTable:
Attributes:
Kann mich bitte jemand in die richtige Richtung schubsen und mir sagen, was da falsch ist? Das ursprüngliche Beispiel sieht ja eigentlich genau gleich aus (die Syntax betreffend).
Dein DOIF ist vom Februar, du solltest die aktuelle Version nehmen.
Hallo Damian,
danke für den Hinweis. Habe FHEM nun auf den aktuellen Stand gebracht. Leider erscheinen der Error und die Warnung immer noch:
Internals:
DEF {if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {set_Exec("timer",'60','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"),'fhem("set Snips say Herd wurde abgeschaltet")','fhem("set Herd off")'}}
FUUID 5c7019e2-f33f-17f9-dfd0-8bcaa954a9ecb3e4
MODEL Perl
NAME Herdwarnung
NOTIFYDEV Herd,global,BM_Kueche
NR 285
NTFY_ORDER 50-Herdwarnung
STATE cmd_2
TYPE DOIF
VERSION 23235 2020-11-25 22:42:28
READINGS:
2020-11-27 10:07:54 Device Herd
2020-11-27 10:07:54 block_01 executed
2020-11-27 09:19:00 e_BM_Kueche_STATE noMotion
2020-11-27 10:07:54 e_Herd_Herd_Status ein
2020-11-26 23:32:39 error in fhem("set Snips say Achtung Herd ist eingeschaltet"): Undefined subroutine &DOIF::fhem("set Snips say Achtung Herd ist eingeschaltet") called at (eval 3356855) line 1.
2020-11-26 23:16:37 mode enabled
2020-11-26 19:25:50 state cmd_2
2020-11-27 10:07:54 warning condition c01: Useless use of a constant ("fhem(\"set Snips say Herd wurde "...) in void context
Regex:
accu:
cond:
BM_Kueche:
0:
&STATE ^BM_Kueche$
Herd:
0:
Herd_Status ^Herd$:^Herd_Status:
condition:
0 if (::ReadingValDoIf($hash,'Herd','Herd_Status') eq "ein" and ::InternalDoIf($hash,'BM_Kueche','STATE') eq "noMotion") {set_Exec("timer",'60','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"),'fhem("set Snips say Herd wurde abgeschaltet")','fhem("set Herd off")'}
helper:
DEVFILTER ^global$|^BM_Kueche$|^Herd$
NOTIFYDEV global|BM_Kueche|Herd
event Herd_Status: ein
globalinit 1
last_timer 0
sleeptimer -1
triggerDev Herd
triggerEvents:
Herd_Status: ein
triggerEventsState:
Herd_Status: ein
internals:
all BM_Kueche:STATE
perlblock:
0 block_01
ptimer:
timer:
cond $count < 3
count 3
name timer
sec 60
subname fhem("set Snips say Achtung Herd ist eingeschaltet")
time 1606468254.66373
hash:
readings:
all Herd:Herd_Status
trigger:
uiTable:
Attributes:
Nun kommt zwar die dreimalige Sprachausgabe (was vor dem Update nicht ging), aber die Meldung danach im else-Zweig kommt nicht. Das zweite Kommando im else-Zweig wird auch nicht ausgeführt. Und wie schon geschrieben, erscheinen immer noch der Error und die Warnung. Warum wird 'fhem(set Snips say ....' als subroutine bzw. als Konstante interpretiert?
Falsche Syntax!
korrekt:
... else {del_Exec("timer");fhem("set Snips say Herd wurde abgeschaltet");fhem("set Herd off")}}
die einfachen Anführungszeichen muss man zusätzlich nur bei set_Exec verwenden.
Hm, nun kommen zwar keine Fehler- bzw. Warnmeldungen mehr, aber der else-Zweig wird nach 3-maligem Durchlauf des ersten Zweigs immer noch nicht durchlaufen. Das DOIF hat auch dauernd den Status initialized.
Wann geht das DOIF eigentlich in den else-Zweig? An den Bedingungen im ersten Zweig ändert sich ja nichts. Oder ist die Variable $count gleichzeitig Timerbedingung und auch quasi die Weiterschaltbedingung?
Internals:
DEF {if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {set_Exec("timer",'20','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"); fhem("set Snips say Herd wurde abgeschaltet"); fhem("set Herd off")}}
FUUID 5c7019e2-f33f-17f9-dfd0-8bcaa954a9ecb3e4
MODEL Perl
NAME Herdwarnung
NOTIFYDEV Herd,BM_Kueche,global
NR 285
NTFY_ORDER 50-Herdwarnung
STATE initialized
TYPE DOIF
VERSION 23235 2020-11-25 22:42:28
READINGS:
2020-11-27 11:20:36 Device Herd
2020-11-27 11:20:36 block_01 executed
2020-11-27 11:20:36 e_Herd_Herd_Status ein
2020-11-27 11:20:20 mode enabled
2020-11-27 11:20:20 state initialized
Regex:
accu:
cond:
BM_Kueche:
0:
&STATE ^BM_Kueche$
Herd:
0:
Herd_Status ^Herd$:^Herd_Status:
condition:
0 if (::ReadingValDoIf($hash,'Herd','Herd_Status') eq "ein" and ::InternalDoIf($hash,'BM_Kueche','STATE') eq "noMotion") {set_Exec("timer",'20','fhem("set Snips say Achtung Herd ist eingeschaltet")','$count < 3')} else {del_Exec("timer"); fhem("set Snips say Herd wurde abgeschaltet"); fhem("set Herd off")}
helper:
DEVFILTER ^global$|^BM_Kueche$|^Herd$
NOTIFYDEV global|BM_Kueche|Herd
event Herd_Status: ein
globalinit 1
last_timer 0
sleeptimer -1
triggerDev Herd
triggerEvents:
Herd_Status: ein
triggerEventsState:
Herd_Status: ein
internals:
all BM_Kueche:STATE
perlblock:
0 block_01
ptimer:
timer:
cond $count < 3
count 3
name timer
sec 20
subname fhem("set Snips say Achtung Herd ist eingeschaltet")
time 1606472496.15691
hash:
readings:
all Herd:Herd_Status
trigger:
uiTable:
Attributes:
Hallo rih,
der ELSE-Zweig wird ausgeführt, wenn die Ausgaben bzw. Zeichenketten von [Herd:Herd_Status] genau gleich "ein" ist UND [BM_Kueche] genau gleich "noMotion" ist.
Sind diese beiden Bedingungen nicht wahr bzw. gegeben, wird sofort in den ELSE-Zweig verwiesen, also $count, etc. nicht angewendet.
Hast Du ein "do always"?
Wir reden hier vom DOIF-Perlmodus, hier gibt es kein do-Attribut, die Ausführungen sind immer "always". Auch des Status des Moduls ändert sich nicht, wenn man den nicht selbst mit set_State ändert.
Die else-Anweisung ist das Gegenteil der If-Abfrage, wenn also dein set_Exec ausgeführt wird, dann wird ja nicht else ausgeführt.
ZitatDie else-Anweisung ist das Gegenteil der If-Abfrage, wenn also dein set_Exec ausgeführt wird, dann wird ja nicht else ausgeführt.
Dann ist dieses Konstukt für meinen Anwendungsfall wohl nicht geeignet. Mein Ziel ist: 3-mal eine Warnmeldung absetzen. Hat sich bis dahin nichts geändert, dann soll abgeschaltet werden und auch hier eine entsprechende Meldung ausgegeben werden. Mit einem DOIF im Nicht-Perl-Modus habe ich das leider auch nicht hinbekommen. Dann muss ich die Idee wohl begraben. Schade.
Ich würde statt des else Zweiges versuchen, das Ausschalten in den set_Exec Aufruf einzubauen. Also als Abbruchbedingung statt '$count < 3' ein '$count < 4' setzen, und im Befehlsteil testen, ob $count = 3 ist. Falls ja, Herd ausschalten.
Dann ist es ein Fall für einen rekursiven Aufruf:
DOIF
subs {
sub check {
if (ReadingsVal("Herd","Herd_Status","") eq "ein" and ReadingsVal("BM_Kueche","state","") eq "noMotion") {
if ($_count < 3) {
$_count++;
fhem("set Snips say Achtung Herd ist eingeschaltet");
set_Exec("timer",20,'check()');
} else {
fhem("set Snips say Herd wurde abgeschaltet");
fhem("set Herd off");
}
}
}
{if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {$_count=0;del_Exec ("timer");set_Exec("timer",20,'check()')}}
Hallo Damian,
vielen Dank für deine Hilfe. Habe das DOIF entsprechend definiert. Bekomme aber in der letzten Zeile folgende Fehler:
Herdwarnung DOIF: error in defs block: syntax error at (eval 96407) line 14, near "Herd:"
syntax error at (eval 96407) line 14, near "}="
syntax error at (eval 96407) line 14, near ")}"
Wenn ich die letzte Zeile weg lasse, bekomme ich zwar keine Fehler mehr, aber das DOIF reagiert trotzdem nicht.
Internals:
CFGFN
DEF subs {
sub check {
if (ReadingsVal("Herd","Herd_Status","") eq "ein" and ReadingsVal("BM_Kueche","state","") eq "noMotion") {
if ($_count < 3) {
$_count++;
fhem("set Snips say Achtung Herd ist eingeschaltet");
set_Exec("timer",20,'check()');
} else {
fhem("set Snips say Herd wurde abgeschaltet");
fhem("set Herd off");
}
}
}
}
FUUID 5fc1690c-f33f-17f9-ac78-30084738a016367e
MODEL Perl
NAME Herdwarnung
NOTIFYDEV global
NR 3051
NTFY_ORDER 50-Herdwarnung
STATE initialized
TYPE DOIF
VERSION 23235 2020-11-25 22:42:28
READINGS:
2020-11-27 22:21:30 mode enabled
2020-11-27 22:21:30 state initialized
condition:
helper:
globalinit 1
last_timer 0
sleeptimer -1
uiTable:
Attributes:
Habe ich etwas falsch gemacht? Kannst du bitte nochmal drüber schauen?
Es fehlte eine Klammer:
defmod di_warnung DOIF subs {\
sub check {\
if (ReadingsVal("Herd","Herd_Status","") eq "ein" and ReadingsVal("BM_Kueche","state","") eq "noMotion") {\
if ($_count < 3) {\
$_count++;;\
fhem("set Snips say Achtung Herd ist eingeschaltet");;\
set_Exec("timer",20,'check()');;\
} else {\
fhem("set Snips say Herd wurde abgeschaltet");;\
fhem("set Herd off");;\
}\
}\
}\
}\
{if ([Herd:Herd_Status] eq "ein" and [BM_Kueche] eq "noMotion") {$_count=0;;del_Exec ("timer");;set_Exec("timer",20,'check()')}}
Hallo Damian,
vielen Dank, dass Du Dich zu so später Stunde noch mit meinem Problem beschäftigt hast. Das DOIF funktioniert nun wie gewünscht. Hätte ich niemals hinbekommen. Rekursiver Aufruf - darauf muss man erst mal kommen. Das kann nur so ein Profi wie Du.
Nochmals vielen Dank.