DOIF Triggerbedingungen Klammersetzung

Begonnen von bismosa, 30 April 2025, 16:38:46

Vorheriges Thema - Nächstes Thema

bismosa

Hallo!
Ich nutze ein relativ komplexes DOIF Template.
Ich stehe gerade voll auf dem Schlauch und habe zwei unterschiedliche Probleme.

Es geht um eine Rolladensteuerung. Hier möchte ich abends einen Dunkel-Status ermitteln:
$1_EveningDark {
if ([Firmata_A1_Licht_Aussen_Grill:value] < [$1:Autom_zu_sonne_solar_wert]){
if (get_Reading("$1"."_isEveningDark2","xx") ne "yes"){
set_Reading("$1".."_isEveningDark2", "yes");
}
} else {
if (get_Reading("$1".."_isEveningDark2","xx") ne "no"){
set_Reading("$1".."_isEveningDark2", "no");
}
}
}

Alternativ über ein Attribut DOIF_Readings:
Rolladen_TEST_isEveningDark: ([Firmata_A1_Licht_Aussen_Grill:value] < [Rolladen_TEST:Autom_zu_sonne_solar_wert] ? "yes" : "no")
1.)
Warum funktioniert ein:
if ([Firmata_A1_Licht_Aussen:value] < [$1:Autom_zu_sonne_solar_wert]){nicht? Ich erhalte die Fehlermeldung:
Argument "Rolladen_TEST" isn't numeric in range (or flop) (Rolladen_TEST = $1)
Setze ich doppelte Klammern im zweiten Teil kommt es nicht zur Fehlermeldung. ([[$1:Autom_zu_sonne_solar_wert]])

2.)
Die Zustandsauswertung habe ich beim DOIF_Readings:
...
[$SELF:$1_isEveningDark] eq "yes"
...
Denn Triggern Soll es nur bei diesem device.
Allerdings erhalte ich auch hier nur die Fehlermeldung:
Use of uninitialized value $1 in concatenation (.) or string
Wie kann ich im Template richtig nur auf das entsprechende Reading des einen Devies reagieren?

