[Gelöst] DOIF mit bedingter Wiederholung

Begonnen von rih, 26 November 2020, 23:18:48

Vorheriges Thema - Nächstes Thema

rih

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).



Damian

Dein DOIF ist vom Februar, du solltest die aktuelle Version nehmen.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

rih

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?

Damian

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.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

rih

#4
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:

twinFHEM

#5
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"?


Damian

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.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

rih

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.

xenos1984

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.

Damian

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()')}}
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

rih

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?

Damian

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()')}}

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

rih

#12
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.