diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index 08bff6137..da160ebdc 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -2821,13 +2821,12 @@ DOIF_SleepTrigger ($)
sub DOIF_set_Exec
{
my ($hash,$timername,$seconds,$subname,$param)=@_;
- $param="" if (!defined $param);
my $current = gettimeofday();
my $next_time = $current+$seconds;
$hash->{ptimer}{$timername}{time}=$next_time;
$hash->{ptimer}{$timername}{name}=$timername;
$hash->{ptimer}{$timername}{subname}=$subname;
- $hash->{ptimer}{$timername}{param}=$param;
+ $hash->{ptimer}{$timername}{param}=$param if (defined $param);
$hash->{ptimer}{$timername}{hash}=$hash;
RemoveInternalTimer(\$hash->{ptimer}{$timername});
if ($seconds > 0) {
@@ -2869,8 +2868,12 @@ sub DOIF_ExecTimer
my $timername=${$timer}->{name};
my $name=$hash->{NAME};
my $subname=${$timer}->{subname};
- my $param=${$timer}->{param};
- eval ("$subname(\"$param\")");
+ my $param=${$timer}->{param} if (defined ${$timer}->{param});
+ if (!defined ($param)) {
+ eval ("$subname");
+ } else {
+ eval ('$subname("$param")');
+ }
if ($@) {
Log3 ($defs{$name}{NAME},1 , "$name error in $subname: $@");
readingsSingleUpdate ($hash, "error", "in $subname: $@",0);
@@ -3453,15 +3456,16 @@ DOIF (ausgeprochen: du if, übersetzt: tue wenn) ist ein universelles Modul mit
Mit diesem Modul ist es möglich, einfache wie auch komplexere Automatisierungsvorgänge zu definieren oder in Perl zu programmieren.
Ereignisse, Zeittrigger, Readings oder Status werden durch DOIF-spezifische Angaben in eckigen Klammern angegeben. Sie führen zur Triggerung des Moduls und damit zur Auswertung und Ausführung der definierten Anweisungen.
-Das Modul verfügt über zwei Modi: FHEM-Modus und [NEU] Perl-Modus. Der Modus eines definierten DOIF-Devices wird automatisch aufgrund der Definition vom Modul erkannt
+Das Modul verfügt über zwei Modi: FHEM-Modus und Perl-Modus. Der Modus eines definierten DOIF-Devices wird automatisch aufgrund der Definition vom Modul erkannt
(FHEM-Modus beginnt mit einer runden Klammer auf).
+Der Perl-Modus kommt weitgehend ohne Attribute aus, er ist aufgrund seiner Flexibilität,
+der Möglichkeit strukturiert zu programmieren und seiner hohen Performance insb. bei umfangreichen Automatisierungsaufgaben dem FHEM-Modus vorzuziehen. Hier geht´s zum Perl-Modus.
Beide Modi sind innerhalb eines DOIF-Devices nicht miteinander kombinierbar. Im Folgendem wird der FHEM-Modus beschrieben.
Syntax FHEM-Modus:
define <name> DOIF (<Bedingung>) (<Befehle>) DOELSEIF (<Bedingung>) (<Befehle>) DOELSEIF ... DOELSE (<Befehle>)
set_Reading
verändert werden, siehe spezifische Perl-Funktionen im Perl-Modus.
-DOIF-spezifische Operanden-Angaben in eckigen Klammern entsprechen vollständig den Angaben im FHEM-Modus des Moduls. Sie können an beliebiger Stelle im Perlcode angegeben werden, wo auch Perl-Funktionen angegeben werden können.define <name> DOIF <Blockname> {<Perl mit DOIF-Syntax in eckigen Klammern>} <Blockname> {<Perl mit DOIF-Syntax in eckigen Klammern>} ...
define <name> DOIF <Blockname> {<Perlcode mit Ereignis-/Zeittriggern in eckigen Klammern>}
fhem"..."
ausgeführt. Im Gegensatz zum FHEM-Modus können im Perl-Modus mehrere Blöcke unabhängig voneinander, ausgelöst durch einen Ereignis- oder Zeit-Trigger, ausgeführt werden. So kann die Funktionalität mehrer DOIF-Module im FHEM-Modus innerhalb eines DOIF-Moduls im Perl-Moduls realisiert werden.set_Reading
verändert werden, siehe spezifische Perl-Funktionen im Perl-Modus.
+FHEM-Befehle werden durch den Aufruf der Perlfunktion fhem"..."
ausgeführt.set_Timer
beliebig viele eigene Timer definieren, die unabhängig voneinander gesetzt und ausgewertet werden können, siehe Spezifische Perl-Funktionen im Perl-Modus.set_Timer/set_Exec
beliebig viele eigene Timer definieren, die unabhängig voneinander gesetzt und ausgewertet werden können, siehe Spezifische Perl-Funktionen im Perl-Modus.DOIF (<Bedingung mit Trigger>) (<FHEM-Befehle>) DOELSE (<FHEM-Befehle>)
DOIF {if (<Bedingung mit Trigger>) {fhem"<FHEM-Befehle>"} else {fhem"<FHEM-Befehle>"}}
DOIF
+{ if (<Bedingung mit Trigger>) ... }
+{ if (<Bedingung mit Trigger>) ... }
+...
DOIF
+{ if (<Bedingung>) {
+ if (<Bedingung>) {
+ if (...
+ ...
+ }
+ }
+ }
+}
+DOIF
+subs { ## Definition von Perlfunktionen lamp_on und lamp_off
+ sub lamp_on {
+ fhem"set lamp on";
+ set_Reading("state","on",1);
+ }
+ sub lamp_off {
+ fhem"set lamp off";
+ set_Reading("state","off",1);
+ }
+}
+{if ([06:00]) {lamp_on() # Um 06:00 Uhr wird die Funktion lamp_on aufgerufen }
+{if ([08:00]) {lamp_off() # Um 08:00 Uhr wird die Funktion lamp_off aufgerufen }
+
define di_rc_tv DOIF {if ([remotecontol:"on"]) {fhem"set tv on"} else {fhem"set tv off"}}
define di_clock_radio DOIF {if ([06:30|Mo Di Mi] or [08:30|Do Fr Sa So]) {fhem"set radio on"} elsif ([08:00|Mo Di Mi] or [09:30|Do Fr Sa So]) {fhem"set radio off"}}
define di_clock_radio DOIF {if ([06:30|Mo Di Mi] or [08:30|Do Fr Sa So]) {fhem"set radio on"}} {if ([08:00|Mo Di Mi] or [09:30|Do Fr Sa So]) {fhem"set radio off"}}
define di_lamp DOIF {if ([06:00-09:00] and [sensor:brightness] < 40) {fhem"set lamp:FILTER=STATE!=on on"} else {fhem"set lamp:FILTER=STATE!=off off"}}
get_Timer(<TimerEvent>)
, Returnwert: 0, w
del_Timer(<TimerEvent>)
set_Exec(<timerName>, <seconds>, <function>, <parameter>)
, mit <timerName>: beliebige Angabe, sie spezifiziert eindeutig einen Timer,
-welcher nach Ablauf die angegebene Perl-Funktion <function> mit optionalen Parameter <parameter> aufruft. Die Perlfunkion muss eindeutig sein und in FHEM zuvor deklariert worden sein.
+set_Time("event",30,"hello");
set_Exec(<timerName>, <seconds>, <perlCode>, <parameter>)
, mit <timerName>: beliebige Angabe, sie spezifiziert eindeutig einen Timer,
+welcher nach Ablauf den angegebenen Perlcode <perlCode> aufruft. Falls als Perlcode eine Perlfunktion angegeben wird, kann optional ein Übergabeparameter <parameter> angegeben werden. Die Perlfunkion muss eindeutig sein und in FHEM zuvor deklariert worden sein.
Wird set_Exec mit dem gleichen <timerName> vor seinem Ablauf erneut aufgerufen, so wird der laufender Timer gelöscht und neugesetzt.get_Exec(<timerName>)
, Returnwert: 0, wenn Timer abgelaufen oder nicht gesetzt ist, sonst Anzahl der Sekunden bis zum Ablauf des Timersdel_Exec(<timerName>)
set_Exec("aus",30,'fhem"set lamp off"');
set_Event(<Event>)
set_Reading(<readingName>,<content>,<trigger>)
, mit <trigger>: 0 ohne Trigger, 1 mit Triggerif (defined $_...) ...
init {$_status=ReadingsVal("$SELF","state",0)}
init {$_status=[?$SELF:state]}
my $i=0;
$_betrag{$i}=100;
+define di_light DOIF {
+ if (["FS:motion"]) { # bei Bewegung
+ fhem"set lamp on" if ([?lamp] ne "on"); # Lampe einschalten, wenn sie nicht an ist
+ set_Exec("off",30,'fhem"set lamp off"'); # Timer namens "off" für das Ausschalten der Lampe auf 30 Sekunden setzen bzw. verlängern
+ }
+}
+
+
-define di_shutter DOIF { # Block zur Auswertung des Tastendruckes
- if (["FS:^on$"] and get_Timer("Timer_shutter")==0){ # wenn Taste betätigt wird und kein Timer läuft
- set_Timer("Timer_shutter",2); # Timer für zwei Sekunden setzen
- } else { # wenn Timer läuft, d.h. ein weitere Tastendruck innerhalb von zwei Sekunden
- del_Timer("Timer_shutter") # Timer löschen
- fhem"set shutter up"; # Rollladen hoch
- }
-}
-{ # Block für die Bearbeitung des Timerevents
- if ([$SELF:"Timer_shutter"]){ # wenn nach zwei Sekunden Timer abläuft, d.h. nur ein Tastendruck
- fhem"set shutter down"; # Rollladen runter
+define di_shutter DOIF {
+ if (["FS:^on$"] and !get_Exec("shutter")){ # wenn Taste betätigt wird und kein Timer läuft
+ set_Exec("shutter",2,'fhem"set shutter down"'); # Timer zum shutter down auf zwei Sekunden setzen
+ } else { # wenn Timer läuft, d.h. ein weitere Tastendruck innerhalb von zwei Sekunden
+ del_Timer("shutter"); # Timer löschen
+ fhem"set shutter up"; # Rollladen hoch
}
}
@@ -5679,43 +5750,12 @@ define di_shutter DOIF { &n
Im folgenden Beispiel wird die Nutzung von Instanzvariablen demonstriert.
-define di_count DOIF { # Block zur Auswertung des Ereignisses
- if (["FS:on"] and get_Timer("Timer_counter")==0){ # wenn Ereignis (hier "FS:on") eintritt und kein Timer läuft
- $_count=1; # setze count-Variable auf 1
- set_Timer("Timer_counter",3600); # setze Timer auf eine Stunde
- } else {
- $_count++; # wenn Timer bereits läuft zähle Ereignis
- }
-}
-{ # Block für die Auswertung nach Ablauf des Timers
- if ([$SELF:"Timer_counter"]) { # wenn Timer nach einer Stunde abläuft
- if ($_count > 10) {
- Log 3,"count: $_count action"; # protokolliere im Log die Anzahl der Ereignisse, wenn sie über 10 ist
- }
- }
-}
-
-define di_light DOIF
-subs { # Block "subs" zur Definition eigener Perl-Funktionen, hier ist nur Perl erlaubt ohne DOIF-Syntax
- sub ein { # Perlfunktion "ein" zum Einschalten wird definiert
- if (ReadingsVal ("lamp","state","") ne "on") {
- fhem"set lamp on";
- set_Reading ("state","on",1);
- }
- }
- sub aus { # Perlfunkton "aus" zum Ausschalten wird definiert
- fhem"set lamp off";
- set_Reading ("state","off",1);
- }
-}
-bewegung { # Block namens "bewegung" reagiert auf Bewegung von FS
- if (["FS:motion"]) {
- ein(); # Perlfunktion "ein" wird ausgeführt
- set_Exec("light_off",10,"aus"); # Timer namens "light_off"für das Ausschalten über Perlfunktion "aus" wird gesetzt bzw. verlängert
+define di_count DOIF {
+ if (["FS:on"] and !get_Exec("counter")) { # wenn Ereignis (hier "FS:on") eintritt und kein Timer läuft
+ $_count=1; # setze count-Variable auf 1
+ set_Exec("counter",3600,'Log (3,"count: $_count action") if ($_count > 10)'); # setze Timer auf eine Stunde zum Protokollieren der Anzahl der Ereignisse, wenn sie über 10 ist
+ } else {
+ $_count++; # wenn Timer bereits läuft zähle Ereignis
}
}