From 6d8c448e4d138e927195910d625ff1d5091de2ea Mon Sep 17 00:00:00 2001
From: Damian <>
Date: Wed, 3 Oct 2018 19:05:21 +0000
Subject: [PATCH] 98_DOIF.pm: use Date::Parse qw(str2time); deleted, more
Perl-Mode examples
git-svn-id: https://svn.fhem.de/fhem/trunk@17455 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/98_DOIF.pm | 285 ++++++++++++++++++++++++++-----------------
1 file changed, 173 insertions(+), 112 deletions(-)
diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index b8b0b7718..b1c62b2bc 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -3264,7 +3264,7 @@ DOIF_Get($@)
package DOIF;
-use Date::Parse qw(str2time);
+#use Date::Parse qw(str2time);
use Time::HiRes qw(gettimeofday);
sub DOIF_ExecTimer
@@ -3552,7 +3552,7 @@ Das Modul verfügt über zwei Modi: FHEM-Modus und Perl-Modus.
-Beide Modi sind innerhalb eines DOIF-Devices nicht miteinander kombinierbar. Im Folgendem wird der FHEM-Modus beschrieben.
+Beide Modi sind innerhalb eines DOIF-Devices nicht miteinander kombinierbar.
Syntax FHEM-Modus:
@@ -3566,9 +3566,8 @@ für das die dazugehörige Bedingung in der abgearbeiteten Reihenfolge wahr ist.
Das DOIF-Modul arbeitet mit Zuständen. Jeder Ausführungszweig DOIF/DOELSEIF..DOELSEIF/DOELSE stellt einen eigenen Zustand dar (cmd_1, cmd_2, usw.).
Das Modul merkt sich den zuletzt ausgeführten Ausführungszweig und wiederholt diesen standardmäßig nicht.
Ein Ausführungszweig wird erst dann wieder ausgeführt, wenn zwischenzeitlich ein anderer Ausführungszweig ausgeführt wurde, also ein Statuswechsel des DOIF-Moduls stattgefunden hat.
-Dieses Verhalten ist sinnvoll, um zu verhindern, dass zyklisch sendende Sensoren (Temperatur, Feuchtigkeit, Helligkeit, usw.) zu ständiger Wiederholung des selben Befehls oder Befehlsabfolge führen.
+Dieses Verhalten ist sinnvoll, um zu verhindern, dass zyklisch sendende Sensoren (Temperatur, Feuchtigkeit, Helligkeit, usw.) zu ständiger Wiederholung des selben Befehls oder Befehlsabfolge führen.
Das Verhalten des Moduls im FHEM-Modus kann durch diverse Attribute verändert werden. Im FHEM-Modus wird maximal nur ein Zweig pro Ereignis- oder Zeit-Trigger ausgeführt, es gibt nur einen Wait-Timer.
-
Einfache Anwendungsbeispiele (vgl. Anwendungsbeispiele im Perl-Modus):
@@ -3589,7 +3588,7 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel
Erste Schritte mit DOIF
-Inhaltsübersicht
+Inhaltsübersicht (Beispiele im Perl-Modus sind besonders gekennzeichnet)
Lesbarkeit der Definitionen
Ereignissteuerung
@@ -3641,9 +3640,6 @@ Eine ausführliche Erläuterung der obigen Anwendungsbeispiele kann hier nachgel
DOIF im FHEM-Wiki
DOIF im FHEM-Forum
Kurzreferenz
- Perl-Funktionen
- DOIF Perl-Modus
- Anwendungsbeispiele im Perl-Modus
@@ -3705,36 +3701,45 @@ Das Modul unterstützt dazu Einrückungen, Zeilenumbrüche an beliebiger Stelle
Die Formatierungen lassen sich im DEF-Editor der Web-Oberfläche vornehmen.
So könnte eine Definition aussehen:
+
+define di_Modul DOIF ([Switch1] eq "on" and [Switch2] eq "on") | ## wenn Schalter 1 und Schalter 2 on ist
|
+(set lamp on)
| ## wird Lampe eingeschaltet |
+DOELSE | ## im sonst-Fall, also wenn einer der Schalter off ist
|
+(set lamp off)
| ## wird die Lampe ausgeschaltet |
-define di_Modul DOIF ([Switch1] eq "on" and [Switch2] eq "on") ## wenn Schalter 1 und Schalter 2 on ist
-
-(set lamp on) ## wird Lampe eingeschaltet
-
-DOELSE ## im sonst-Fall, also wenn einer der Schalter off ist
-
-(set lamp off) ## wird die Lampe ausgeschaltet
+
+Perl-Modus:
+
+define di_Modul DOIF
+{ if ([Switch1] eq "on" and [Switch2] eq "on") { | ## wenn Schalter 1 und Schalter 2 on ist
|
+fhem_set "set lamp on"
| ## wird Lampe eingeschaltet |
+ } elsif { | ## im sonst-Fall, also wenn einer der Schalter off ist
|
+fhem_set "lamp off"
| ## wird die Lampe ausgeschaltet |
+ }
|
+}
|
+
Im Folgenden wird die Funktionalität des Moduls im Einzelnen an vielen praktischen Beispielen erklärt.
Ereignissteuerung back
-Vergleichende Abfragen werden, wie in Perl gewohnt, mit Operatoren ==, !=, <, <=, >, >=
bei Zahlen und mit eq, ne, lt, le, gt, ge, =~, !~
bei Zeichenketten angegeben.
+Vergleichende Abfragen werden in der Bedingung, mit Perl-Operatoren ==, !=, <, <=, >, >=
bei Zahlen und mit eq, ne, lt, le, gt, ge, =~, !~
bei Zeichenketten angegeben.
Logische Verknüpfungen sollten zwecks Übersichtlichkeit mit and
bzw. or
vorgenommen werden.
-Selbstverständlich lassen sich auch alle anderen Perl-Operatoren verwenden, da die Auswertung der Bedingung vom Perl-Interpreter vorgenommen wird.
Die Reihenfolge der Auswertung wird, wie in höheren Sprachen üblich, durch runde Klammern beeinflusst.
Status werden mit [<devicename>]
, Readings mit [<devicename>:<readingname>]
,
Internals mit [<devicename>:&<internal>]
angegeben.
-Anwendungsbeispiel: Einfache Ereignissteuerung mit einmaliger Ausführung beim Zustandswechsel, "remotecontrol" ist hier ein Device, es wird in eckigen Klammern angegeben. Ausgewertet wird der Status des Devices - nicht das Event.
+Anwendungsbeispiel: Einfache Ereignissteuerung, "remotecontrol" ist hier ein Device, es wird in eckigen Klammern angegeben. Ausgewertet wird der Status des Devices - nicht das Event.
define di_garage DOIF ([remotecontrol] eq "on") (set garage on) DOELSEIF ([remotecontrol] eq "off") (set garage off)
Das Modul wird getriggert, sobald das angegebene Device hier "remotecontrol" ein Event erzeugt. Das geschieht, wenn irgendein Reading oder der Status von "remotecontrol" aktualisiert wird.
-Ausgewertet wird hier der Zustand des Status von remotecontrol nicht das Event selbst. Die Ausführung erfolgt standardmäßig einmalig nur nach Zustandswechsel des Moduls.
+Ausgewertet wird hier der Zustand des Status von remotecontrol nicht das Event selbst. Im FHEM-Modus arbeitet das Modul mit Zuständen, indem es den eigenen Status auswertet.
+Die Ausführung erfolgt standardmäßig nur ein mal, bis ein anderer DOIF-Zweig und damit eine Ändernung des eigenen Status erfolgt.
Das bedeutet, dass ein mehrmaliges Drücken der Fernbedienung auf "on" nur einmal "set garage on" ausführt. Die nächste mögliche Ausführung ist "set garage off", wenn Fernbedienung "off" liefert.
-Wünscht man eine Ausführung des gleichen Befehls mehrfach nacheinander bei jedem Trigger, unabhängig davon welchen Zustand das DOIF-Modul hat,
+Wünscht man eine Ausführung des gleichen Befehls mehrfach nacheinander bei jedem Trigger, unabhängig davon welchen Status das DOIF-Modul hat,
weil z. B. Garage nicht nur über die Fernbedienung geschaltet wird, dann muss man das per "do always"-Attribut angeben:
attr di_garage do always
@@ -3750,6 +3755,13 @@ Ohne do always
wird hier dagegen erst wieder "set heating on" ausge
Soll bei Nicht-Erfüllung aller Bedingungen ein Zustandswechsel erfolgen, so muss man ein DOELSE am Ende der Definition anhängen. Ausnahme ist eine einzige Bedingung ohne do always, wie im obigen Beispiel,
hierbei wird intern ein virtuelles DOELSE angenommen, um bei Nicht-Erfüllung der Bedingung einen Zustandswechsel in cmd_2 zu provozieren, da sonst nur ein einziges Mal geschaltet werden könnte, da das Modul aus dem cmd_1-Zustand nicht mehr herauskäme.
+Perl-Modus:
+
+Im Perl-Modus arbeitet das DOIF-Modul im Gegensatz zum FHEM-Modus ohne den eigenen Status auszuwerten. Es kommt immer zur Auswertung des definierten Block, wenn er getriggert wird.
+Diese Verhalten entspricht dem Verhalten mit dem Attribut do always im FHEM-Modus. Damit bei zyklisch sendenden Sensoren nicht zum ständigen Schalten kommt, muss das Schalten unterbunden werden. Das obige Beispiel lässt sich, wie folgt definieren:
+
+define di_heating DOIF {if ([sens:temperature] < 20) {if (Value("heating") ne "on") {fhem_set"heating on"}}}
+
Teilausdrücke abfragen back
@@ -3760,6 +3772,9 @@ Abfragen nach Vorkommen eines Wortes innerhalb einer Zeichenkette können mit Hi
define di_garage DOIF ([remotecontrol] =~ "Long") (set garage on)
attr di_garage do always
+Perl-Modus:
+define di_garage DOIF {if ([remotecontrol] =~ "Long") {fhem_set"garage on"}}
+
Weitere Möglichkeiten bei der Nutzung des Perl-Operators: =~
, insbesondere in Verbindung mit regulären Ausdrücken, können in der Perl-Dokumentation nachgeschlagen werden.
@@ -3772,6 +3787,9 @@ Die Syntax lautet: [<devicename>:"<regex>"]
define di_garage DOIF ([remotecontrol:"on"]) (set garage on) DOELSEIF ([remotecontrol:"off"]) (set garage off)
+Perl-Modus:
+define di_garage DOIF {if ([remotecontrol:"on"]) {fhem_set"garage on"} elsif ([remotecontrol:"off"]) {fhem_set"garage off"}}
+
In diesem Beispiel wird nach dem Vorkommen von "on" innerhalb des Events gesucht.
Falls "on" gefunden wird, wird der Ausdruck wahr und der DOIF-Fall wird ausgeführt, ansonsten wird der DOELSEIF-Fall entsprechend ausgewertet.
Die Auswertung von reinen Ereignissen bietet sich dann an, wenn ein Modul keinen Status oder Readings benutzt, die man abfragen kann, wie z. B. beim Modul "sequence".
@@ -3800,44 +3818,16 @@ Entsprechend können Perl-Variablen in der DOIF-Bedingung ausgewertet werden, si
Anwendungsbeispiele:
-Loggen aller Ereignisse in FHEM
-
-define di_all_events DOIF ([""]) ({Log 3,"Events from device $DEVICE:$EVENTS"})
-
-attr di_all_events do always
-
"Fenster offen"-Meldung
define di_window_open (["^window_:open"]) (set Pushover msg 'alarm' 'open windows $DEVICE' '' 2 'persistent' 30 3600)
-
attr di_window_open do always
+Perl-Modus:
+define di_window_open {if (["^window_:open"]) {fhem_set"Pushover msg 'alarm' 'open windows $DEVICE' '' 2 'persistent' 30 3600"}}
+
Hier werden alle Fenster, die mit dem Device-Namen "window_" beginnen auf "open" im Event überwacht.
-Rollladen auf Lüften stellen
-
-define di_air DOIF (["^window_contact_:open|tilted"]) (set {("$DEVICE"=~/^window_contact_(.*)/;"shutters_$1")} 10)
-
-attr di_air do always
-
-Hier werden alle Fensterkontakte, die mit dem Device-Namen "window_contact_" beginnen auf "open" oder "tilted" im Event überwacht
-und der entsprechende Rollladen mit der gleichen Endung auf Lüften per set shutters_<postfix> 10
gestellt.
-In diesem Beispiel wird die Möglichkeit genutzt bei FHEM-Befehlen Perlcode innerhalb der Klammern {(...)} einzufügen. Siehe Berechnungen im Ausführungsteil
-
-Verzögerte "Fenster offen"-Meldung im Perl-Modus für mehrere Fenster
-
-Batteriewarnung per E-Mail verschicken
-
-define di_battery DOIF ([":battery: low"] and [?$SELF:B_$DEVICE] ne "low")
- ({DebianMail('yourname@gmail.com', 'FHEM - battery warning from device: $DEVICE')}, setreading $SELF B_$DEVICE low)
-DOELSEIF ([":battery: ok"] and [?$SELF:B_$DEVICE] ne "ok")
- (setreading $SELF B_$DEVICE ok)
-
-attr di_battery do always
-
-Eine aktuelle Übersicht aller Batterie-Status entsteht gleichzeitig in den Readings des di_battery-DOIF-Moduls.
-
-
Allgemeine Ereignistrigger können ebenfalls so definiert werden, dass sie nicht nur wahr zum Triggerzeitpunkt und sonst nicht wahr sind,
sondern Inhalte des Ereignisses zurückliefern. Initiiert wird dieses Verhalten durch die Angabe eines Default-Wertes.
@@ -3847,7 +3837,11 @@ Syntax:
Anwendungsbeispiel:
-define di_warning DOIF ([":^temperature",0]< 0 and [06:00-09:00] ) (set pushmsg danger of frost)
+define di_warning DOIF ([":^temperature",0]< 0) (set pushmsg danger of frost $DEVICE)
+attr di_warning do always
+
+Perl-Modus:
+define di_warning DOIF {if ([":^temperature",0]< 0) {fhem_set"pushmsg danger of frost $DEVICE}}
Damit wird auf alle Devices getriggert, die mit "temperature" im Event beginnen. Zurückgeliefert wird der Wert, der im Event hinter "temperature: " steht.
Wenn kein Event stattfindet, wird der Defaultwert, hier 0, zurückgeliefert.
@@ -3912,7 +3906,7 @@ Der Inhalt des Dummys Alarm soll in einem Text eingebunden werden:
Die Definition von regulären Ausdrücken mit Nutzung der Perl-Variablen $1, $2 usw. kann in der Perldokumentation nachgeschlagen werden.
-Angaben im Ausführungsteil: back
+Angaben im Ausführungsteil (gilt nur für FHEM-Modus): back
Der Ausführungsteil wird durch runde Klammern eingeleitet. Es werden standardmäßig FHEM-Befehle angegeben, wie z. B.: ...(set lamp on)
@@ -4102,13 +4096,20 @@ Einschalten um 8:00 Uhr, ausschalten um 10:00 Uhr.
define di_light DOIF ([08:00]) (set switch on) DOELSEIF ([10:00]) (set switch off)
+Perl-Modus:
+define di_light DOIF
+{[08:00];fhem_set"switch on"}
+{[10:00];fhem_set"switch on"}
+
+
Zeitsteuerung mit mehreren Zeitschaltpunkten:
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)
-Zeitangaben können ebenfalls in Sekunden angegeben werden. Es handelt sich dann um Sekundenangaben nach Mitternacht, hier also um 01:00 Uhr:
-
-define di_light DOIF ([3600]) (set lamp on)
+Perl-Modus:
+define di_light DOIF
+{if ([08:00] or [10:00] or [20:00]) {fhem_set"switch on"}}
+{if ([09:00] or [11:00] or [00:00]) {fhem_set"switch off"}}
Relative Zeitangaben back
@@ -4120,9 +4121,10 @@ Zeitangaben, die mit Pluszeichen beginnen, werden relativ behandelt, d. h. die a
define di_save DOIF ([+01:00]) (save)
attr di_save do always
-Ebenfalls lassen sich relative Angaben in Sekunden angeben. Das obige Beispiel entspricht:
+Perl-Modus:
+define di_save DOIF {[+01:00];fhem"save"}}
-define di_save DOIF ([+3600]) (save)
+Ebenfalls lassen sich relative Angaben in Sekunden angeben. [+01:00] entspricht [+3600];
Zeitangaben nach Zeitraster ausgerichtet back
@@ -4131,14 +4133,12 @@ Das Format lautet: [:MM] MM sind Minutenangaben zwischen 00 und 59.
Anwendungsbeispiel: Viertelstunden-Gong
-define di_gong DOIF ([:00])
- ({system ("mplayer /opt/fhem/Sound/BigBen_00.mp3 -volume 90 −really−quiet &")})
-DOELSEIF ([:15])
- ({system ("mplayer /opt/fhem/Sound/BigBen_15.mp3 -volume 90 −really−quiet &")})
-DOELSEIF ([:30])
- ({system ("mplayer /opt/fhem/Sound/BigBen_30.mp3 -volume 90 −really−quiet &")})
-DOELSEIF ([:45])
- ({system ("mplayer /opt/fhem/Sound/BigBen_45.mp3 -volume 90 −really−quiet &")})
+Perl-Modus:
+define di_gong DOIF
+ {[:00];system"mplayer /opt/fhem/Sound/BigBen_00.mp3 -volume 90 −really−quiet &"}
+ {[:15];system"mplayer /opt/fhem/Sound/BigBen_15.mp3 -volume 90 −really−quiet &"}
+ {[:30];system"mplayer /opt/fhem/Sound/BigBen_30.mp3 -volume 90 −really−quiet &"}
+ {[:45];system"mplayer /opt/fhem/Sound/BigBen_45.mp3 -volume 90 −really−quiet &"}
Relative Zeitangaben nach Zeitraster ausgerichtet back
@@ -4150,6 +4150,9 @@ Das Format lautet: [+:MM] MM sind Minutenangaben zwischen 1 und 59.
define di_gong DOIF ([+:15]) (set Gong_mp3 playTone 1)
attr di_gong do always
+Perl-Modus:
+define di_gong DOIF {[+:15];fhem_set"Gong_mp3 playTone 1"}
+
Zeitangaben nach Zeitraster ausgerichtet alle X Stunden back
@@ -4160,6 +4163,9 @@ Format: [+[h]:MM] mit: h sind Stundenangaben zwischen 2 und 23 und MM Minuten zw
define di_gong DOIF ([+[2]:05]) (set pump on-for-timer 300)
attr di_gong do always
+Perl-Modus:
+define di_gong DOIF {[+[2]:05];set_fhem"pump on-for-timer 300"}
+
Wochentagsteuerung back
@@ -4182,7 +4188,12 @@ Beispiel: di_mydoif attr weekdays Son,Mon,Die,Mit,Don,Fre,Sam,Wochenende,A
Anwendungsbeispiel: Radio soll am Wochenende und an Feiertagen um 08:30 Uhr eingeschaltet und um 09:30 Uhr ausgeschaltet werden. Am Montag und Mittwoch soll das Radio um 06:30 Uhr eingeschaltet und um 07:30 Uhr ausgeschaltet werden. Hier mit englischen Bezeichnern:
define di_radio DOIF ([06:30|Mo We] or [08:30|WE]) (set radio on) DOELSEIF ([07:30|Mo We] or [09:30|WE]) (set radio off)
+attr di_radio weekdays Su,Mo,Tu,We,Th,Fr,Sa,WE,WD
+Perl-Modus:
+define di_radio DOIF
+{if ([06:30|Mo We] or [08:30|WE]) {fhem_set"radio on"}}
+{if ([07:30|Mo We] or [09:30|WE]) {fhem_set"radio off"}}
attr di_radio weekdays Su,Mo,Tu,We,Th,Fr,Sa,WE,WD
Bemerkung: Es ist unerheblich wie die definierten Wochenttagbezeichner beim Timer angegeben werden. Sie können mit beliebigen Trennzeichen oder ohne Trennzeichen direkt aneinander angegeben werden.
@@ -4195,7 +4206,12 @@ Anstatt einer direkten Wochentagangabe, kann ein Status oder Reading in eckigen
set myweekday monday wednesday thursday weekend
define di_radio DOIF ([06:30|[myweekday]]) (set radio on) DOELSEIF ([07:30|[myweekday]]) (set radio off)
+attr di_radio weekdays sunday,monday,thuesday,wednesday,thursday,friday,saturday,weekend,workdays
+Perl-Modus:
+define di_radio DOIF
+{[06:30|[myweekday]];fhem_set"radio on"}
+{[07:30|[myweekday]];fhem_set"radio off"}
attr di_radio weekdays sunday,monday,thuesday,wednesday,thursday,friday,saturday,weekend,workdays
@@ -4213,13 +4229,15 @@ Radio soll zwischen 8:00 und 10:00 Uhr an sein:
define di_radio DOIF ([08:00-10:00]) (set radio on) DOELSE (set radio off)
+Perl-Modus:
+define di_radio DOIF {if ([08:00-10:00]) {fhem_set"radio on"} else {fhem_set"radio off"}}
+
mit mehreren Zeitintervallen:
define di_radio DOIF ([08:00-10:00] or [20:00-22:00]) (set radio on) DOELSE (set radio off)
-Radio soll nur sonntags (0) eingeschaltet werden:
-
-define di_radio DOIF ([08:00-10:00|0]) (set radio on) DOELSE (set radio off)
+Perl-Modus:
+define di_radio DOIF {if ([08:00-10:00] or [20:00-22:00]) {fhem_set"radio on"} else {fhem_set"radio off"}}
Nur montags, mittwochs und freitags:
@@ -4243,10 +4261,20 @@ Einschalten am Freitag ausschalten am Montag:
define di_light DOIF ([22:00|5]) (set light on) DOELSEIF ([10:00|1]) (set light off)
+Perl-Modus:
+define di_light DOIF
+{[22:00|5];fhem_set"light on"}
+{[10:00|1];fhem_set"light off"}
+
Schalten mit Zeitfunktionen, hier: bei Sonnenaufgang und Sonnenuntergang:
define di_light DOIF ([{sunrise(900,"06:00","08:00")}]) (set outdoorlight off) DOELSEIF ([{sunset(900,"17:00","21:00")}]) (set outdoorlight on)
+Perl-Modus:
+define di_light DOIF
+{[{sunrise(900,"06:00","08:00")}];fhem_set"outdoorlight off"}
+{[{sunset(900,"17:00","21:00")}];fhem_set"outdoorlight on"}
+
Indirekten Zeitangaben back
@@ -4257,9 +4285,13 @@ Statt fester Zeitangaben können Status, Readings oder Internals angegeben werde
define time dummy
set time 08:00
+
define di_time DOIF ([[time]])(set lamp on)
attr di_time do always
+Perl-Modus:
+define di_time DOIF {[[time]];fhem_set"lamp on"}
+
Die indirekte Angabe kann ebenfalls mit einer Zeitfunktion belegt werden. Z. B.
set time {sunset()}
@@ -4268,7 +4300,12 @@ Das Dummy kann auch mit einer Sekundenzahl belegt werden, oder als relative Zeit
define time dummy
set time 300
-define di_time DOIF ([+[time]])(save)
+
+define di_time DOIF ([+[time]])(save)
+attr di_time do always
+
+Perl-Modus:
+define di_time DOIF {[+[time]];fhem"save"}
Ebenfalls funktionieren indirekte Zeitangaben mit Zeitintervallen. Hier wird die Ein- und Ausschaltzeit jeweils über einen Dummy bestimmt:
@@ -4280,6 +4317,9 @@ set end 10:00
define di_time DOIF ([[begin]-[end]]) (set radio on) DOELSE (set radio off)
+Perl-Modus:
+define di_time DOIF {if([[begin]-[end]]) {fhem_set"radio on"} else {fhem_set"radio off"}}
+
Indirekte Zeitangaben können auch als Übergabeparameter für Zeitfunktionen, wie z. B. sunset oder sunrise übergeben werden:
define di_time DOIF ([{sunrise(0,"[begin]","09:00")}-{sunset(0,"18:00","[end]")}]) (set lamp off) DOELSE (set lamp on)
@@ -4289,17 +4329,18 @@ Bei einer Änderung des angegebenen Status oder Readings wird die geänderte Zei
Angabe eines Readings als Zeitangabe. Beispiel: Schalten anhand eines Twilight-Readings:
define di_time DOIF ([[myTwilight:ss_weather]])(set lamp on)
+attr di_timer do always
-Dynamische Änderung einer Zeitangabe.
-
-Anwendungsbeispiel: Die Endzeit soll abhängig von der Beginnzeit mit Hilfe einer eigenen Perl-Funktion, hier: OffTime()
, bestimmt werden. begin
und end
sind Dummys, wie oben definiert:
-
-define di_time DOIF ([[begin]-[end]]) (set lamp on, set end {(OffTime("[begin]"))}) DOELSE (set lamp off)
+Perl-Modus:
+define di_time DOIF {[[myTwilight:ss_weather]];fhem_set"lamp on"}
Indirekte Zeitangaben lassen sich mit Wochentagangaben kombinieren, z. B.:
define di_time DOIF ([[begin]-[end]|7]) (set radio on) DOELSE (set radio off)
+Perl-Modus:
+define di_time DOIF {if ([[begin]-[end]|7]) {fhem_set"radio on"} else {fhem_set"radio off"}}
+
Zeitsteuerung mit Zeitberechnung back
@@ -4317,6 +4358,12 @@ Lampe wird nach Sonnenuntergang zwischen 900 und 1500 (900+600) Sekunden zufäll
DOELSEIF ([([23:00]+int(rand(600)))])
(set lamp off)
+Perl-Modus:
+define di_light DOIF
+{[({sunset()}+900+int(rand(600)))];fhem_set"lamp on"}
+{[([23:00]+int(rand(600)))];;fhem_set"lamp off"}
+
+
Zeitberechnung können ebenfalls in Zeitintervallen genutzt werden.
Licht soll eine Stunde vor gegebener Zeit eingeschaltet werden und eine Stunde danach wieder ausgehen:
@@ -4356,6 +4403,9 @@ Innerhalb des definierten Zeitintervalls, triggert der definierte Timer. Außerh
define di_pump DOIF ([08:00-22:00,+:30])(set pump on-for-timer 300)
attr di_pump do always
+Perl-Modus:
+define di_pump DOIF {[08:00-22:00,+:30];set_fhem"pump on-for-timer 300"}
+
Es wird um 08:00, 08:30, 09:00, ..., 21:30 Uhr die Anweisung ausgeführt. Um 22:00 wird das letzte Mal getriggert, das Zeitintervall ist zu diesem Zeitpunkt nicht mehr wahr.
Es lassen sich ebenso indirekte Timer, Timer-Funktionen, Zeitberechnungen sowie Wochentage miteinander kombinieren.
@@ -4363,6 +4413,9 @@ Es lassen sich ebenso indirekte Timer, Timer-Funktionen, Zeitberechnungen sowie
define di_rand_lamp DOIF ([{sunset()}-[end:state],+(rand(600)+900)|Sa So])(set lamp on-for-timer 300)
attr di_rand_lamp do always
+Perl-Modus:
+define di_rand_lamp DOIF {[{sunset()}-[end:state],+(rand(600)+900)|Sa So];fhem_set"lamp on-for-timer 300"}
+
Kombination von Ereignis- und Zeitsteuerung mit logischen Abfragen back
@@ -4384,6 +4437,9 @@ Angaben in eckigen Klammern, die mit einem Fragezeichen beginnen, führen zu kei
define di_motion DOIF ([?06:00-10:00] and [button] and [?Home] eq "present")(set lamp on-for-timer 600)
attr di_motion do always
+Perl-Modus:
+define di_motion DOIF {if ([?06:00-10:00] and [button] and [?Home] eq "present"){fhem_set"lamp on-for-timer 600"}}
+
Nutzung von Readings, Status oder Internals im Ausführungsteil back
@@ -5694,37 +5750,40 @@ Es sind beliebige Hierarchietiefen möglich:
Bemerkung: Innerhalb eines Ereignisblocks muss mindestens ein Trigger definiert werden, damit der gesamte Block beim passenden Trigger ausgeführt wird.
-Es können ebenso Ereignisblöcke ohne if-else-Abfragen definiert werden:
-
-Loggen des Zustands vom Device FS:
-
DOIF {Log 3,"State from FS: ".[FS:state]}
-
-Das Schalten der Lampe mit dem Status von FS:
-
-DOIF {fhem("set lamp ".[FS:state])}
-
-entspricht mit dem performanteren Perl-Befehl fhem_set
:
-
-DOIF {fhem_set("lamp ".[FS:state])}
-
-Das Setzen des eigenen Status mit dem Status von FS:
-
-DOIF {set_State([FS:state])}
-
-Das Setzen des eigenen Readings "temperature" mit dem Wert des Readings "temperature" des Raumes "livingroom":
-
-DOIF {set_Reading("temperature",[livingroom:temperature])}
-
-Einfache Zeit- oder Ereignistrigger können ebenfalls ohne if-Anweisungen definiert werden:
-
-Schalte lampe um 08:00 Uhr ein:
-
-DOIF {[08:00];fhem_set("lamp on")}
-
-Lampe ausschalten, beim Auftreten des Events "FS:on":
-
-DOIF {["FS:on"];fhem_set("lamp off")}
-
+
+Inhaltsübersicht (Beispiele im Perlmodus sind besonders gekennzeichnet)
+
Eigene Funktionen
Ein besonderer Block ist der Block namens subs. In diesem Block werden Perlfunktionen definiert, die innerhalb des DOIFs genutzt werden.
@@ -5889,17 +5948,19 @@ Ebenso funktionieren hash-Variablen z. B.:
Blokierende Funktionsaufrufe (blocking calls)
-DOIF verwaltet blockierende Funktionsaufrufe, d.h. die in diesem Zusammenhang gestarteten FHEM-Instanzen werden gelöscht, beim Herunterfahren (shutdown), Wiedereinlesen der Konfiguration (rereadcfg) Änderung der Konfiguration (modify) und Deaktivieren des Gerätes (disabled).
+DOIF verwaltet blockierende Funktionsaufrufe, d.h. die in diesem Zusammenhang gestarteten FHEM-Instanzen werden gelöscht, beim Herunterfahren (shutdown), Wiedereinlesen der Konfiguration (rereadcfg) Änderung der Konfiguration (modify) und Deaktivieren des Gerätes (disabled).
-Die Handhabung von blockierenden Funktionsaufrufen ist im FHEMwiki erklärt, s. Blocking Call.
+Die Handhabung von blockierenden Funktionsaufrufen ist im FHEMwiki erklärt, s. Blocking Call.
-Der von der Funktion BlockingCall zurückgegebene Datensatz ist unterhalb von $_blockingcalls abzulegen, z.B.
+Der von der Funktion BlockingCall zurückgegebene Datensatz ist unterhalb von $_blockingcalls abzulegen, z.B.
-$_blockingcalls{<blocking call name>} = BlockingCall(<blocking function>, <argument>, <finish function>, <timeout>, <abort function>, <abort argument>) unless(defined($_blockingcalls{<blocking call name>}));
+$_blockingcalls{<blocking call name>} = ::BlockingCall(<blocking function>, <argument>, <finish function>, <timeout>, <abort function>, <abort argument>) unless(defined($_blockingcalls{<blocking call name>}));
-Für unterschiedliche blockierende Funktionen ist jeweils ein eigener Name (<blocking call name>) unterhalb von $_blockingcalls anzulegen.
+Für unterschiedliche blockierende Funktionen ist jeweils ein eigener Name (<blocking call name>) unterhalb von $_blockingcalls anzulegen.
-$_blockingcalls ist eine für DOIF reservierte Variable und darf nur in der beschriebener Weise verwendet werden.
+Wenn <blocking function>, <finish function> und <abort function> im Package DOIF definiert werden, dann ist dem Funktionsnamen DOIF:: voranzustellen, im Aufruf der Funktion BlockingCall, z.B. DOIF::<blocking function>
+
+$_blockingcalls ist eine für DOIF reservierte Variable und darf nur in der beschriebener Weise verwendet werden.
Nutzbare Attribute im Perl-Modus