From c09ecc8127c68c35674b1c6764a22b8bdd922ac6 Mon Sep 17 00:00:00 2001
From: damian-s <>
Date: Fri, 26 Dec 2014 19:36:30 +0000
Subject: [PATCH] 98_DOIF.pm new features relative time, ? for no trigger new
attributes: resetwait, repeatsame, waitsame, cmdpause, initialize sec for he
time in seconds since the last change of reading docu adapted
git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@7328 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
FHEM/98_DOIF.pm | 452 +++++++++++++++++++++++++++++++++---------------
1 file changed, 315 insertions(+), 137 deletions(-)
diff --git a/FHEM/98_DOIF.pm b/FHEM/98_DOIF.pm
index b94b22fa8..07efa5bc7 100644
--- a/FHEM/98_DOIF.pm
+++ b/FHEM/98_DOIF.pm
@@ -35,7 +35,7 @@ DOIF_Initialize($)
$hash->{UndefFn} = "DOIF_Undef";
$hash->{AttrFn} = "DOIF_Attr";
$hash->{NotifyFn} = "DOIF_Notify";
- $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always cmdState state";
+ $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6 wait do:always,resetwait cmdState state initialize repeatsame waitsame cmdpause";
}
@@ -90,7 +90,14 @@ InternalDoIf($$$)
$element=$r;
}
return($element);
+}
+sub
+ReadingSecDoIf($$)
+{
+ my ($name,$reading)=@_;
+ my ($seconds, $microseconds) = gettimeofday();
+ return ($seconds - time_str2num(ReadingsTimestamp($name, $reading, "1970-01-01 01:00:00")));
}
sub
@@ -122,12 +129,12 @@ EvalAllDoIf($)
($beginning,$eval,$err,$tailBlock)=GetBlockDoIf($tailBlock,'[\{\}]');
return ($eval,$err) if ($err);
if ($eval) {
- if (substr($eval,0,1) eq "(") {
+ if ($eval =~ m/^[\d]+$/) {
+ $eval="{".$eval."}";
+ } else {
my $ret = eval $eval;
return($eval." ",$@) if ($@);
$eval=$ret;
- } else {
- $eval="{".$eval."}";
}
}
$cmd.=$beginning.$eval;
@@ -151,13 +158,15 @@ sub ReplaceReadingDoIf($)
if ($format) {
if ($format eq "d") {
$regExp = '(-?\d+(\.\d+)?)';
+ } elsif ($format eq "sec") {
+ return("ReadingSecDoIf('$name','$reading')","",$name,$reading,undef);
} elsif (substr($format,0,1) eq '[') {
- ($beginning,$regExp,$err,$tailBlock)=GetBlockDoIf($format,'[\[\]]');
- return ($regExp,$err) if ($err);
- return ($regExp,"no round brackets in regular expression") if ($regExp !~ /.*\(.*\)/);
- } else {
- return($format,"unknown expression format");
- }
+ ($beginning,$regExp,$err,$tailBlock)=GetBlockDoIf($format,'[\[\]]');
+ return ($regExp,$err) if ($err);
+ return ($regExp,"no round brackets in regular expression") if ($regExp !~ /.*\(.*\)/);
+ } else {
+ return($format,"unknown expression format");
+ }
}
if ($internal) {
return("InternalDoIf('$name','$internal','$regExp')","",$name,undef,$internal);
@@ -197,21 +206,26 @@ sub ReplaceAllReadingsDoIf($$$$)
my $definition=$tailBlock;
my $reading;
my $internal;
+ my $trigger=1;
while ($tailBlock ne "") {
+ $trigger=1;
($beginning,$block,$err,$tailBlock)=GetBlockDoIf($tailBlock,'[\[\]]');
return ($block,$err) if ($err);
if ($block ne "") {
+ if (substr($block,0,1) eq "?") {
+ $block=substr($block,1);
+ $trigger=0;
+ }
if ($condition >= 0) {
- ($timer,$err)=DOIF_CheckTimers($hash,$block,$condition,\@timerarray);
+ ($timer,$err)=DOIF_CheckTimers($hash,$block,$condition,$trigger,\@timerarray);
return($timer,$err) if ($err);
if ($timer) {
$cmd.=$beginning.$timer;
- $event=1;
+ $event=1 if ($trigger);
next;
}
}
- if ($block =~ /:/ or ($block =~ /[a-z]/i and $block =~ /^[a-z0-9._]*$/i))
- {
+ if ($block =~ /:/ or ($block =~ /[a-z]/i and $block =~ /^[a-z0-9._]*$/i)) {
($block,$err,$device,$reading,$internal)=ReplaceReadingDoIf($block);
return ($block,$err) if ($err);
if ($eval) {
@@ -221,16 +235,18 @@ sub ReplaceAllReadingsDoIf($$$$)
return($block." ",$@) if ($@);
$block=$ret;
}
- if ($condition >= 0) {
- $hash->{devices}{$condition} = AddItemDoIf($hash->{devices}{$condition},$device);
- $hash->{devices}{all} = AddItemDoIf($hash->{devices}{all},$device);
- $hash->{readings}{$condition} = AddItemDoIf($hash->{readings}{$condition},"$device:$reading") if (defined ($reading));
- $hash->{internals}{$condition} = AddItemDoIf($hash->{internals}{$condition},"$device:$internal") if (defined ($internal));
- $hash->{readings}{all} = AddItemDoIf($hash->{readings}{all},"$device:$reading") if (defined ($reading));
- $hash->{internals}{all} = AddItemDoIf($hash->{internals}{all},"$device:$internal") if (defined ($internal));
- $event=1;
- } elsif ($condition == -2) {
- $hash->{state}{device} = AddItemDoIf($hash->{state}{device},$device) if ($device ne $hash->{NAME});
+ if ($trigger) {
+ if ($condition >= 0) {
+ $hash->{devices}{$condition} = AddItemDoIf($hash->{devices}{$condition},$device);
+ $hash->{devices}{all} = AddItemDoIf($hash->{devices}{all},$device);
+ $hash->{readings}{$condition} = AddItemDoIf($hash->{readings}{$condition},"$device:$reading") if (defined ($reading));
+ $hash->{internals}{$condition} = AddItemDoIf($hash->{internals}{$condition},"$device:$internal") if (defined ($internal));
+ $hash->{readings}{all} = AddItemDoIf($hash->{readings}{all},"$device:$reading") if (defined ($reading));
+ $hash->{internals}{all} = AddItemDoIf($hash->{internals}{all},"$device:$internal") if (defined ($internal));
+ $event=1;
+ } elsif ($condition == -2) {
+ $hash->{state}{device} = AddItemDoIf($hash->{state}{device},$device) if ($device ne $hash->{NAME});
+ }
}
} else {
$block="[".$block."]";
@@ -238,7 +254,7 @@ sub ReplaceAllReadingsDoIf($$$$)
}
$cmd.=$beginning.$block;
}
- return ($definition,"no state, reading or time in condition") if ($condition >=0 and $event == 0);
+ return ($definition,"no trigger in condition") if ($condition >=0 and $event == 0);
return ($cmd,"");
}
@@ -259,6 +275,12 @@ ParseCommandsDoIf($$$)
if ($tailBlock=~ /^\s*\{/) { # perl block
($beginning,$currentBlock,$err,$tailBlock)=GetBlockDoIf($tailBlock,'[\{\}]');
return ($currentBlock,$err) if ($err);
+ if ($currentBlock ne "") {
+ ($currentBlock,$err)=ReplaceAllReadingsDoIf($hash,$currentBlock,-1,$eval);
+ return ($currentBlock,$err) if ($err);
+ ($currentBlock,$err)=EvalAllDoIf($currentBlock);
+ return ($currentBlock,$err) if ($err);
+ }
$currentBlock="{".$currentBlock."}";
} elsif ($tailBlock =~ /^\s*IF/) {
my $ifcmd="";
@@ -306,20 +328,20 @@ ParseCommandsDoIf($$$)
}
sub
-DOIF_CheckTimers($$$$)
+DOIF_CheckTimers($$$$$)
{
my $i=0;
my @nrs;
my @times;
- my $nr;
+ my $nr=0;
my $days="";
my $err;
my $beginning;
my $pos;
my $time;
my $block;
- my ($hash,$timer,$condition,$timerarray)=@_;
- if ($timer =~ /^((\{.*\})|([0-2][0-9](:[0-5][0-9]){1,2}))(\|[0-8]+$|-([0-2][0-9](:[0-5][0-9]){1,2})|-({.*})|$)(\|[0-8]+$|$)/) {
+ my ($hash,$timer,$condition,$trigger,$timerarray)=@_;
+ if ($timer =~ /^(\+)?((\{.*\})|([0-9][0-9](:[0-5][0-9]){1,2}))(\|[0-8]+$|-(\+)?([0-9][0-9](:[0-5][0-9]){1,2})|-(\+)?({.*})|$)(\|[0-8]+$|$)/) {
while ($timer ne "") {
if ($timer=~ /^\s*\{/) {
($beginning,$time,$err,$timer)=GetBlockDoIf($timer,'[\{\}]');
@@ -338,16 +360,15 @@ DOIF_CheckTimers($$$$)
($time,$days)=split(/\|/,$timer);
$timer="";
}
- $nr=$hash->{helper}{last_timer}++;
$times[$i]=$time;
- $nrs[$i++]=$nr;
+ $nrs[$i++]=$hash->{helper}{last_timer}++;
$timer=substr($timer,pos($timer)) if ($timer =~ /^\s*\-/g);
}
$days = "" if (!defined ($days));
for (my $j=0; $j<$i;$j++) {
$nr=$nrs[$j];
$time=$times[$j];
- $time .=":00" if ($time =~ m/^[0-2][0-9]:[0-5][0-9]$/);
+ $time .=":00" if ($time =~ m/^[0-9][0-9]:[0-5][0-9]$/);
$hash->{timer}{$nr}=0;
$hash->{time}{$nr}=$time;
$hash->{timeCond}{$nr}=$condition;
@@ -355,7 +376,7 @@ DOIF_CheckTimers($$$$)
${$timerarray}[$nr]={hash=>$hash,nr=>$nr};
$err=(DOIF_SetTimer("DOIF_TimerTrigger",\${$timerarray}[$nr]));
return($hash->{time}{$nr},$err) if ($err);
- $hash->{timers}{$condition}.=" $nr ";
+ $hash->{timers}{$condition}.=" $nr " if ($trigger);
$hash->{timerfunc}{$nr}=\${$timerarray}[$nr];
}
if ($i == 2) {
@@ -512,7 +533,49 @@ DOIF_cmd ($$$)
my $ret;
my $cmd;
my $err="";
- if ($hash->{do}{$nr}) {
+ my $repeatnr;
+ my $last_cmd=ReadingsVal($pn,"cmd_nr",0)-1;
+ my @repeatsame=split(/:/,AttrVal($pn,"repeatsame",""));
+ my @cmdpause=split(/:/,AttrVal($pn,"cmdpause",""));
+ my @waitsame=split(/:/,AttrVal($pn,"waitsame",""));
+ my ($seconds, $microseconds) = gettimeofday();
+ if ($cmdpause[$nr]) {
+ return undef if ($seconds - time_str2num(ReadingsTimestamp($pn, "state", "1970-01-01 01:00:00")) < $cmdpause[$nr]);
+ }
+ if (AttrVal($pn,"repeatsame","")) {
+ if ($repeatsame[$nr]) {
+ $repeatnr=ReadingsVal($pn,"cmd_count",0);
+ if ($last_cmd == $nr) {
+ if ($repeatnr < $repeatsame[$nr]) {
+ $repeatnr++;
+ } else {
+ return undef;
+ }
+ } else {
+ $repeatnr=1;
+ }
+ readingsSingleUpdate ($hash, "cmd_count", $repeatnr,1);
+ } else {
+ return undef if ($last_cmd == $nr and AttrVal($pn,"do","") ne "always");
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_count});
+ }
+ }
+ if (AttrVal($pn,"waitsame","")) {
+ if ($waitsame[$nr]) {
+ my $cmd_nr="cmd_".($nr+1);
+ if (ReadingsVal($pn,"waitsame","") eq $cmd_nr) {
+ if ($seconds - time_str2num(ReadingsTimestamp($pn, "waitsame", "1970-01-01 01:00:00")) > $waitsame[$nr]) {
+ readingsSingleUpdate ($hash, "waitsame", $cmd_nr,1);
+ return undef;
+ }
+ } else {
+ readingsSingleUpdate ($hash, "waitsame", $cmd_nr,1);
+ return undef;
+ }
+ }
+ delete ($defs{$hash->{NAME}}{READINGS}{waitsame});
+ }
+ if ($hash->{do}{$nr}) {
($cmd,$err)=ParseCommandsDoIf($hash,$hash->{do}{$nr},1);
}
DOIF_SetState ($hash,$nr,$event,$err);
@@ -560,18 +623,12 @@ DOIF_Trigger ($$$)
}
}
if ($doelse) { #DOELSE
- if (defined ($hash->{do}{$max_cond})) { #DOELSE does exist
+ if (defined ($hash->{do}{$max_cond}) or $max_cond == 1) { #DOELSE
if (DOIF_SetSleepTimer($hash,$last_cond,$max_cond,$device,$timerNr)) {
DOIF_cmd ($hash,$max_cond,$event) ;
return 1;
}
}
- elsif ($max_cond == 1) {
- if (DOIF_SetSleepTimer($hash,$last_cond,$max_cond,$device,$timerNr)) {
- DOIF_SetState($hash,$max_cond,$event,"");
- return 1;
- }
- }
}
return undef;
}
@@ -602,6 +659,11 @@ DOIF_Notify($$)
readingsSingleUpdate ($hash, "e_".$dev->{NAME}."_".$internal,$defs{$device}{$internal},0) if ($item and $device eq $dev->{NAME} and $defs{$device}{$internal});
}
}
+ #my ($seconds, $microseconds) = gettimeofday();
+ #if ($hash->{helper}{last_event_time}) {
+ # return undef if (($seconds-$hash->{helper}{last_event_time}) < AttrVal($pn,"eventpause",0));
+ #}
+ #$hash->{helper}{last_event_time}=$seconds;
$ret=DOIF_Trigger($hash,$dev->{NAME},-1);
}
if (($hash->{state}{device}) and $hash->{state}{device} =~ / $dev->{NAME} / and !$ret) {
@@ -617,7 +679,8 @@ my ($timer)=@_;
my $nr=${$timer}->{nr};
my $hash=${$timer}->{hash};
my $ret;
- if (!AttrVal($hash->{NAME},"disable","")) {$hash->{timer}{$nr}=1;
+ if (!AttrVal($hash->{NAME},"disable","")) {
+ $hash->{timer}{$nr}=1;
$ret=DOIF_Trigger ($hash,"",$nr);
$hash->{timer}{$nr}=0;
}
@@ -633,6 +696,12 @@ DOIF_SetTimer($$)
my $hash=${$timer}->{hash};
my $timeStr=$hash->{time}{$nr};
my $cond=$hash->{timeCond}{$nr};
+ my $rel=0;
+ my $next_time;
+ if (substr($timeStr,0,1) eq "+") {
+ $timeStr=substr($timeStr,1);
+ $rel=1;
+ }
my ($err, $h, $m, $s, $fn) = GetTimeSpec($timeStr);
return $err if($err);
my $second = $h*3600+$m*60+$s;
@@ -642,8 +711,12 @@ DOIF_SetTimer($$)
my $isdst_now=$isdst;
my $sec_today = $hour*3600+$min*60+$sec;
my $midnight = $now-$sec_today;
- my $next_time = $midnight+$second;
- $next_time+=86400 if ($sec_today>=$second);
+ if ($rel) {
+ $next_time =$now+$second;
+ } else {
+ $next_time = $midnight+$second;
+ }
+ $next_time+=86400 if ($sec_today>=$second and !$rel);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($next_time);
if ($isdst_now != $isdst) {
if ($isdst_now == 1) {
@@ -667,7 +740,7 @@ DOIF_SetSleepTimer($$$$$)
my ($hash,$last_cond,$nr,$device,$timerNr)=@_;
my $pn = $hash->{NAME};
return 1 if ($timerNr == -2); #Sleeptrigger
- if ($hash->{helper}{sleeptimer} != -1 and $hash->{helper}{sleeptimer} != $nr) {
+ if ($hash->{helper}{sleeptimer} != -1 and ($hash->{helper}{sleeptimer} != $nr or AttrVal($pn,"do","") eq "resetwait")) {
RemoveInternalTimer($hash);
#delete ($defs{$hash->{NAME}}{READINGS}{wait_timer});
readingsSingleUpdate ($hash, "wait_timer", "no timer",1);
@@ -675,13 +748,13 @@ DOIF_SetSleepTimer($$$$$)
}
if ($timerNr >= 0) {#Timer
- if ($last_cond != $nr or AttrVal($pn,"do","") eq "always") {
+ if ($last_cond != $nr or AttrVal($pn,"do","") eq "always" or AttrVal($pn,"repeatsame","")) {
return 1;
} else {
return 0;
}
}
- if ($hash->{helper}{sleeptimer} == -1 and ($last_cond != $nr or AttrVal($pn,"do","") eq "always")) {
+ if ($hash->{helper}{sleeptimer} == -1 and ($last_cond != $nr or AttrVal($pn,"do","") eq "always" or AttrVal($pn,"do","") eq "resetwait" or AttrVal($pn,"repeatsame",""))) {
my @sleeptimer=split(/:/,AttrVal($pn,"wait",""));
if ($sleeptimer[$nr]) {
my ($seconds, $microseconds) = gettimeofday();
@@ -859,6 +932,11 @@ DOIF_Attr(@)
#delete ($defs{$hash->{NAME}}{READINGS}{wait_timer});
readingsSingleUpdate ($hash, "wait_timer", "no timer",1);
$hash->{helper}{sleeptimer}=-1;
+ } elsif($a[0] eq "set" && $a[2] eq "initialize") {
+ readingsSingleUpdate ($hash,"state",$a[3],1);
+ readingsSingleUpdate ($hash,"cmd_nr","0",1);
+ } elsif($a[0] eq "del" && $a[2] eq "repeatsame") {
+ delete ($defs{$hash->{NAME}}{READINGS}{cmd_count});
}
return undef;
}
@@ -901,11 +979,13 @@ DOIF is a universal module. It works event- and time-controlled.
It combines the functionality of a notify, at-, watchdog command with logical queries.
-With the module complex problems to be solved that would otherwise be realized with individual modules in several places in FHEM. This leads to clear solutions and simplifies their maintenance.
+Complex problems can be solved with this module, which would otherwise be solved only with several modules at different locations in FHEM. This leads to clear solutions and simplifies their maintenance.
-There is no need event in the event monitor to analyze. Instead, the status, readings or Internals of devices are specified.
-
-The state administration is an important distinguishing feature of DOIF to notify or at. In the module is executed last command detained and prevented repeatedly executing the same commands..
+Logical queries are created in conditions using Perl operators.
+These are combined with information from states, readings, internals of devices or times in square brackets.
+Arbitrary Perl functions can also be specified that are defined in FHEM.
+The module is triggered by time or by events information through the Devices specified in the condition.
+If a condition is true, the associated FHEM- or Perl commands are executed.
Syntax:
@@ -915,40 +995,23 @@ The commands are always processed from left to right. There is only one command
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[<devicename>]
, readings with [<devicename>:<readingname>]
or internals with [<devicename>:&<internal>]
[HH:MM:SS]
or [HH:MM]
or [{<perl-function>}]
[<begin>-<end>]
for <begin>
and <end>
, the above time format can be selected.[+<time>]
or [+<begin>-+<end>]
combined with Perl functions[<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[<devicename>]
, Readings mit [<devicename>:<readingname>]
und Internals mit [<devicename>:&<internal>]
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>]
oder [+<begin>-+<end>]
kombinierbar mit Perl-Funktionen s. o.[<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]
==, !=, <, <=, >, >=
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.define di_garage DOIF ([remotecontrol] eq "on") (set garage on) DOELSEIF ([remotecontrol] eq "off") (set garage off)
attr di_garage do always
=~
vorgenommen werden.define di_garage DOIF ([remotecontrol] =~ "Long") (set garage on)
+attr di_garage do always
=~
, insbesondere in Verbindung mit regulären Ausdrücken, können in der Perl-Dokumentation nachgeschlagen werden.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] or [10:00] or [20:00]) (set switch on) DOELSEIF ([09:00] or [11:00] or [00:00]) (set switch off)
define di_save DOIF ([+01:00]) (save)
+attr di_save do always
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_lamp DOIF ([06:00-09:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)
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)
define di_motion DOIF ([?06:00-10:00] and [BM] eq "motion")(set lamp on-for-timer 600)
+attr di_motion do always
define di_button DOIF ([button]) (set lamp1 [lamp2])
attr di_button do always
define di_pushmsg DOIF ([window] eq "open" and [alarm] eq "armed") (set Pushover msg 'alarm' 'open windows [window:LastDevice]' '' 2 'persistent' 30 3600)
define di_average DOIF ([08:00]) (set TH_Modul desired {([default:temperature]+[outdoor:temperature])/2})
attr di_average do always
define di_heating DOIF ([adjusting:actuator:d] < 10) (set heating off) DOELSE (set heating on)
define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
attr di_washer wait 300
define di_shutters DOIF ([Sun] eq "on") (set shutters down) DOELSE (set shutters up)
attr di_shutters wait 1200:1200
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_fan DOIF ([light] eq "on")
@@ -1150,6 +1237,59 @@ DOELSEIF ([light] eq "off" and [sensor:humidity]<60)
attr di_fan wait 120:0:180
define di_push DOIF ([Tempsensor])(set pushmsg "sensor failed again")
+attr di_push wait 1800
+attr di_push do resetwait
cmdpause <Sekunden für cmd_1>:<Sekunden für cmd_2>:...
wird die Zeitspanne in Sekunden angegeben für eine Zwangspause seit der letzten Zustandsänderung.
+In der angegebenen Zeitspanne wird ein Kommando nicht ausgeführt, auch wenn die dazugehörige Bedingung wahr wird.define di_frost DOIF ([outdoor:temperature] < 0) (set pushmsg "danger of frost")
+attr di_frost cmdpause 3600
+attr di_frost do always
repeatsame <maximale Anzahl von cmd_1>:<maximale Anzahl von cmd_2>:...
wird die maximale Anzahl hintereinander folgenden Ausführungen festgelegt.define di_washer DOIF ([Watt]<2) (set pushmeldung "washer finished")
+attr di_washer repeatsame 3
+attr di_washer cmdpause 600
waitsame <Zeitspanne in Sekunden für cmd_1>:<Zeitspanne in Sekunden für das cmd_2>:...
wird ein Kommando erst dann ausgeführt, wenn innerhalb einer definierten Zeitspanne die entsprechende Bedingung zwei mal hintereinander wahr wird.define di_shutters DOIF ([Button])(set shutters up)
+attr di_shutters waitsame 2
+attr di_shutters do always
[<Device>:<Reading>:sec]
in Sekunden seit der letzten Änderung bestimmt werdendefine di_lamp DOIF ([BM:state:sec] < 5)(set lamp on-for-timer 300)
+attr di_lamp do always
define di_hum DOIF ([outdoor:humidity]>70) DOELSEIF ([outdoor:humidity]>50) DOELSE
attr di_hum cmdState wet|normal|dry
attr di_hum state The current humidity is [outdoor:humidity], it is [di_hum]
define di_average DOIF
attr di_average state Average of the two rooms is {([room1:temperature]+[room2:temperature])/2}
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)}
di_lamp
mit "initialized" vorbelegt werden. Das Reading cmd_nr
wird auf 0 gesetzt, damit wird ein Zustandswechsel provoziert, das Modul wird initialisiert - der nächste Trigger führt zum Ausführen eines Kommandos.attr di_lamp intialize initialized
define di_light DOIF ([08:00]) (set switch on)
attr di_light do always
define di_heating DOIF ([sens:temperature] < 20)(set heating on)
define di_lamp ([brightness] < 50 and [lamp] eq "off")(set lamp on)
define di_lamp ([brightness] < 50 and [?lamp] eq "off")(set lamp on)