DOIF Verständnisfrage oder besser: was mache ich falsch?

Begonnen von ahermann86, 23 Juni 2019, 14:52:19

Vorheriges Thema - Nächstes Thema

ahermann86

Hallo,

bin gerade am Verzweifeln mit einem DOIF:

Um das ganze zu debuggen, habe ich mein DOIF wie folgt heruntergekürzt:


define di_BMode DOIF (([$SELF:IstSommer]) eq "on" and ([$SELF:FreigabeKuehlen] eq "on"))\
(set HPSU_Set BMode Sommer)\
DOELSEIF (["$SELF:IstSommer: off"])\
(set HPSU_Set BMode Sommer)\


"IstSommer" und "FreigabeKuehlen" sind eigens definierte Readings:
attr di_BMode readingList IstSommer FreigabeKuehlen
attr di_BMode room Heizung_HPSU
attr di_BMode setList IstSommer:on,off FreigabeKuehlen:on,off

Natürlich macht das DOIF da oben keinen großen Sinn aber... sollte doch mit dem DOIF "state" (z.B. cmd_2) sichtbar sein, welche Bedinung erfüllt ist..?
Wenn ich "IstSommer" und "FreigabeKuehlen" "händisch" über die Weboberfläche schalte, funktioniert das ganze manchmal. Dabei beobachte ich das "state" (z.B. cmd_2). Irgendwann will das ganze einfach nicht mehr. Da kann man dann schalten wie man will und sogar nach einem FHEM Neustart wirds nicht besser.

Habe ich da noch einen Denkfehler drin - sollte ich lieber als Abfrage die Variante " ["$SELF:IstSommer: on"] " nehmen?

Da ich die Readings "IstSommer" und "FreigabeKuehlen" als "Schalter" verwenden möchte, sind das keine z.B. KNX Devices. Sie sollen im Moment eher als "Platzhalter" dienen, bis ich das auch noch "von Außen" steueren werde.

Letztendlich will ich nachfolgendes realisieren (Herauskopiert aus "DEF" in der Weboberfläche, daher nicht ganz komplett:


(([$SELF:IstSommer] eq "off") and (([$SELF:MaxTempdiff] > 0.4) or [$SELF:MaxTempdiffhi] > 0.3))
((set Heizung_Zwang_EG_Arbeit,Heizung_Zwang_EG_Flur,Heizung_Zwang_EG_Wohnen_Kueche off))
((set Heizung_Zwang_KG_Arbeiten,Heizung_Zwang_KG_Bad,Heizung_Zwang_KG_Flur,Heizung_Zwang_KG_Wohnen_Kueche off))
((set Heizung_Zwang_OG_Abstell,Heizung_Zwang_OG_Bad,Heizung_Zwang_OG_Flur,Heizung_Zwang_OG_Kind_Nord off))
((set Heizung_Zwang_OG_Kind_Sued,Heizung_Zwang_OG_Schlafen,Heizung_Zwang_OG_WC off))
(set HPSU_Set Raumtemperatur 21)
(set HPSU_Set BMode Heizen)
DOELSEIF (([$SELF:IstSommer] eq "off") and ([$SELF:MaxTempdiff] <= 0.2 and [$SELF:MaxTempdiffhi] <= 0.1))
((set Heizung_Zwang_EG_Arbeit,Heizung_Zwang_EG_Flur,Heizung_Zwang_EG_Wohnen_Kueche on))
((set Heizung_Zwang_KG_Arbeiten,Heizung_Zwang_KG_Bad,Heizung_Zwang_KG_Flur,Heizung_Zwang_KG_Wohnen_Kueche on))
((set Heizung_Zwang_OG_Abstell,Heizung_Zwang_OG_Bad,Heizung_Zwang_OG_Flur,Heizung_Zwang_OG_Kind_Nord on))
((set Heizung_Zwang_OG_Kind_Sued,Heizung_Zwang_OG_Schlafen,Heizung_Zwang_OG_WC on))
(set HPSU_Set BMode Absenken)
DOELSEIF (([$SELF:FreigabeKuehlen] eq "on") and ([$SELF:IstSommer] eq "on")
          and ([09:00-11:30] or [13:00-19:00]))
((set Heizung_Zwang_EG_Arbeit,Heizung_Zwang_EG_Flur on))
((set Heizung_Zwang_KG_Bad,Heizung_Zwang_KG_Flur,Heizung_Zwang_KG_Wohnen_Kueche on))
((set Heizung_Zwang_OG_Abstell,Heizung_Zwang_OG_Bad,Heizung_Zwang_OG_Flur,Heizung_Zwang_OG_Kind_Nord on))
((set Heizung_Zwang_OG_Kind_Sued,Heizung_Zwang_OG_Schlafen,Heizung_Zwang_OG_WC on))
(set HPSU_Set Raumtemperatur 19)
(set HPSU_Set BMode Sommer)
DOELSEIF (([$SELF:IstSommer] eq "on"))
((set Heizung_Zwang_EG_Arbeit,Heizung_Zwang_EG_Flur,Heizung_Zwang_EG_Wohnen_Kueche off))
((set Heizung_Zwang_KG_Arbeiten,Heizung_Zwang_KG_Bad,Heizung_Zwang_KG_Flur,Heizung_Zwang_KG_Wohnen_Kueche off))
((set Heizung_Zwang_OG_Abstell,Heizung_Zwang_OG_Bad,Heizung_Zwang_OG_Flur,Heizung_Zwang_OG_Kind_Nord off))
((set Heizung_Zwang_OG_Kind_Sued,Heizung_Zwang_OG_Schlafen,Heizung_Zwang_OG_WC off))
(set HPSU_Set BMode Sommer)

...

attr wait 0,0,0,0,0,300:0,0,0,0,0:0,0,0,0,0,300:0,0,0,0,0



Danke schon Mal für Tipps.

Gruß
Axel H.

Otto123

Hallo Axel,

mich stört das hier -> (set HPSU_Set BMode Sommer)\

Damit ist die DEF dort nicht zu Ende. Keine Ahnung was damit passieren kann.

Ansonsten funktioniert dein Beispiel bei mir.

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

ahermann86

Hallo Otto,

- das  \ und \CR\LF  habe ich gelöscht - keine Besserung.
- (set HPSU_Set BMode Sommer) habe ich ersetzt durch (setreading di_BMode Test 1) bzw. (setreading di_BMode Test 2) - keine Besserung.

...

Nur so funktioniert es:



define di_BMode DOIF (([$SELF:IstSommer] eq "off") and ([$SELF:FreigabeKuehlen] eq "off"))\
(setreading di_BMode Test 1)\
DOELSEIF (([$SELF:IstSommer] eq "on"))\
(setreading di_BMode Test 2)
setuuid di_BMode 5d09e62c-f33f-a47e-0b43-445a331d377f323b
attr di_BMode DOIF_Readings MaxTempdiff:[#max:"^Temperatur":"diff"], MaxTempdiffhi:[#max:"^Temperatur":"diffhi"]
attr di_BMode event-on-change-reading .*
attr di_BMode event_Readings PV_Ueberschuss_Avg:[Pikoread:Akt_Ueberschuss:avg60]
attr di_BMode readingList IstSommer FreigabeKuehlen
attr di_BMode room Heizung_HPSU
attr di_BMode setList IstSommer:on,off FreigabeKuehlen:on,off


Und so geht's nicht:


define di_BMode DOIF (["$SELF:IstSommer: off"] and ["$SELF:FreigabeKuehlen: off"])\
(setreading di_BMode Test 1)\
DOELSEIF (["$SELF:IstSommer: on"])\
(setreading di_BMode Test 2)
...


Was ist an den Kurzformen "["$SELF:IrgendeinInternesReading: off"]"  falsch? Durch Klammern der [] Befehle hat es natürlich auch nicht funktioniert...


Nur zur Info:
Das "set HPSU_Set BMode Sommer" ruft über ein Dummy Device ein Notify auf:


define notHPSU_Set notify HPSU_Set.*\
{\
  if ( $EVTPART0 eq 'Warmwasser')\
  {\
    system("pyHPSU.py -d HPSUD -c t_dhw_setpoint1:".sprintf("%.02f", $EVTPART1)." &")\
  }\
  if ( $EVTPART0 eq 'Raumtemperatur')\
  {\
    system("pyHPSU.py -d HPSUD -c t_room1_setpoint:".sprintf("%.02f", $EVTPART1)." &")\
  }\
  if ( $EVTPART0 eq 'BMode')\
  {\
    my $var = 3;;\
\
    if ( $EVTPART1 eq 'Bereitschaft' ) { $var = 1;; }\
    if ( $EVTPART1 eq 'Heizen' ) { $var = 3;; }\
    if ( $EVTPART1 eq 'Absenken' ) { $var = 4;; }\
    if ( $EVTPART1 eq 'Sommer' ) { $var = 5;; }\
    if ( $EVTPART1 eq 'Kühlen' ) { $var = 17;; }\
    if ( $EVTPART1 eq 'Auto1' ) { $var = 11;; }\
    if ( $EVTPART1 eq 'Auto2' ) { $var = 12;; }\
    system("pyHPSU.py -d HPSUD -c mode_01:".sprintf("%.02f", $var)." &")\
  }\
}


Mit dem & Operator am Ende des System Befehls sollte das ganze nicht Blockierend sein. Das ganze wird dann in eine Schleife eingequed...

Gruß
Axel

Otto123

#3
Hallo Axel,

das ist jetzt viel Stoff deshalb erstmal zu den "Kurzformen" - das sind keine Kurzformen, das ist etwas völlig Anderes!
Das ist eine Bedingung: ([$SELF:FreigabeKuehlen] eq "off"), wenn dein DOIF getriggert wird (durch was auch immer) wird diese Bedingung ausgewertet.
Das ist die Auswertung eines Events: ["$SELF:FreigabeKuehlen: off"], dieser Ausdruck wird in dem Moment wahr, wenn ein Event eintritt der diesem regExp entspricht, der also diesen Text "$SELF:FreigabeKuehlen: off" im Event enthält.
Das Konstrukt ist technisch gesehen nie wahr: (["$SELF:IstSommer: off"] and ["$SELF:FreigabeKuehlen: off"]) weil keine zwei Events zur gleichen Zeit auftreten können!
Zwei Bedingungen können natürlich mit and verknüpft werden aber zwei Events nicht!

Siehe dazu auch die Doku:
https://commandref.fhem.de/commandref_DE.html#DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

Ich sagte ja Dein Beispiel funktioniert, jetzt hast Du quasi on und off vertauscht und Du sagst auch es funktioniert :) ::)

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

ahermann86

#4
Naja, das on und off habe ich vertauscht, dass ich zum Testen nicht beide ändern muss  ;D

Die Erklärung mit den Events, ist mir jetzt völlig klar geworden - Danke dafür  ;)
Die " in den [] markieren einen Regex ..

..das steht zwar alles in der Commandref. Wenn man aber nicht weiß, nach was man suchen soll, findet man das ohne Hilfe leider nicht.

Nun zu meinem neuen Erfolgserlebnis - das funktioniert:

Bedinung: IstSommer ist und bleibt dauerhaft on - FreigabeKuehlen wird getoggelt und es funktioniert wie erwartet.


define di_BMode DOIF ([$SELF:FreigabeKuehlen] eq "on" and [$SELF:IstSommer] eq "on"\
          and ([09:00-11:30] or [13:00-22:00]))\
(setreading di_BMode Test 1)\
DOELSEIF ([$SELF:FreigabeKuehlen] eq "off" and [$SELF:IstSommer] eq "on")\
(setreading di_BMode Test 2)


Das hier hingegen funktioniert nicht:

Bedinung: wie oben.

Ausgeführt wird nur cmd_1. Ja ich weiß, das hätte man mit einem DOELSE lösen können - will ich aber nicht, da ich es verstehen möchte.


define di_BMode DOIF ([$SELF:FreigabeKuehlen] eq "on" and [$SELF:IstSommer] eq "on"\
          and ([09:00-11:30] or [13:00-22:00]))\
(setreading di_BMode Test 3)\
DOELSEIF ([$SELF:IstSommer] eq "on")\
(setreading di_BMode Test 4)


Vermutlich liegt das daran, dass sich ([$SELF:IstSommer] eq "on") nicht mehr ändert..? Leider nicht ganz verständlich, da das eine Bedingung ist  :o

Otto123

#5
Du hast drei Bedingungen die mit and verknüpft sind, alle drei müssen wahr sein damit das gesamt Ergebnis war wird.
Eine der drei Bedingungen wird separat nochmal genauso im zweiten Zweig geprüft.
([$SELF:IstSommer] eq "on")
Wenn der erste Zweig war wird, wird der zweite Zweig nicht mehr geprüft. So funktioniert DOIF :)
Steht ausführlich ganz am Anfang der Doku :)
https://commandref.fhem.de/commandref_DE.html#DOIF

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

ahermann86

#6
Das ist klar, wenn eine Bedinung im DOIF erfüllt ist, werden die nachfolgenden nicht mehr überprüft und ausgeführt. Für mich als beruflicher C Programmierer ist das ein else if und die Funktion damit klar  8)

Das DOIF habe ich bereits in der Commandref und in der Wiki duchgelesen und daher für meine nicht ganz einfache Abfrage DIE Lösung ausgewählt - da Timer avg .....  ;D

In meinem Beispiel ist es tatsächlich so, dass der erste Zweig nicht ausgeführt wird wenn [$SELF:FreigabeKuehlen] eq "off" ist. Den nächsten möchte ich aber trotzdem ausführen, weil zumindest [$SELF:IstSommer] eq "on" erfüllt ist.

Otto123

#7
naja dann muss das DOIF nochmal triggern. Das passiert aber in dem Moment wo Du
[$SELF:FreigabeKuehlen] eq "off" setzt. Das DOIF wird getriggert, der erste Zweig ist nicht wahr, der zweite Zweig wird wahr.

Aber Du hast Recht, das tut er nicht.   :-[ Deswegen?
ZitatZu beachten ist, dass nur die Bedingungen überprüft werden, die zum ausgelösten Event das dazughörige Device bzw. die dazugehörige Triggerzeit beinhalten.

Verschieb das Ganze besser nach DOIF, vielleicht sagt dort Damian was dazu :)

Edit: hat er schon  ;) ich lag richtig :)
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

Damian

Zitat von: ahermann86 am 23 Juni 2019, 21:50:48
Das ist klar, wenn eine Bedinung im DOIF erfüllt ist, werden die nachfolgenden nicht mehr überprüft und ausgeführt. Für mich als beruflicher C Programmierer ist das ein else if und die Funktion damit klar  8)

Das DOIF habe ich bereits in der Commandref und in der Wiki duchgelesen und daher für meine nicht ganz einfache Abfrage DIE Lösung ausgewählt - da Timer avg .....  ;D

In meinem Beispiel ist es tatsächlich so, dass der erste Zweig nicht ausgeführt wird wenn [$SELF:FreigabeKuehlen] eq "off" ist. Den nächsten möchte ich aber trotzdem ausführen, weil zumindest [$SELF:IstSommer] eq "on" erfüllt ist.

Wichtig ist noch dieser Satz aus der Commandref:

ZitatZu beachten ist, dass nur die Bedingungen überprüft werden, die zum ausgelösten Event das dazughörige Device bzw. die dazugehörige Triggerzeit beinhalten.

Im Gegensatz zu einer if-else if-Abfrage werden bei einem Trigger nicht alle Zweige abgefragt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

ahermann86