3.) Wo ist der Unterschied in der Performance, wenn ich mehrere Bedingungen habe um diesen Zweig zu triggern? Brauche ich überhaupt die DOIF_Readings oder lässt sich das nicht einfacher (und genau so performant) umsetzen wie mit den Readings?
Also z.B. sind meine Bedingungen:
if ([$1:Autom_zu_sonne] eq "Ja" &&
[$1:Autom_zu_sonne_solar] eq "Ja" &&
[([astro:CustomTwilightEvening] + [$1:Autom_zu_sonne_offset]*60)-23:59] &&
[$SELF:["$1_isEveningDark"]] eq "yes") {...
bzw. ohne die DOIF-Readings (da würde ich den häufigen Trigger als erstes setzen):
if ([Firmata_A1_Licht_Aussen_Grill:value] < [[$1:Autom_zu_sonne_solar_wert]] &&
[$1:Autom_zu_sonne] eq "Ja" &&
[$1:Autom_zu_sonne_solar] eq "Ja" &&
[([astro:CustomTwilightEvening] + [$1:Autom_zu_sonne_offset]*60)-23:59]) {...

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Damian

Wie sieht deine Template-Definition aus?
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

bismosa

Die ist mittlerweile schon über 300 Zeilen lang  ;)
Hier der Aufbau mit den interessanten Teilen:
subs {
  sub di_Rolladen_CheckWindows_Close {
...
  }
  sub di_Rolladen_LockTimer_Move {
...
  }
  ...
}

DEF TPL_RolloAutomatikNEU(

$1_Sonnenschutz {
...
}

$1_RolloZu {
  if ( [$1:Autom_zu] eq "Ja" && [di_Einst_Rolladen:Schliessen_aktiv] eq "Ja" ) {
    [$1:state];[$2:state];[$3:state];
    ## Fenster geschlossen + Timer aktiv
    if ( get_Exec("${1}_Window_Timer") > 0 ) {
  di_Rolladen_Log(1, "$1", "Fenster geschlossen. di_Rolladen_CheckWindows_Close");
      di_Rolladen_CheckWindows_Close("$1", "$2", "$3", "$4");
      return;
    }

    ## Bedingungen definieren
    my %cases = (
      "Nur_Uhrzeit" => (
        [$1:Autom_zu_sonne] eq "Nein" &&
        [$1:Autom_zu_sonne_solar] eq "Nein" &&
        [[$1:Autom_zu_zeit]|012345678]
      ),
      "Uhrzeit_abends_dunkel" => (
        [$1:Autom_zu_sonne] eq "Nein" &&
        [$1:Autom_zu_sonne_solar] eq "Ja" &&
        [[$1:Autom_zu_zeit]-23:59] &&
        [$SELF:["$1_isEveningDark"]] eq "yes"
      ),
      "Sonnenuntergang" => (
        [$1:Autom_zu_sonne] eq "Ja" &&
        [$1:Autom_zu_sonne_solar] eq "Nein" &&
        [([astro:CustomTwilightEvening] + [$1:Autom_zu_sonne_offset]*60)|012345678]
      ),
      "Sonnenuntergang_dunkel" => (
        [$1:Autom_zu_sonne] eq "Ja" &&
        [$1:Autom_zu_sonne_solar] eq "Ja" &&
        [([astro:CustomTwilightEvening] + [$1:Autom_zu_sonne_offset]*60)-23:59] &&
        [$SELF:["$1_isEveningDark"]] eq "yes"
      ),
    );

    foreach my $fall (keys %cases) {
      if ($cases{$fall}) {
  di_Rolladen_Log(1, "$1", "Bedingung '$fall' erfüllt. di_Rolladen_CheckWindows_Close");
        di_Rolladen_CheckWindows_Close("$1","$2","$3","$4");
        last;
      }
    }
  }
}

$1_RolloZeitAuf{
...
}

$1_EveningDark {
my $test1=[Firmata_A1_Licht_Aussen_Grill:value];
my $test2=[$1:Autom_zu_sonne_solar_wert];
di_Rolladen_Log(1, "$1", "EveningDark getriggert  $DEVICE $EVENT $test1 $test2");
if ([Firmata_A1_Licht_Aussen_Grill:value] < [[$1:Autom_zu_sonne_solar_wert]]){
if (get_Reading("$1"."_isEveningDark2","xx") ne "yes"){
set_Reading("$1".."_isEveningDark2", "yes");
}
} else {
if (get_Reading("$1".."_isEveningDark2","xx") ne "no"){
set_Reading("$1".."_isEveningDark2", "no");
}
}
}

) ##TPL

TPL_RolloAutomatikNEU(Rolladen_TEST,Fenster_EG_Buero_L,Fenster_EG_Buero_R,Fenster_EG_Buero_R);

attr di_Rolladen_Auto_NEU DOIF_Readings Rolladen_TEST_isEveningDark: ([Firmata_A1_Licht_Aussen_Grill:value] < [Rolladen_TEST:Autom_zu_sonne_solar_wert] ? "yes" : "no")
Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Damian

ich habe die Stelle des Templates bei mir ohne Probleme übernehmen können:

defmod testtpl2 DOIF DEF TPL_RolloAutomatikNEU(\
\
$1_EveningDark {\
my $test1=[Firmata_A1_Licht_Aussen_Grill:value];;\
my $test2=[$1:Autom_zu_sonne_solar_wert];;\
di_Rolladen_Log(1, "$1", "EveningDark getriggert  $DEVICE $EVENT $test1 $test2");;\
if ([Firmata_A1_Licht_Aussen_Grill:value] < [$1:Autom_zu_sonne_solar_wert]){\
if (get_Reading("$1"."_isEveningDark2","xx") ne "yes"){\
set_Reading("$1".."_isEveningDark2", "yes");;\
}\
} else {\
if (get_Reading("$1".."_isEveningDark2","xx") ne "no"){\
set_Reading("$1".."_isEveningDark2", "no");;\
}\
}\
}\
\
) ##TPL\
\
TPL_RolloAutomatikNEU(Rolladen_TEST,Fenster_EG_Buero_L,Fenster_EG_Buero_R,Fenster_EG_Buero_R);;

setstate testtpl2 initialized
setstate testtpl2 2025-04-30 17:59:57 mode enabled
setstate testtpl2 2025-04-30 17:59:57 state initialized

mit List kann man den gewandelten Perlcode sehen sowie die aufgesetzten Trigger:

Internals:
   CFGFN     
   DEF        DEF TPL_RolloAutomatikNEU(

$1_EveningDark {
my $test1=[Firmata_A1_Licht_Aussen_Grill:value];
my $test2=[$1:Autom_zu_sonne_solar_wert];
di_Rolladen_Log(1, "$1", "EveningDark getriggert  $DEVICE $EVENT $test1 $test2");
if ([Firmata_A1_Licht_Aussen_Grill:value] < [$1:Autom_zu_sonne_solar_wert]){
if (get_Reading("$1"."_isEveningDark2","xx") ne "yes"){
set_Reading("$1".."_isEveningDark2", "yes");
}
} else {
if (get_Reading("$1".."_isEveningDark2","xx") ne "no"){
set_Reading("$1".."_isEveningDark2", "no");
}
}
}

) ##TPL

TPL_RolloAutomatikNEU(Rolladen_TEST,Fenster_EG_Buero_L,Fenster_EG_Buero_R,Fenster_EG_Buero_R);
   FUUID      68124830-f33f-c0d4-73ab-4cfa945787f1ea32
   MODEL      Perl
   NAME       testtpl2
   NOTIFYDEV  Firmata_A1_Licht_Aussen_Grill,global,Rolladen_TEST
   NR         288
   NTFY_ORDER 50-testtpl2
   STATE      initialized
   TYPE       DOIF
   VERSION    28546 2024-02-23 20:11:05
   eventCount 4
   READINGS:
     2025-04-30 17:59:57   mode            enabled
     2025-04-30 17:59:57   state           initialized
   Regex:
     accu:
     bar:
     barAvg:
     collect:
     cond:
       Firmata_A1_Licht_Aussen_Grill:
         0:
           value      ^Firmata_A1_Licht_Aussen_Grill$:^value:
       Rolladen_TEST:
         0:
           Autom_zu_sonne_solar_wert ^Rolladen_TEST$:^Autom_zu_sonne_solar_wert:
   condition:
     0         
my $test1=::ReadingValDoIf($hash,'Firmata_A1_Licht_Aussen_Grill','value');
my $test2=::ReadingValDoIf($hash,'Rolladen_TEST','Autom_zu_sonne_solar_wert');
di_Rolladen_Log(1, "Rolladen_TEST", "EveningDark getriggert  $DEVICE $EVENT $test1 $test2");
if (::ReadingValDoIf($hash,'Firmata_A1_Licht_Aussen_Grill','value') < ::ReadingValDoIf($hash,'Rolladen_TEST','Autom_zu_sonne_solar_wert')){
if (get_Reading("Rolladen_TEST"."_isEveningDark2","xx") ne "yes"){
set_Reading("Rolladen_TEST".."_isEveningDark2", "yes");
}
} else {
if (get_Reading("Rolladen_TEST".."_isEveningDark2","xx") ne "no"){
set_Reading("Rolladen_TEST".."_isEveningDark2", "no");
}
}

   defs:
     tpl:
       TPL_RolloAutomatikNEU

$1_EveningDark {
my $test1=[Firmata_A1_Licht_Aussen_Grill:value];
my $test2=[$1:Autom_zu_sonne_solar_wert];
di_Rolladen_Log(1, "$1", "EveningDark getriggert  $DEVICE $EVENT $test1 $test2");
if ([Firmata_A1_Licht_Aussen_Grill:value] < [$1:Autom_zu_sonne_solar_wert]){
if (get_Reading("$1"."_isEveningDark2","xx") ne "yes"){
set_Reading("$1".."_isEveningDark2", "yes");
}
} else {
if (get_Reading("$1".."_isEveningDark2","xx") ne "no"){
set_Reading("$1".."_isEveningDark2", "no");
}
}
}


   helper:
     NOTIFYDEV  Firmata_A1_Licht_Aussen_Grill,global,Rolladen_TEST
     globalinit 1
     last_timer 0
     sleeptimer -1
   perlblock:
     0          Rolladen_TEST_EveningDark
   readings:
     all         Firmata_A1_Licht_Aussen_Grill:value Rolladen_TEST:Autom_zu_sonne_solar_wert
   uiState:
   uiTable:
Attributes:

Mit doppelten Klammern würdest du aus einem Readingtrigger einen indirekten Timer machen, das willst du in der Abfrage aber nicht. Unter Condition 0 siehst du den korrekten Code insb. die if-Abfrage.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

bismosa

Hallo!

Danke für die Antwort und das testen!

Oh Mann...den Fehler habe ich gerade entdeckt.  ::)
set_Reading("$1".."_isEveningDark2", "yes");Da ist doch ein Punkt zu viel richtig wäre:
set_Reading("$1"."_isEveningDark2", "yes");Fehler 30. Das Problem sitzt 30cm vor dem Bildschirm...100x gelesen und doch übersehen.


