Hauptmenü

DOIF mit mehreren DOIF-Zweigen

Begonnen von Damian, 03 Mai 2015, 22:23:50

Vorheriges Thema - Nächstes Thema

Damian

Ich habe folgende Option auf die todo-Liste gesetzt:

Mehrere DOIF-Fälle:

define di DOIF (...) (...)
DOELSEIF (...) (...)
DOELSE (...)
DOIF (...) (...)
DOELSEIF (...) (...)
DOELSE (...)

DOELSEIF und DOELSE beziehen sich immer auf den vorhergehenden DOIF-Fall.

Beispiele:

on-for-timer:

define onfortimer DOIF ([Event]) (set lamp on)
                  DOIF ([Event]) (set lamp off)
attr onfortimer wait 0:400


Doppelklick (bei Doppelklick rollo hoch, beim einfachen runter)

define doppelklick DOIF ([Event]) (set Rollo hoch)
                   DOIF ([Event]) (set Rollo runter)
attr doppelklick waitsame 2:0
attr doppelklick waitdel 0:2


Damit ließen sich einige Probleme in einem Modul lösen.

Edit: Hier noch eine Alternative mit mehreren Kommandos pro Bedingung, nach der Syntax DOIF (...) (...) (...). Dann würde es so aussehen:

on-for-timer:

define onfortimer DOIF ([Event]) (set lamp on)
                                 (set lamp off)
attr onfortimer wait 0:400


Doppelklick (bei Doppelklick rollo hoch, beim einfachen runter)

define doppelklick DOIF ([Event]) (set Rollo hoch)
                                  (set Rollo runter)
attr doppelklick waitsame 2:0
attr doppelklick waitdel 0:2




Gruß

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

fheminist

#1
Hallo Damian,

erst einmal großes Lob an Dich und alle, die das DOIF Modul entwickelt haben. Ich war eigentlich dabei, so auf andere Geräte umzustellen, dass ich auch auf andere Plattformen wechseln kann. Wegen dem Doif-Modul habe ich FHEM neu schätzen und echt lieben gelernt. Bin im Automatisierungs & Digitalisierungsbereich tätig, programmiere daher viel. Bei Pearl habe ich allerdings echt Schreikrämpfe bekommen... Ich habe es lieber auf einem Blatt zusammenhängend, anstatt in x-Modulen hin und her zu springen *lost in space*.  Ebenfalls möchte ich nicht ständig zwischen Pearl und FHEM-code hin und her springen. Ein Standard, und den dann richtig ausschöpfen (Ausnahmen wird es immer geben, schon klar ;-) ).
Habe wirklich große DOIFs die auch schön laufen. Mein 'Glück' war immer, dass die Stränge sich nicht gegenseitig beeinflusst haben, oder man konnte es mindestens mit set cmd_x beheben. Nun ist Winter gekommen und ich komme zum Heizen, das war noch nicht auf DOIF umgestellt  ::).  Hier gibt es viele Sachen, die sich zeitlich, unabhängig von einander beeinflussen könnten. Mit dem IF-Statement (auch ein sehr schönes Modul. Favo2  :D)  Gibt es aber allerdings wieder andere Syntax ...  ::) .  Hier habe ich erneut zu kämpfen und fühle mich wieder zurück geworfen... gerade die unterschiede mit der Zeit-Syntax macht mir zu schaffen.

Wollte daher mal, der Vereinheitlichung wegen gaaanz nett fragen, ob man
1.) die zeitliche Syntax aus dem DOIF, auch ins IF-Modul übernehmen könnte, oder
2.) dein oben genannten Vorschlag umsetzen kann?

Favorisieren würde ich zweitens, da man damit auch viele viele andere Sachen vereinfachen kann. Eigentlich betrifft das dann nahezu alles, was mit "set cmd_x" manipuliert wird.
Das ist nicht schön, da sich auch die Anzahl der DOIF-Stänge verändern können, daher schreibe ich mir als Kommi auch meistens die Nummer des DOIFs-Zweiges rein...  Nach Änderungen muss man immer aufpassen wie Lux, damit die Nummern wieder zu den Zweigen passen. Mit deinem Vorschlag im 1. Post würde das eine sehr runde, einfache Sache sein.

