diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index 589f9e590..5369c9bab 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -884,22 +884,22 @@ The state administration is an important distinguishing feature of DOIF to notif
Syntax:
-define <name> DOIF (condition) (commands) DOELSEIF (condition) (commands) DOELSEIF ... DOELSE (commands)
+define <name> DOIF (<condition>) (<commands>) DOELSEIF (<condition>) (<commands>) DOELSEIF ... DOELSE (<commands>)
The commands are always processed from left to right. There is only one command executed, namely the first, for which the corresponding condition in the processed sequence is true. In addition, only the conditions are checked, which include a matching device of the trigger (in square brackets).
Features
[<devicename>], readings with [<devicename>:<readingname>][HH:MM:SS] or [HH:MM] or [{<perl-function>}][<begin>-<end>] for <begin> and <end>, the above time format can be selected.[<time>|012345678] or [<begin>-<end>|012345678] (0-6 corresponds to Sunday through Saturday) such as 7 for $we and 8 for !$we[<device>:<reading>:<format>|[<regular expression>]] or [<device>:&<internal>:<format>|[<regular expression>]]<format> and [<regular expression>] are filter options und are optional.<format>:'d' for decimal number.[<device>:<reading>:d] corresponsed to [<device>:<reading>:[(-?\d+(\.\d+)?)]][<device>] corresponsed to [<device>:&STATE]define <name> DOIF (<Bedingung>) (<Befehle>) DOELSEIF (<Bedingung>) (<Befehle>) DOELSEIF ... DOELSE (<Befehle>)[<devicename>], Readings mit [<devicename>:<readingname>] in der Bedingung sowie bei FHEM-Befehlen angegeben[HH:MM:SS] oder [HH:MM] oder [{<perl-function>}][<begin>-<end>] für <begin> bzw. <end> kann das obige Zeitformat gewählt werden[<time>|012345678] oder [<begin>-<end>|012345678] (0-6 entspricht Sonntag bis Samstag) sowie 7 für $we und 8 für !$we[<device>:<reading>:<format>|[<regulärer Ausdruck>]] bzw. [<device>:&<internal>:<format>|[<regulärer Ausdruck>]]<format> und [<regulärer Ausdruck>] sind Filteroptionen, sie können optional genutzt werden.<format> sind:'d' zum Filtern von positiven und negativen Dezimalzahlen.[<device>:<reading>:d] entspricht [<device>:<reading>:[(-?\d+(\.\d+)?)]][<device>] entspricht [<device>:&STATE]define DI_garage DOIF ([remotecontrol] eq "on") (set garage on) DOELSEIF ([remotecontrol] eq "off") (set garage off)define di_garage DOIF ([remotecontrol] eq "on") (set garage on) DOELSEIF ([remotecontrol] eq "off") (set garage off)attr DI_garage do alwaysattr di_garage do alwaysdefine DI_light DOIF ([08:00]) (set switch on,set lamp on) DOELSEIF ([10:00]) (set switch off,set lamp off)define di_light DOIF ([08:00]) (set switch on,set lamp on) DOELSEIF ([10:00]) (set switch off,set lamp off)define DI_light DOIF ([08:00]) ((set lamp1,lamp2 on),set switch on)define di_light DOIF ([08:00]) ((set lamp1,lamp2 on),set switch on)define DI_light DOIF ([08:00] or [10:00] or [20:00]) (set switch on) DOELSEIF ([09:00] or [11:00] or [00:00]) (set switch off)define di_light DOIF ([08:00] or [10:00] or [20:00]) (set switch on) DOELSEIF ([09:00] or [11:00] or [00:00]) (set switch off)define DI_radio DOIF ([08:00-10:00]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00]) (set radio on) DOELSE (set radio off) define DI_radio DOIF ([08:00-10:00] or [20:00-22:00]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00] or [20:00-22:00]) (set radio on) DOELSE (set radio off) define DI_radio DOIF ([08:00-10:00|06]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00|06]) (set radio on) DOELSE (set radio off) define DI_radio DOIF ([08:00-10:00|135]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00|135]) (set radio on) DOELSE (set radio off) define DI_radio DOIF ([08:00-10:00|7]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00|7]) (set radio on) DOELSE (set radio off) define DI_radio DOIF ([08:00-10:00|8]) (set radio on) DOELSE (set radio off) define di_radio DOIF ([08:00-10:00|8]) (set radio on) DOELSE (set radio off) define DI_light DOIF ([22:00-07:00]) (set light on) DOELSE (set light off) define di_light DOIF ([22:00-07:00]) (set light on) DOELSE (set light off) define DI_light DOIF ([22:00-07:00|5]) (set light on) DOELSE (set light off) define di_light DOIF ([22:00-07:00|5]) (set light on) DOELSE (set light off) define DI_light DOIF ([22:00|5]) (set light on) DOELSEIF ([10:00|1]) (set light off) define di_light DOIF ([22:00|5]) (set light on) DOELSEIF ([10:00|1]) (set light off) define DI_light DOIF ([{sunset(0,"17:00","21:00")}-{sunset_abs()}]) (set outdoorlight off) DOELSE (set outdoorlight on)define di_light DOIF ([{sunset(0,"17:00","21:00")}-{sunset_abs()}]) (set outdoorlight off) DOELSE (set outdoorlight on)define DI_shutters DOIF ([sensor:brightness]>100 and [06:25-09:00|8] or [09:00|7]) (set shutters on)define DI_lamp DOIF ([06:00-09:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)define di_lamp DOIF ([06:00-09:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)define DI_Rolladen DOIF ([sensor:brightness]>100 and [06:25-09:00|8] or [09:00|7])) (set shutters on)define di_shutters DOIF ([sensor:brightness]>100 and [06:25-09:00|8] or [09:00|7]) (set shutters up) DOELSEIF ([sensor:brightness]<50) (set shutters down)setreading sensor default 20
-setreading sensor hysteresis 1
+Wenn ein Taster betätigt wird, soll Lampe1 mit dem aktuellen Zustand der Lampe2 geschaltet werden:
-define DI_threshold DOIF ([sensor:temperature]<([sensor:default]-[sensor:hysteresis])) (set heating on) DOELSEIF ([sensor:temperature]>[sensor:default]) (set heating off)define DI_button DOIF ([button]) (set lamp1 [lamp2])
+define di_button DOIF ([button]) (set lamp1 [lamp2])
attr di_button do always
+Benachrichtung beim Auslösen eines Alarms durch Öffnen eines Fensters:
+
+define di_pushmsg DOIF ([window] eq "open" and [alarm] eq "armed") (set Pushover msg 'alarm' 'open windows [window:LastDevice]' '' 2 'persistent' 30 3600)
+
Berechnungen im FHEM-Ausführungsteil können mit geschweiften Klammern erfolgen. Aus Kompatibilitätsgründen zu bestehenden FHEM-Befehlen (insb. at) muss der Perlausdruck hinter der geschweiften Klammer auf mit einer runden Klammer beginnen. Innerhalb der Perlberechnung können Readings, Stati oder Internals wie gewohnt in eckigen Klammern angegeben werden.
Es soll ein Vorgabewert aus zwei verschiedenen Readings ermittelt werden und an das set Kommando übergeben werden:
-define DI_average DOIF ([08:00]) (set TH_Modul desired {([default:temperature]+[outdoor:temperature])/2})
-attr DI_average do always
+define di_average DOIF ([08:00]) (set TH_Modul desired {([default:temperature]+[outdoor:temperature])/2})
+attr di_average do always
-Filtern nach Zahlen
+Filtern nach Zahlen
-Es soll aus einem Reading, der z. B. ein Prozentzeichen beinhaltet, nur der Zahlenanteil für den Vergleich genutzt werden.
+Es soll aus einem Reading, der z. B. ein Prozentzeichen beinhaltet, nur der Zahlenanteil für den Vergleich genutzt werden:
-define DI_heating DOIF ([adjusting:actuator:d] < 10) (set heating off) DOELSE (set heating on)
+define di_heating DOIF ([adjusting:actuator:d] < 10) (set heating off) DOELSE (set heating on)
+
+Verzögerungen
Verzögerungen für die Ausführung von Kommandos werden pro Kommando über das Attribut "wait" definiert. Syntax:
-attr <Modulname> wait <Sekunden für das erste Kommando>:<Sekunden für das zweite Kommando>:...
+attr <Modulname> wait <Sekunden für das erste Kommando>:<Sekunden für das zweite Kommando>:...
-Die Sekundenangaben können von hinten weggelassen werden. Die Verzögerungen werden nur auf Events angewandt und nicht auf Zeitsteuerung. Eine bereits ausgelöste Verzögerung wird zurückgesetzt, wenn während der Wartezeit ein anders Kommando, ausgelöst durch ein neues Ereignis, ausgeführt werden soll.
-
-Beispiele mit Verzögerung:
+Die Sekundenangaben können von hinten ausgelassen werden. Die Verzögerungen werden nur auf Events angewandt und nicht auf Zeitsteuerung. Eine bereits ausgelöste Verzögerung wird zurückgesetzt, wenn während der Wartezeit ein anders Kommando, ausgelöst durch ein neues Ereignis, ausgeführt werden soll.
Benachrichtung: "Waschmaschine fertig", wenn Verbrauch mindestens 5 Minuten unter 2 Watt (Perl-Code wird in geschweifte Klammern gesetzt):
-define DI_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
-attr DI_washer wait 300
+define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
+attr di_washer wait 300
Eine erneute Benachrichtigung wird erst wieder ausgelöst, wenn zwischendurch der Verbrauch über 2 Watt angestiegen war.
Rolladen um 20 Minuten zeitverzögert bei Sonne runter- bzw. hochfahren (wenn der Zustand der Sonne wechselt, wird die Verzögerungszeit zurückgesetzt):
-define DI_shutters DOIF ([Sun] eq "on") (set shutters down) DOELSE (set shutters up)
-attr DI_shutters wait 1200:1200
+define di_shutters DOIF ([Sun] eq "on") (set shutters down) DOELSE (set shutters up)
+attr di_shutters wait 1200:1200
-Beschattungssteuerung abhängig von der Temperatur: Der Rollladen soll runter von 11:00 Uhr bis Sonnenuntergang, wenn die Temperatur über 26 Grad ist. Temperaturschwankungen um 26 Grad werden mit Hilfe des wait-Attributes durch eine 15 minutige Verzögerung ausgeglichen.
+Beschattungssteuerung abhängig von der Temperatur. Der Rollladen soll runter von 11:00 Uhr bis Sonnenuntergang, wenn die Temperatur über 26 Grad ist. Temperaturschwankungen um 26 Grad werden mit Hilfe des wait-Attributes durch eine 15 minutige Verzögerung ausgeglichen.
-define DI_shutters DOIF ([sensor:temperature] > 26 and [11:00-{sunset_abs()}] (set shutters down) DOELSE (set shutters up)
-attr DI_shutters wait 900:900
+define di_shutters DOIF ([sensor:temperature] > 26 and [11:00-{sunset_abs()}] (set shutters down) DOELSE (set shutters up)
+attr di_shutters wait 900:900
-Belüftung in Kombination mit einem Lichtschalter mit Nachlaufsteuerung:
+Belüftung in Kombination mit einem Lichtschalter mit Nachlaufsteuerung. Der Lüfter soll angehen, wenn das Licht mindestens 2 Minuten lang brennt oder die Luftfeuchtigkeit 65 % überschreitet, der Lüfter soll ausgehen, drei Minuten nachdem die Luftfeuchtigkeit unter 60 % fällt und das Licht aus ist bzw. das Licht ausgeht und die Luftfeuchtigkeit unter 60% ist. Definitionen lassen sich über die Weboberfläche (DEF-Eingabebereich) übersichtlich gestalten:
-Der Lüfter soll angehen, wenn das Licht mindestens 2 Minuten lang brennt oder die Luftfeuchtigkeit 65 % überschreitet, der Lüfter soll ausgehen, drei Minuten nachdem die Luftfeuchtigkeit unter 60 % fällt und das Licht aus ist bzw. das Licht ausgeht und die Luftfeuchtigkeit unter 60% ist. Definitionen lassen sich über die Weboberfläche (DEF-Eingabebereich) übersichtlich gestalten:
-
-define DI_fan DOIF ([light] eq "on")
+define di_fan DOIF ([light] eq "on")
(set fan on)
@@ -1130,10 +1123,11 @@ DOELSEIF ([light] eq "off" and [sensor:humidity]<60)
(set fan off)
-attr DI_fan wait 120:0:180
+attr di_fan wait 120:0:180
+Status des Moduls
-Der Status des Moduls wird standardmäßig mit cmd_1, cmd_2, usw. belegt. Dieser lässt sich über das Attribut "cmdState" mit | getrennt festlegen:
+Der Status des Moduls wird standardmäßig mit cmd_1, cmd_2, usw. belegt. Dieser lässt sich über das Attribut "cmdState" mit | getrennt umdefinieren:
attr <Modulname> cmdState <Status für das erste Kommando>|<Status für das zweite Kommando>|...
@@ -1143,12 +1137,12 @@ z. B.
Wenn nur der DOIF-Fall angegeben wird, so wird, wenn Bedingung nicht erfüllt ist, ein cmd_2-Status gesetzt. Damit wird ein Zustandswechsel des Moduls erreicht, was zur Folge hat, dass beim nächsten Wechsel von false auf true das DOIF-Kommando erneut ausgeführt wird.
-Reine Statusanzeige ohne Ausführung von Befehlen. Der Ausführungsteil kann jeweils ausgelassen werden.
+Reine Statusanzeige ohne Ausführung von Befehlen. Der Ausführungsteil kann jeweils ausgelassen werden:
-define DI_humiditystate DOIF ([outdoor:humidity]>70) DOELSEIF ([outdoor:humidity]>50) DOELSE
+define di_humiditystate DOIF ([outdoor:humidity]>70) DOELSEIF ([outdoor:humidity]>50) DOELSE
attr di_hum cmdState wet|normal|dry
-Anpassung des Status mit Hilfe des Attributes "state". Es können beliebige Reading und Stati oder Internals angegeben werden.
+Anpassung des Status mit Hilfe des Attributes "state". Es können beliebige Reading und Stati oder Internals angegeben werden:
attr di_hum state The current humidity is [outdoor:humidity], it is [di_hum]
@@ -1156,30 +1150,54 @@ Es können beim Attribut state ebenfalls, wie bei FHEM-Befehlen im Ausführungst
Berechnung des Mittelwertes zweier Readings:
-define DI_average DOIF
-attr DI_average state Average of the two rooms is {([room1:temperature]+[room2:temperature])/2}
+define di_average DOIF
+attr di_average state Average of the two rooms is {([room1:temperature]+[room2:temperature])/2}
Da man beliebige Perl-Ausdrücke verwenden kann, lässt sich z. B. der Mittelwert auf eine Stelle mit der Perlfunktion sprintf formatieren:
-attr DI_average state Average of the two rooms is {(sprintf("%.1f",([room1:temperature]+[room2:temperature])/2))}
+attr di_average state Average of the two rooms is {(sprintf("%.1f",([room1:temperature]+[room2:temperature])/2))}
+Weitere Anwendungsbeispiele
+
+Zweipunktregler a la THRESHOLD
+
+setreading sensor default 20
+setreading sensor hysteresis 1
+
+define di_threshold DOIF ([sensor:temperature]<([sensor:default]-[sensor:hysteresis])) (set heating on) DOELSEIF ([sensor:temperature]>[sensor:default]) (set heating off)
+
+Eleganter lässt sich ein Zweipunktregler (Thermostat) mit Hilfe des, für solche Zwecke, spezialisierten THRESHOLD-Moduls realisieren, siehe: THRESHOLD
+
+on-for-timer
+
+Die Nachbildung eines on-for-timers lässt sich mit zwei DOIF´s und einem Dummy realisieren:
+
+define switch_d dummy
+
+define di_switch DOIF ([detector] eq "motion") (set switch_d on, set switch_d off)
+attr di_switch do always
+
+define di_light DOIF ([switch_d] eq "on") (set light on) DOELSE (set light off)
+attr di_light wait 0:300
+
+Hiermit wird das Licht bei Bewegung eingeschaltet. Dabei wird, solange es brennt, bei jeder Bewegung die Ausschaltzeit auf 5 Minuten neugesetzt, "set light on" wird dabei nicht unnötig wiederholt.
Die Beispiele stellen nur eine kleine Auswahl von möglichen Problemlösungen dar. Da sowohl in der Bedingung (hier ist die komplette Perl-Syntax möglich), als auch im Ausführungsteil, keine Einschränkungen gegeben sind, sind die Möglichkeiten zur Lösung eigener Probleme mit Hilfe des Moduls sehr vielfältig.
-Zu beachten ist:
+Zu beachten
In jeder Bedingung muss mindestens ein Reading oder ein Status (Internal) oder eine Zeitangabe gemacht werden (Angaben in eckigen Klammern). Die entsprechenden DO-Fälle werden nur dann ausgewertet, wenn auch das entsprechende Event oder Zeit-Trigger ausgelöst wird.
Zeitangaben der Art:
-define DI_light DOIF ([08:00] and [10:00]) (set switch on)
+define di_light DOIF ([08:00] and [10:00]) (set switch on)
sind nicht sinnvoll, da diese Bedingung nie wahr sein wird.
Angaben, bei denen aufgrund der Definition kein Zustandswechsel erfolgen kann z. B.:
-define DI_light DOIF ([08:00]) (set switch on)
-attr DI_light do always
+define di_light DOIF ([08:00]) (set switch on)
+attr di_light do always
müssen mit Attribut "do always" definiert werden, damit sie nicht nur einmal, sondern jedes mal (hier jeden Tag) ausgeführt werden.
@@ -1187,25 +1205,29 @@ Bei Devices, die mit Zwischenzuständen arbeiten, insbesondere HM-Komponenten (Z
statt:
-define DI_lamp DOIF ([HM_switch] eq "on") (set lamp on) DOELSE (set lamp off)
+define di_lamp DOIF ([HM_switch] eq "on") (set lamp on) DOELSE (set lamp off)
konkreter spezifizieren:
-define DI_lamp DOIF ([HM_switch] eq "on") (set lamp on) DOELSEIF ([HM_switch] eq "off") (set lamp off)
+define di_lamp DOIF ([HM_switch] eq "on") (set lamp on) DOELSEIF ([HM_switch] eq "off") (set lamp off)
Namenskonvention: Da der Doppelpunkt bei Readingangaben als Trennzeichen gilt, darf er nicht im Namen des Devices vorkommen. In solchen Fällen bitte das Device umbenennen.
+Da innerhalb eines DOIF-Moduls festgehalten wird, welches Kommando zuletzt ausgeführt wurde (Zustandsverwaltung), so wird das Wiederholen desselben Kommmandos vom Modul unterbunden.
+Daher sollte nach Möglichkeit eine Problemlösung mit Hilfe eines und nicht mehrerer DOIF-Module realisiert werden, getreu dem Motto "wer die Lampe einschaltet, soll sie auch wieder ausschalten".
+Dadurch wird erreicht, dass unnötiges (wiederholendes) Schalten vom Modul unterbunden werden kann, ohne dass sich der Anwender selbst darum kümmern muss.
+
Mehrere Bedingungen, die zur Ausführung gleicher Kommandos führen, sollten zusammengefasst werden. Dadurch wird ein unnötiges Schalten aufgrund verschiedener Zustände verhindert.
Beispiel:
-define DI_lamp DOIF ([brightness] eq "off") (set lamp on) DOELSEIF ([19:00]) (set lamp on) DOELSE (set lamp off)
+define di_lamp DOIF ([brightness] eq "off") (set lamp on) DOELSEIF ([19:00]) (set lamp on) DOELSE (set lamp off)
-Hier wird um 19:00 Uhr Lampe eingeschaltet, obwohl sie evtl. vorher schon durch das Ereignis Helligkeit off eingeschaltet wurde.
+Hier wird um 19:00 Uhr Lampe eingeschaltet, obwohl sie evtl. vorher schon durch das Ereignis brightness "off" eingeschaltet wurde.
-define DI_lamp DOIF ([brightness] eq "off" or [19:00]) (set lamp on) DOELSE (set lamp off)
+define di_lamp DOIF ([brightness] eq "off" or [19:00]) (set lamp on) DOELSE (set lamp off)
-Hier passiert das nicht mehr, da die ursprünglichen Zustände cmd1 und cmd2 jetzt nur noch einen Zustand cmd1 darstellen und dieser wird nicht wiederholt.
+Hier passiert das nicht mehr, da die ursprünglichen Zustände cmd_1 und cmd_2 jetzt nur noch einen Zustand cmd_1 darstellen und dieser wird nicht wiederholt.
=end html_DE