Bei Problem 2 bin ich allerdings noch nicht weiter gekommen. Ich gehe davon aus, das dies eher unüblich ist?

Ich denke auch, das ich die Bedingung von "$1_EveningDark" hier einfach in mein "$1_RolloZu" einbauen kann. (Frage 3) Oder?

Gruß
Bismosa





1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

Damian

DOIF_Readings bringen keinen Geschwindigkeitsvorteil. Der entscheidende Unterschied ist allerdings, dass ein DOIF_Reading nur beim Wechsel seines Zustands triggert, was dem FHEM-Modus ohne do always entspricht.

Es ist unerheblich wie oft die gleiche Trigger-Angabe innerhalb eines DOIF-Blocks vorkommt oder sogar in verschiedenen Blöcken, es wird immer nur ein Trigger im DOIF aufgesetzt. Das Modul merkt sich nur in welchen Blöcken die Angabe vorkommt, damit diese Blöcke ausgeführt werden. Es läuft also alles mit maximaler Perl-Performance.

Natürlich sollte man keine Trigger von Readings definieren, wenn diese Readings grundsätzlich nicht als Trigger benötigt werden, denn diese belasten unnötig das System. Also ein Fragezeichen bei diesen Abfragen setzen [?device:reading] oder gleich ReadingsVal-Funktion benutzen.