Hier mein aktuelles Beispiel:

• Nach der Umsetzung:
-- ------------------------------------------------------

([Switch_Heizung:state] eq "on" and
( ( [05:45|AT] and [State_Urlaub:state] eq "off" ) or [State_Nachtruhe:state] eq "off" )
)
## Heizen angefordert -- AT = Werktags, 7 = WE
(set Scene_Heizung on)
(setreading $SELF HEAT on)

DOELSEIF ( [Switch_Heizung:state] eq "off" or [State_Nachtruhe:state] eq "on" )
## Anforderung aus - zur Sicherheit 3 mal kalt setzen...
(set Scene_Heizung off)

## Eg allgemeine Räume
DOIF ([$SELF:HEAT] eq "on" and [State_Kamin] eq "off")
(set WZ_temp desired-temp 21.0)
DOELSE (set WZ_temp desired-temp 17.0)
DOIF ([$SELF:HEAT] eq "on" and [tk_ElZi:state] eq "off" and [Mo Fr Sa So])
(set ElZi_temp desired-temp 20.0)
DOELSE (set ElZi_temp desired-temp 17.0)
## Bad
DOIF ([$SELF:HEAT] eq "on" and [tk_BadEG:state] eq "off" )
(set EG_Temp_Bad desired-temp 21.5)
DOELSE (set EG_Temp_Bad desired-temp 17.0)
DOIF ( [$SELF:HEAT] eq "on" and ([00:00-09:00|AT]) or [WE])
(set OG_temp_Bad desired-temp 21.0)
DOELSE (set OG_temp_Bad desired-temp 17.0)
## Zimmer Kids
DOIF ( [$SELF:HEAT] eq "on" and [tk_Leon:state] eq "off" and
( [13:00-20:00|AT] or [State_Urlaub:state] eq "on"  or [WE] )
)
(set KG_temp_LeZi desired-temp 19.5)
DOELSE (set KG_temp_LeZi desired-temp 17.0)
DOIF ( [$SELF:HEAT] eq "on" and [tk_FeZi:state] eq "off" and
( [14:00-19:00|Mo Di Mi Fr] or [State_Urlaub:state] eq "on"  or [WE] )
(set OG_temp_FeZi desired-temp 20.0)
DOELSE (set OG_temp_FeZi desired-temp 17.0)

## x faches Ausschalten .. vertrauen ist gut ...
DOIF ( [$SELF:HEAT] eq "off2" ) (setreading $SELF HEAT off)
DOELSEIF ( [$SELF:HEAT] eq "off1" ) (setreading $SELF HEAT off2)
DOELSEIF ( [Scene_Heizung:state] eq "off" and [$SELF:HEAT] eq "on" )
(setreading $SELF HEAT off1)



• Hier mein aktueller versuch (Zeiten eigentlich wie oben erwünscht... bekomme ich aber nicht hin... )
-- ------------------------------------------------------

([Switch_Heizung:state] eq "on" and
( ( [05:45|AT] and [State_Urlaub:state] eq "off" ) or [State_Nachtruhe:state] eq "off" )
)
## AT = Werktags, 7 = WE
##
(set Scene_Heizung on)
(setreading $SELF HEAT on)

DOELSEIF ( [Switch_Heizung:state] eq "off" or [State_Nachtruhe:state] eq "on" )
## Anforderung aus - zur Sicherheit 3 mal kalt setzen...
(set Scene_Heizung off)

DOELSEIF ([$SELF:HEAT] ne "off" and [+900])
## Eg allgemeine Räume
(IF ([$SELF:HEAT] eq "on" and [State_Kamin] eq "off")
(set WZ_temp desired-temp 21.0)
ELSE (set WZ_temp desired-temp 17.0)
)
(IF ([$SELF:HEAT] eq "on" and [tk_ElZi:state] eq "off" and !$we)
(set ElZi_temp desired-temp 20.0)
ELSE (set ElZi_temp desired-temp 17.0)
)
## Bad
(IF ([$SELF:HEAT] eq "on" and [tk_BadEG:state] eq "off" )
(set EG_Temp_Bad desired-temp 21.5)
ELSE (set EG_Temp_Bad desired-temp 17.0)
)
(IF ( [$SELF:HEAT] eq "on" and
($hms lt "09:00" and $hms gt "15:00" and !$we) or $we )
(set OG_temp_Bad desired-temp 21.0)
ELSE (set OG_temp_Bad desired-temp 17.0)
)
## Zimmer Kids
(IF ( [$SELF:HEAT] eq "on" and [tk_Leon:state] eq "off" and
( ($hms gt "13:00" and !$we) or [State_Urlaub:state] eq "on"  or $we ) )
(set KG_temp_LeZi desired-temp 19.5)
ELSE (set KG_temp_LeZi desired-temp 17.0)
)
(IF ( [$SELF:HEAT] eq "on" and [tk_FeZi:state] eq "off" and
( ($hms gt "14:00" and !$we) or [State_Urlaub:state] eq "on"  or $we ) )
(set OG_temp_FeZi desired-temp 20.0)
ELSE (set OG_temp_FeZi desired-temp 17.0)
)

(IF ( [$SELF:HEAT] eq "off2" ) (setreading $SELF HEAT off)  )
(IF ( [$SELF:HEAT] eq "off1" ) (setreading $SELF HEAT off2) )
(IF ( [Scene_Heizung:state] eq "off" and [$SELF:HEAT] eq "on" ) 
(setreading $SELF HEAT off1)
)




Vielen Dank und beste Grüße
3*FB-Mesh ,FHEM+MariaDB+TVH+TriaxSatIPGrafana@Docker/DS220+, 6*Kodi-RPis, EpsonTW650+DIY-Lift, 3*IPCam@TVH, 2*AI@EspCAM, Robo.S6
6*Maxcio bulbs, 15*Nodemcu&WemosD1, 20*GosundSP1, 25*Shelly, 8*MC400A, 7*CometDect, abgelöst: diyCurls, 433Mhz, JeeLink, DenonAVR, FS20, HM ...

Damian

#2
Dieser Thread war von 2015, also schon über 5 Jahre alt. Seitdem hat sich einiges im DOIF geändert.

DOIF im DOIF habe ich verworfen, weil dann das Zustandskonzept (cmd_1, cmd_2 usw. schließen sich gegenseitig aus, sie bilden jeweils einen eigenen Zustand) nicht mehr funktionieren würde.

Auch wenn es dir jetzt nicht gefallen wird, die unabhängige Blöcke im DOIF werden im DOIF-Perlmodus realisiert.

Dabei muss man nicht großartig Perl können, um seine Wünsche zu realisieren.

Konkret für deinen Fall würde es so aussehen:
DOIF
{  ## erster Block
if ([Switch_Heizung:state] eq "on" and  ([05:45|AT] and [State_Urlaub:state] eq "off" ) or [State_Nachtruhe:state] eq "off" ))
{
## Heizen angefordert -- AT = Werktags, 7 = WE
   fhem_set("Scene_Heizung on");
   set_reading("HEAT","on");
} elsif ([Switch_Heizung:state] eq "off" or [State_Nachtruhe:state] eq "on" ) {
## Anforderung aus - zur Sicherheit 3 mal kalt setzen...
   fhem_set("Scene_Heizung off");
}
}
{ ## zweiter Block
if  ([$SELF:HEAT] eq "on" and [State_Kamin] eq "off")
{
   fhem_set("WZ_temp desired-temp 21.0");
} else {
   fhem_set("WZ_temp desired-temp 17.0");
}
}
{ ## dritter Block
...
}
usw.


man kann also den FHEM-Code weitgehend 1:1 übersetzen.

Dieser Modus hat sich als sehr mächtig erwiesen, weil man so beliebig komplexe Aufgaben in einem Modul unterbringen kann, weil die Blöcke unabhängig von einander funktionieren.

Der DOIF-FHEM-Modus wird aufgrund seiner einfachen Syntax von vielen zurecht bevorzugt, allerdings sollte man nicht zu viel Funktionalität in ein Modul rein packen, sonst entstehen zu viele Abhängigkeiten, die man irgendwann nicht mehr kontrollieren kann.

Den IF-Befehl wiederum möchte ich nicht weiter erweitern, weil er keinen vollständigen Parser darstellt. Es gibt immer wieder Konstellationen mit anderen FHEM-Befehlen, die zu Problemen führen. 
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF