diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm
index 4ce3110aa..6528aa65d 100644
--- a/fhem/FHEM/98_DOIF.pm
+++ b/fhem/FHEM/98_DOIF.pm
@@ -25,6 +25,8 @@ use Blocking;
use Color;
use vars qw($FW_CSRF);
+my $hs;
+
sub DOIF_cmd ($$$$);
sub DOIF_Notify ($$);
@@ -1113,13 +1115,13 @@ sub ReplaceAggregateDoIf($$$)
if (defined $default) {
$match="" if (!defined $match);
- $block="AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading','$match','$default')";
+ $block="::AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading','$match','$default')";
} elsif (defined $match) {
- $block="AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading','$match')";
+ $block="::AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading','$match')";
} elsif (defined $reading) {
- $block="AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading')";
+ $block="::AggregateDoIf(".'$hash'.",'$aggrType','$nameExp','$reading')";
} else {
- $block="AggregateDoIf(".'$hash'.",'$aggrType','$nameExp')";
+ $block="::AggregateDoIf(".'$hash'.",'$aggrType','$nameExp')";
}
if ($eval) {
@@ -1172,11 +1174,11 @@ sub ReplaceEventDoIf($)
if (defined $filter) {
return ($block,"default value must be defined")
} else {
- $block="EventDoIf('$nameExp',".'$hash,'."'$notifyExp',0)";
+ $block="::EventDoIf('$nameExp',".'$hash,'."'$notifyExp',0)";
return ($block,undef);
}
}
- $block="EventDoIf('$nameExp',".'$hash,'."'$notifyExp',0,'$filter','$output','$default')";
+ $block="::EventDoIf('$nameExp',".'$hash,'."'$notifyExp',0,'$filter','$output','$default')";
return ($block,undef);
}
@@ -1213,15 +1215,15 @@ sub ReplaceReadingDoIf($)
if ($reading) {
if (substr($reading,0,1) eq "\?") {
$notifyExp=substr($reading,1);
- return("EventDoIf('$name',".'$hash,'."'$notifyExp',1)","",$name,undef,undef);
+ return("::EventDoIf('$name',".'$hash,'."'$notifyExp',1)","",$name,undef,undef);
} elsif ($reading =~ /^"(.*)"$/g) {
$notifyExp=$1;
- return("EventDoIf('$name',".'$hash,'."'$notifyExp',1)","",$name,undef,undef);
+ return("::EventDoIf('$name',".'$hash,'."'$notifyExp',1)","",$name,undef,undef);
}
$internal = substr($reading,1) if (substr($reading,0,1) eq "\&");
if ($format) {
if ($format eq "sec") {
- return("ReadingSecDoIf('$name','$reading')","",$name,$reading,undef);
+ return("::ReadingSecDoIf('$name','$reading')","",$name,$reading,undef);
} elsif (substr($format,0,1) eq '[') { #old Syntax
($beginning,$regExp,$err,$tailBlock)=GetBlockDoIf($format,'[\[\]]');
return ($regExp,$err) if ($err);
@@ -1248,15 +1250,15 @@ sub ReplaceReadingDoIf($)
$param=",'$default'";
}
if ($internal) {
- return("InternalDoIf(".'$hash'.",'$name','$internal'".$param.")","",$name,undef,$internal);
+ return("::InternalDoIf(".'$hash'.",'$name','$internal'".$param.")","",$name,undef,$internal);
} else {
- return("ReadingValDoIf(".'$hash'.",'$name','$reading'".$param.")","",$name,$reading,undef);
+ return("::ReadingValDoIf(".'$hash'.",'$name','$reading'".$param.")","",$name,$reading,undef);
}
} else {
if ($default) {
$param=",'$default'";
}
- return("InternalDoIf(".'$hash'.",'$name','STATE'".$param.")","",$name,undef,'STATE');
+ return("::InternalDoIf(".'$hash'.",'$name','STATE'".$param.")","",$name,undef,'STATE');
}
}
}
@@ -1620,9 +1622,9 @@ DOIF_CheckTimers($$$$)
}
if (defined $end) {
if ($days eq "") {
- $block='DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms)';
+ $block='::DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms)';
} else {
- $block='DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms,"'.$days.'")';
+ $block='::DOIF_time($hash,'.$i.','.($i+1).',$wday,$hms,"'.$days.'")';
}
$hash->{interval}{$i}=-1;
$hash->{interval}{($i+1)}=$i;
@@ -1633,9 +1635,9 @@ DOIF_CheckTimers($$$$)
}
} else {
if ($days eq "") {
- $block='DOIF_time_once($hash,'.$i.',$wday)';
+ $block='::DOIF_time_once($hash,'.$i.',$wday)';
} else {
- $block='DOIF_time_once($hash,'.$i.',$wday,"'.$days.'")';
+ $block='::DOIF_time_once($hash,'.$i.',$wday,"'.$days.'")';
}
}
if ($init_done) {
@@ -1865,7 +1867,9 @@ sub DOIF_CheckCond($$) {
}
$cmdFromAnalyze="$hash->{NAME}: ".sprintf("warning in condition c%02d",($condition+1));
$lastWarningMsg="";
- my $ret = eval $command;
+ $hs=$hash;
+ my $ret=$hash->{MODEL} eq "Perl" ? eval("package DOIF; $command"):eval ($command);
+ #my $ret = eval ($command);
if($@){
$@ =~ s/^(.*) at \(eval.*\)(.*)$/$1,$2/;
$err = sprintf("condition c%02d",($condition+1)).": $@";
@@ -2264,7 +2268,7 @@ DOIF_Notify($$)
my $err;
my $eventa;
my $eventas;
-
+
$eventa = deviceEvents($dev, AttrVal($pn, "addStateEvent", 0));
$eventas = deviceEvents($dev, 1);
@@ -2822,132 +2826,6 @@ DOIF_SleepTrigger ($)
return undef;
}
-sub DOIF_set_Exec
-{
- my ($hash,$timername,$seconds,$subname,$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 if (defined $param);
- $hash->{ptimer}{$timername}{hash}=$hash;
- RemoveInternalTimer(\$hash->{ptimer}{$timername});
- if ($seconds > 0) {
- readingsSingleUpdate ($hash,"timer_$timername",strftime("%d.%m.%Y %H:%M:%S",localtime($next_time)),0);
- }
- InternalTimer($next_time, "DOIF_ExecTimer",\$hash->{ptimer}{$timername}, 0);
-}
-
-
-sub DOIF_get_Exec
-{
- my ($hash,$timername)=@_;
- my $current = gettimeofday();
- if (defined $hash->{ptimer}{$timername}{time}) {
- my $sec=$hash->{ptimer}{$timername}{time}-$current;
- if ($sec > 0) {
- return ($sec);
- } else {
- delete ($hash->{ptimer}{$timername}{time});
- return (0);
- }
- } else {
- return (0);
- }
-}
-
-sub DOIF_del_Exec
-{
- my ($hash,$timername)=@_;
- RemoveInternalTimer(\$hash->{ptimer}{$timername});
- delete $hash->{ptimer}{$timername};
- delete ($defs{$hash->{NAME}}{READINGS}{"timer_$timername"});
-}
-
-sub DOIF_ExecTimer
-{
- my ($timer)=@_;
- my $hash=${$timer}->{hash};
- my $timername=${$timer}->{name};
- my $name=$hash->{NAME};
- my $subname=${$timer}->{subname};
- 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);
- }
- delete ($defs{$name}{READINGS}{"timer_$timername"});
-}
-
-sub DOIF_set_Timer
-{
- my ($hash,$event,$seconds)=@_;
- my $name=$hash->{NAME};
- my $timername="$name:$event";
- my $current = gettimeofday();
- my $next_time = $current+$seconds;
- RemoveInternalTimer($timername);
- $hash->{ptimer}{$timername}=$next_time;
- if ($seconds > 0) {
- $event =~ s/\W/_/g;
- readingsSingleUpdate ($hash,"timer_$event",strftime("%d.%m.%Y %H:%M:%S",localtime($next_time)),0);
- }
- InternalTimer($next_time, "DOIF_PerlTimer", $timername, 0);
-}
-
-
-
-sub DOIF_get_Timer
-{
- my ($hash,$event)=@_;
- my $name=$hash->{NAME};
- my $timername="$name:$event";
- my $current = gettimeofday();
- if (defined $hash->{ptimer}{$timername}) {
- my $sec=$hash->{ptimer}{$timername}-$current;
- if ($sec > 0) {
- return ($sec);
- } else {
- delete ($hash->{ptimer}{$timername});
- return (0);
- }
- } else {
- return (0);
- }
-}
-
-sub DOIF_PerlTimer
-{
- my ($timername)=@_;
- my ($name,$event)=split(":",$timername);
- DoTrigger($name, $event);
- $event =~ s/\W/_/g;
- delete ($defs{$name}{READINGS}{"timer_$event"});
-}
-
-sub DOIF_del_Timer
-{
- my ($hash,$event)=@_;
- my $name=$hash->{NAME};
- my $timername="$name:$event";
- delete $hash->{ptimer}{$timername};
- $event =~ s/\W/_/g;
- delete ($defs{$hash->{NAME}}{READINGS}{"timer_$event"});
- RemoveInternalTimer($timername);
-}
-
-sub DOIF_set_Event
-{
- my ($hash,$event)=@_;
- DOIF_set_Timer($hash,$event,0);
-}
-
sub
CmdDoIfPerl($$)
{
@@ -2958,7 +2836,7 @@ CmdDoIfPerl($$)
my $err="";
my $i=0;
-#def modify
+ #def modify
if ($init_done)
{
DOIF_delTimer($hash);
@@ -2975,14 +2853,6 @@ CmdDoIfPerl($$)
return("","") if ($tail =~ /^ *$/);
- $tail =~ s/set_Timer[ \t]*\(/DOIF_set_Timer\(\$hash,/g;
- $tail =~ s/get_Timer[ \t]*\(/DOIF_get_Timer\(\$hash,/g;
- $tail =~ s/del_Timer[ \t]*\(/DOIF_del_Timer\(\$hash,/g;
- $tail =~ s/set_Exec[ \t]*\(/DOIF_set_Exec\(\$hash,/g;
- $tail =~ s/get_Exec[ \t]*\(/DOIF_get_Exec\(\$hash,/g;
- $tail =~ s/del_Exec[ \t]*\(/DOIF_del_Exec\(\$hash,/g;
- $tail =~ s/set_Event[ \t]*\(/DOIF_set_Event\(\$hash,/g;
- $tail =~ s/set_Reading[ \t]*\(/readingsSingleUpdate\(\$hash,/g;
$tail =~ s/\$_(\w+)/\$hash->\{var\}\{$1\}/g;
while ($tail ne "") {
@@ -2992,7 +2862,7 @@ CmdDoIfPerl($$)
my $blockname=$1;
if ($blockname eq "subs") {
$perlblock =~ s/\$SELF/$hash->{NAME}/g;
- $perlblock ="no warnings 'redefine';".$perlblock;
+ $perlblock ="no warnings 'redefine';package DOIF;".$perlblock;
eval ($perlblock);
if ($@) {
return ("error in defs block",$@);
@@ -3133,7 +3003,7 @@ DOIF_Define($$$)
return undef if (AttrVal($hash->{NAME},"disable",""));
my $err;
my $msg;
-
+
if (!$cmd) {
$cmd="";
$defs{$hash->{NAME}}{DEF}="##";
@@ -3392,9 +3262,287 @@ DOIF_Get($@)
return undef;
}
+sub DOIF_PerlTimer
+{
+ my ($timername)=@_;
+ my ($name,$event)=split(":",$timername);
+ DoTrigger($name, $event);
+ $event =~ s/\W/_/g;
+ delete ($::defs{$name}{READINGS}{"timer_$event"});
+}
+
+
+package DOIF;
+
+use Date::Parse qw(str2time);
+use Time::HiRes qw(gettimeofday);
+
+sub DOIF_ExecTimer
+{
+ my ($timer)=@_;
+ my $hash=${$timer}->{hash};
+ my $timername=${$timer}->{name};
+ my $name=$hash->{NAME};
+ my $subname=${$timer}->{subname};
+ my $param=${$timer}->{param} if (defined ${$timer}->{param});
+ $hs=$hash;
+ if (!defined ($param)) {
+ eval ("package DOIF;$subname");
+ } else {
+ #eval ("package DOIF;$subname(\"$param\")");
+ eval('no strict "refs";&{$subname}($param);use strict "refs"');
+ }
+ if ($@) {
+ ::Log3 ($::defs{$name}{NAME},1 , "$name error in $subname: $@");
+ ::readingsSingleUpdate ($hash, "error", "in $subname: $@",0);
+ }
+ delete ($::defs{$name}{READINGS}{"timer_$timername"});
+}
+
+sub set_Exec
+{
+ my ($timername,$seconds,$subname,$param)=@_;
+ my $current = ::gettimeofday();
+ my $next_time = $current+$seconds;
+ $hs->{ptimer}{$timername}{time}=$next_time;
+ $hs->{ptimer}{$timername}{name}=$timername;
+ $hs->{ptimer}{$timername}{subname}=$subname;
+ $hs->{ptimer}{$timername}{param}=$param if (defined $param);
+ $hs->{ptimer}{$timername}{hash}=$hs;
+ ::RemoveInternalTimer(\$hs->{ptimer}{$timername});
+ if ($seconds > 0) {
+ ::readingsSingleUpdate ($hs,"timer_$timername",::strftime("%d.%m.%Y %H:%M:%S",localtime($next_time)),0);
+ }
+ ::InternalTimer($next_time, "DOIF::DOIF_ExecTimer",\$hs->{ptimer}{$timername}, 0);
+}
+
+
+sub get_Exec
+{
+ my ($timername)=@_;
+ my $current = ::gettimeofday();
+ if (defined $hs->{ptimer}{$timername}{time}) {
+ my $sec=$hs->{ptimer}{$timername}{time}-$current;
+ if ($sec > 0) {
+ return ($sec);
+ } else {
+ delete ($hs->{ptimer}{$timername}{time});
+ return (0);
+ }
+ } else {
+ return (0);
+ }
+}
+
+sub del_Exec
+{
+ my ($timername)=@_;
+ ::RemoveInternalTimer(\$hs->{ptimer}{$timername});
+ delete $hs->{ptimer}{$timername};
+ delete ($::defs{$hs->{NAME}}{READINGS}{"timer_$timername"});
+}
+
+
+sub set_Timer
+{
+ my ($event,$seconds)=@_;
+ my $name=$hs->{NAME};
+ my $timername="$name:$event";
+ my $current = ::gettimeofday();
+ my $next_time = $current+$seconds;
+ ::RemoveInternalTimer($timername);
+ $hs->{ptimer}{$timername}=$next_time;
+ if ($seconds > 0) {
+ $event =~ s/\W/_/g;
+ ::readingsSingleUpdate ($hs,"timer_$event",::strftime("%d.%m.%Y %H:%M:%S",localtime($next_time)),0);
+ }
+ ::InternalTimer($next_time, "DOIF_PerlTimer", $timername, 0);
+}
+
+
+
+sub get_Timer
+{
+ my ($event)=@_;
+ my $name=$hs->{NAME};
+ my $timername="$name:$event";
+ my $current = ::gettimeofday();
+ if (defined $hs->{ptimer}{$timername}) {
+ my $sec=$hs->{ptimer}{$timername}-$current;
+ if ($sec > 0) {
+ return ($sec);
+ } else {
+ delete ($hs->{ptimer}{$timername});
+ return (0);
+ }
+ } else {
+ return (0);
+ }
+}
+
+sub del_Timer
+{
+ my ($event)=@_;
+ my $name=$hs->{NAME};
+ my $timername="$name:$event";
+ delete $hs->{ptimer}{$timername};
+ $event =~ s/\W/_/g;
+ delete ($::defs{$hs->{NAME}}{READINGS}{"timer_$event"});
+ ::RemoveInternalTimer($timername);
+}
+
+sub set_Event
+{
+ my ($event)=@_;
+ set_Timer($event,0);
+}
+
+sub set_State
+{
+ my ($content)=@_;
+ return(::readingsSingleUpdate($hs,"state",$content,1));
+}
+
+sub set_Reading
+{
+ my ($reading,$content,$trigger)=@_;
+ if (defined $trigger) {
+ return(::readingsSingleUpdate($hs,$reading,$content,$trigger));
+ } else {
+ return(::readingsSingleUpdate($hs,$reading,$content,0));
+ }
+}
+
+sub set_Reading_Begin
+{
+ return(::readingsBeginUpdate ($hs));
+}
+
+sub set_Reading_Update ($$@)
+{
+ my ($reading,$value,$changed)= @_;
+ return(::readingsBulkUpdate($hs, $reading, $value,$changed));
+}
+
+sub set_Reading_End
+{
+ my ($trigger)=@_;
+ return(::readingsEndUpdate($hs,$trigger));
+}
+
+sub get_State
+{
+ my ($default)=@_;
+ if (defined $default) {
+ return(::ReadingsVal($hs->{NAME},"state",$default));
+ } else {
+ return(::ReadingsVal($hs->{NAME},"state",""));
+ }
+}
+
+sub get_Reading
+{
+ my ($reading,$default)=@_;
+ if (defined $default) {
+ return(::ReadingsVal($hs->{NAME},$reading,$default));
+ } else {
+ return(::ReadingsVal($hs->{NAME},$reading,""));
+ }
+}
+
+sub fhem_set {
+ my ($content)=@_;
+ return(::CommandSet(undef,$content));
+}
+
+sub fhem {
+ my ($content)=@_;
+ return(::fhem($content));
+}
+
+sub Log {
+ my ($loglevel, $text) = @_;
+ return(::Log3(undef, $loglevel, $text));
+}
+
+sub Log3 {
+ my ($dev, $loglevel, $text) = @_;
+ return(::Log3($dev, $loglevel, $text));
+}
+
+sub InternalVal {
+ my ($d,$n,$default) = @_;
+ return(::InternalVal($d,$n,$default));
+}
+
+sub InternalNum {
+ my ($d,$n,$default,$round) = @_;
+ return(::InternalNum($d,$n,$default,$round));
+}
+
+sub OldReadingsVal {
+ my ($d,$n,$default) = @_;
+ return(::OldReadingsVal($d,$n,$default));
+}
+
+sub OldReadingsNum {
+ my ($d,$n,$default,$round) = @_;
+ return(::OldReadingsNum($d,$n,$default,$round));
+}
+
+sub OldReadingsTimestamp {
+ my ($d,$n,$default) = @_;
+ return(::OldReadingsTimestamp($d,$n,$default));
+}
+
+sub ReadingsVal {
+ my ($device,$reading,$default)=@_;
+ return(::ReadingsVal($device,$reading,$default));
+}
+
+sub ReadingsNum {
+ my ($d,$n,$default,$round) = @_;
+ return(::ReadingsNum($d,$n,$default,$round));
+}
+
+sub ReadingsTimestamp {
+ my ($d,$n,$default) = @_;
+ return(::ReadingsTimestamp($d,$n,$default));
+}
+
+sub ReadingsAge {
+ my ($device,$reading,$default) = @_;
+ return(::ReadingsAge($device,$reading,$default));
+}
+
+sub Value($) {
+ my ($d) = @_;
+ return(::Value($d));
+}
+
+sub OldValue {
+ my ($d) = @_;
+ return(::OldValue($d));
+}
+
+sub OldTimestamp {
+ my ($d) = @_;
+ return(::OldTimestamp($d));
+}
+
+sub AttrVal {
+ my ($d,$n,$default) = @_;
+ return(::AttrVal($d,$n,$default));
+}
+
+sub AttrNum {
+ my ($d,$n,$default,$round) = @_;
+ return (::AttrNum($d,$n,$default,$round));
+}
1;
+
=pod
=item helper
=item summary universal module, it works event- and time-controlled
@@ -5557,8 +5705,8 @@ Syntax Perl-Modus:
Ein Ereignisblock wird ausgeführt, wenn dieser bedingt durch Ereignis- und Zeittrigger in eckigen Klammern innerhalb des Blocks, getriggert wird.
Es wird die vollständige Perl-Syntax unterstützt. Es können beliebig viele Ereignisblöcke innerhalb eines DOIF-Devices definiert werden. Sie werden unabhängig voneinander durch passende Trigger ausgeführt. Der Name eines Ereignisblocks ist optional.
-Der Status des Moduls wird nicht vom Modul gesetzt, er kann vom Anwender mit Hilfe der Funktion set_Reading verändert werden, siehe spezifische Perl-Funktionen im Perl-Modus.
-FHEM-Befehle werden durch den Aufruf der Perlfunktion fhem"..." ausgeführt.
+Der Status des Moduls wird nicht vom Modul gesetzt, er kann vom Anwender mit Hilfe der Funktion set_State verändert werden, siehe spezifische Perl-Funktionen im Perl-Modus.
+FHEM-Befehle werden durch den Aufruf der Perlfunktion fhem"..." ausgeführt. Für den häufig genutzten fhem-Befehl set wurde eine kompatible Perlfunkton namens fhem_set definiert. Sie ist performanter und sollte bevorzugt verwendet werden, da das Parsen nach dem FHEM-set Befehl entfällt.
Der Benutzer kann mit der Funktion 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.
@@ -5603,7 +5751,38 @@ Es sind beliebige Hierarchietiefen möglich:
}
}
-Bemerkung: Innerhalb eines Ereignisblocks muss mindestens ein Trigger in irgendeiner Bedingung definiert werden, damit der gesamte Block beim passenden Trigger ausgewertet wird.
+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")}
Eigene Funktionen
@@ -5615,18 +5794,41 @@ Beispiel:
DOIF
subs { ## Definition von Perlfunktionen lamp_on und lamp_off
sub lamp_on {
- fhem"set lamp on";
- set_Reading("state","on",1);
+ fhem_set("lamp on");
+ set_State("on");
}
sub lamp_off {
- fhem"set lamp off";
- set_Reading("state","off",1);
+ fhem_set("lamp off");
+ set_State("off");
}
}
-{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
+{[06:00];lamp_on()} ## Um 06:00 Uhr wird die Funktion lamp_on aufgerufen
+{[08:00}];lamp_off()} ## Um 08:00 Uhr wird die Funktion lamp_off aufgerufen
+Eigene Funktionen mit Parametern
+
+Unter Verwendung von Funktionsparamerter lassen sich Definitionen oft vereinfachen, das obige Beispiel lässt sich mit Hilfe nur einer Funktion kürzer wie folgt definieren:
+
+DOIF
+subs { ## Definition der Perlfunktion lamp
+ sub lamp {
+ my ($state)=@_; # Variable $state mit dem Parameter belegen
+ fhem_set("lamp $state");
+ set_State($state);
+ }
+}
+{[06:00];lamp("on")} ## Um 06:00 Uhr wird die Funktion lamp mit Parameter "on" aufgerufen
+{[08:00];lamp("off")} ## Um 08:00 Uhr wird die Funktion lamp mit dem Parameter "off" aufgerufen
+
+
+
Der Namensraum im Perl-Modus ist gekapselt. Selbst definierte Funktionen können nicht bereits existierende Perlfunktionen in FHEM überschreiben.
+Selten genutze Funktionen aus dem Namensraum von FHEM müssen mit vorangestellem Doppelpunkt (Namensraum main von FHEM) angegeben werden: ::<perlfunction>
+
+Folgende FHEM-Perlfunktonen wurden im DOIF-Namensraum definiert: fhem, Log, Log3, InternVal, InternalNum, OldReadingsVal, OldReadingsNum, OldReadingsTimestamp, ReadingsVal, ReadingsNum, ReadingsTeimestamp, ReadingsAge, Value, OldValue, OldTimestamp, AttrVal, AttrNum
+
+Die obigen Funktionen können wie gewohnt ohne vorangestellten Doppelpunkt genutzt werden.
+
Spezifische Perl-Funktionen im Perl-Modus
@@ -5642,7 +5844,7 @@ Laufenden Timer löschen: del_Timer(<TimerEvent>)
Beispiel: Das Event "hello" 30 Sekunden verzögert auslösen:
-set_Time("hell",30);
+set_Time("hello",30);
Ausführungstimer
@@ -5656,11 +5858,52 @@ Laufenden Timer löschen: del_Exec(<timerName>)
Beispiel: Lampe verzögert um 30 Sekunden ausschalten:
-set_Exec("aus",30,'fhem"set lamp off"');
+set_Exec("aus",30,'fhem_set("lamp off")');
Ein beliebiges FHEM-Event absetzen: set_Event(<Event>)
-Reading schreiben: set_Reading(<readingName>,<content>,<trigger>), mit <trigger>: 0 ohne Trigger, 1 mit Trigger
+Beispiel: Setze das Event "on":
+
+set_Event("on");
+
+Status setzen: set_State(<value>,<trigger>), mit <trigger>: 0 ohne Trigger, 1 mit Trigger, <trigger> ist optional, default ist 1
+
+Beispiel: Status auf "on" setzen:
+
+set_State("on");
+
+Status des eigenen Devices holen: get_State()
+
+Beispiel: Schalte lampe mit dem eigenen Status:
+
+fhem_set("lamp ".get_State());
+
+Eigenes Reading schreiben: set_Reading(<readingName>,<value>,<trigger>), mit <trigger>: 0 ohne Trigger, 1 mit Trigger, <trigger> ist optional, default ist 0
+
+set_Reading("weather","cold");
+
+Reading des eigenen Devices holen: get_Reading("readingName")
+
+Beispiel: Schalte Lampe mit dem Inhalt des eigenen Readings "dim":
+
+fhem_set("lamp ".get_Reading("dim"));
+
+Setzen mehrere Readings des eigenen Devices in einem Eventblock:
+
+set_Reading_Begin()
+set_Reading_Update(<readingName>,<value>,<change>), <change> ist optional
+set_Reading_End(<trigger>), mit <trigger>: 0 ohne Trigger, 1 mit Trigger, <trigger>
+
+Die obigen Funktionen entsprechen den FHEM-Perlfunktionen: readingsBegin, readingsBulkUpdate, readingsEndUpdate.
+
+Beispiel:
+
+Die Readings "temperature" und "humidity" sollen in einem Eventblock mit dem zuvor belegten Inhalt der Perlvariablen $temp bzw. $hum belegt werden.
+
+set_Reading_Begin;
+set_Reading_Update("temperature",$temp);
+set_Reading_Update("humidity",$hum);
+set_Reading_End(1);
init-Block
@@ -5728,8 +5971,8 @@ Für unterschiedliche blockierende Funktionen ist jeweils ein eigener Name (<
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
+ 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
}
}
@@ -5742,10 +5985,10 @@ Anforderung: Wenn eine Taste innerhalb von zwei Sekunden zwei mal betätig wird,
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
+ 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
+ fhem_set("shutter up"); # Rollladen hoch
}
}