Um den Überblick zu behalten, was einen Block triggert, kann man am Anfang eines Block alle benötigten Trigger definieren und jeweils einer Perl-Variablen zuweisen und nur noch diese benutzen, Bsp.:

myblock {

my $küchenLicht=[lampe1:status];
my $wohnzimmer=[wohnzimmerLampe:status];

if ($küchenLicht == "off") {...}

if ($küchenLicht == "on") {...}

if ($wohnzimmer == ...

... usw.


So muss man nicht lange innerhalb eines Blocks nach Triggern suchen, denn diese können an beliebiger Stellen vorkommen, nicht nur in der if-Bedingung. Der Code wird dadurch aber nicht performanter.


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

bismosa

Hallo!

Und nochmal DANKE!

Ich habe jetzt endlich meine Fehler gefunden:
[$1:state];[$2:state];[$3:state];
    ## Fenster geschlossen + Timer aktiv
    if ( get_Exec("${1}_Window_Timer") > 0 ) {
Hier habe ich zwei gemacht. $1:state hätte schon $2:state sein müssen.

if ( get_Exec("${1}_Window_Timer") > 0 ) {
hätte if ( get_Exec("$1_Window_Timer") > 0 ) { sein müssen.
 
Das passiert, wenn man sich von ChatGPT eninige Verbesserungen einbauen lässt und dies nicht vernünftig liest. Ich hatte den Fehler an völlig falscher Stelle gesucht.  ::)

Hat sich hier somit erledigt.

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...