mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
fhem.pl: sleep can now wait for an event (Forum #100306)
git-svn-id: https://svn.fhem.de/fhem/trunk@19374 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
6e8848d460
commit
ae6859a3bd
@ -67,7 +67,8 @@ notify_Define($$)
|
|||||||
$hash->{".COMMAND"} = $command;
|
$hash->{".COMMAND"} = $command;
|
||||||
|
|
||||||
my $doTrigger = ($name !~ m/^$re$/); # Forum #34516
|
my $doTrigger = ($name !~ m/^$re$/); # Forum #34516
|
||||||
readingsSingleUpdate($hash, "state", "active", $doTrigger);
|
readingsSingleUpdate($hash, "state", "active", $doTrigger)
|
||||||
|
if(!$hash->{TEMPORARY});
|
||||||
InternalTimer(0, sub(){ notifyRegexpChanged($hash, $re); }, $hash);
|
InternalTimer(0, sub(){ notifyRegexpChanged($hash, $re); }, $hash);
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
|
@ -737,7 +737,7 @@ The following local attributes are used by a wider range of devices:
|
|||||||
<ul>
|
<ul>
|
||||||
<code>cancel [<id> [quiet]]</code>
|
<code>cancel [<id> [quiet]]</code>
|
||||||
<br><br>
|
<br><br>
|
||||||
Cancels a named <a href="#sleep">sleep</a>.
|
List named sleeps or cancel a named <a href="#sleep">sleep</a>.
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<!-- cancel end -->
|
<!-- cancel end -->
|
||||||
@ -1357,12 +1357,17 @@ The following local attributes are used by a wider range of devices:
|
|||||||
<a name="sleep"></a>
|
<a name="sleep"></a>
|
||||||
<h3>sleep</h3>
|
<h3>sleep</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<code>sleep <sec> [<id>] [quiet]</code>
|
<code>sleep <sec|timespec|regex> [<id>] [quiet]</code>
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
sleep followed by another command is comparable to a nameless <a
|
sleep followed by another command is comparable to a nameless <a
|
||||||
href="#at">at</a>, it executes the following commands after waiting the
|
href="#at">at</a> or <a href="#notify">notify</a>, it executes the
|
||||||
specified time. The unit is seconds, with millisecond accuracy, as you can
|
following commands after waiting for the specified time or an event matching
|
||||||
specify decimal places.<br><br>
|
<regex>. The delay can be given<ul>
|
||||||
|
<li>in seconds, with millisecond accuracy, as you can specify decimal places,
|
||||||
|
</li>
|
||||||
|
<li>as a timespec (HH:MM or HH::MM::SS or {perlfunc})</li>
|
||||||
|
<li>or as a regex (devicename or devicename:event)</li></ul><br>
|
||||||
|
|
||||||
A sleep with an <id> will replace a sleep with the same <id>
|
A sleep with an <id> will replace a sleep with the same <id>
|
||||||
and can be canceled by <a href="#cancel">cancel</a>.
|
and can be canceled by <a href="#cancel">cancel</a>.
|
||||||
|
@ -757,7 +757,7 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
|
|||||||
<ul>
|
<ul>
|
||||||
<code>cancel [<id> [quiet]]</code>
|
<code>cancel [<id> [quiet]]</code>
|
||||||
<br><br>
|
<br><br>
|
||||||
Entfernt ein benanntes <a href="#sleep">sleep</a>.
|
Listet benannte sleeps oder entfernt ein benanntes <a href="#sleep">sleep</a>.
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<!-- cancel end -->
|
<!-- cancel end -->
|
||||||
@ -1444,13 +1444,18 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
|
|||||||
<a name="sleep"></a>
|
<a name="sleep"></a>
|
||||||
<h3>sleep</h3>
|
<h3>sleep</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<code>sleep <sec> [<id>] [quiet]</code>
|
<code>sleep <sec|timespec|suchmuster> [<id>] [quiet]</code>
|
||||||
<br><br>
|
<br><br>
|
||||||
sleep gefolgt von weiteren Befehlen ist vergleichbar mit einem namenlosen <a
|
sleep gefolgt von weiteren Befehlen ist vergleichbar mit einem namenlosen <a
|
||||||
href="#at">at</a> Kommando, es führt die nachfolgenden Befehle aus,
|
href="#at">at</a> oder <a href="#notify">notify</a> Kommando, es führt
|
||||||
nachdem es die spezifizierte Zeitspanne gewartet hat. Die Einheit ist
|
die nachfolgenden Befehle aus, nachdem es die spezifizierte Zeitspanne
|
||||||
Sekunde, Millisekunden genau, da man Nachkommastellen spezifizieren
|
gewartet hat bzw. ein Event welches dem <suchmuster> entspricht
|
||||||
kann.<br><br>
|
aufgetreten ist. Die verzögerung kann<ul>
|
||||||
|
<li>in Sekunden (Millisekunden genau, da man Nachkommastellen spezifizieren
|
||||||
|
kann)</li>
|
||||||
|
<li> als timespec (HH:MM or HH::MM::SS oder {perlfunc})</li>
|
||||||
|
<li>oder als suchmuster (Gerätename oder Gerätename:Event)</li>
|
||||||
|
</ul> angegeben werden.<br>
|
||||||
|
|
||||||
Ein sleep mit einer <id> ersetzt ein sleep mit der gleichen <id>
|
Ein sleep mit einer <id> ersetzt ein sleep mit der gleichen <id>
|
||||||
and can mit <a href="#cancel">cancel</a> entfernt werden.
|
and can mit <a href="#cancel">cancel</a> entfernt werden.
|
||||||
|
68
fhem/fhem.pl
68
fhem/fhem.pl
@ -106,7 +106,6 @@ sub SemicolonEscape($);
|
|||||||
sub SignalHandling();
|
sub SignalHandling();
|
||||||
sub TimeNow();
|
sub TimeNow();
|
||||||
sub Value($);
|
sub Value($);
|
||||||
sub WakeUpFn($);
|
|
||||||
sub WriteStatefile();
|
sub WriteStatefile();
|
||||||
sub XmlEscape($);
|
sub XmlEscape($);
|
||||||
sub addEvent($$);
|
sub addEvent($$);
|
||||||
@ -2059,6 +2058,7 @@ CommandDefine($$)
|
|||||||
if($currcfgfile ne AttrVal("global", "configfile", "") &&
|
if($currcfgfile ne AttrVal("global", "configfile", "") &&
|
||||||
!configDBUsed());
|
!configDBUsed());
|
||||||
$hash{CL} = $cl;
|
$hash{CL} = $cl;
|
||||||
|
$hash{TEMPORARY} = 1 if($temporary);
|
||||||
|
|
||||||
# If the device wants to issue initialization gets/sets, then it needs to be
|
# If the device wants to issue initialization gets/sets, then it needs to be
|
||||||
# in the global hash.
|
# in the global hash.
|
||||||
@ -2073,7 +2073,6 @@ CommandDefine($$)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
delete $hash{CL};
|
delete $hash{CL};
|
||||||
$hash{TEMPORARY} = 1 if($temporary);
|
|
||||||
foreach my $da (sort keys (%defaultattr)) { # Default attributes
|
foreach my $da (sort keys (%defaultattr)) { # Default attributes
|
||||||
CommandAttr($cl, "$name $da $defaultattr{$da}");
|
CommandAttr($cl, "$name $da $defaultattr{$da}");
|
||||||
}
|
}
|
||||||
@ -2082,8 +2081,10 @@ CommandDefine($$)
|
|||||||
$modules{$m}{NotifyOrderPrefix} : "50-") . $name;
|
$modules{$m}{NotifyOrderPrefix} : "50-") . $name;
|
||||||
}
|
}
|
||||||
%ntfyHash = ();
|
%ntfyHash = ();
|
||||||
addStructChange("define", $name, $def);
|
if(!$temporary && !$init_done) {
|
||||||
DoTrigger("global", "DEFINED $name", 1) if($init_done);
|
addStructChange("define", $name, $def);
|
||||||
|
DoTrigger("global", "DEFINED $name", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ($ret && $ignoreErr ?
|
return ($ret && $ignoreErr ?
|
||||||
"Cannot define $name, remove -ignoreErr for details" : $ret);
|
"Cannot define $name, remove -ignoreErr for details" : $ret);
|
||||||
@ -3133,15 +3134,19 @@ CommandTrigger($$)
|
|||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
WakeUpFn($)
|
sleep_WakeUpFn($)
|
||||||
{
|
{
|
||||||
my $h = shift;
|
my $id = shift;
|
||||||
delete $sleepers{$h->{id}} if( $h->{id} );
|
my $h = $sleepers{$id};
|
||||||
|
return if(!$h);
|
||||||
|
delete $sleepers{$id};
|
||||||
|
CommandDelete($h->{cl}, $h->{name}) if(!defined($h->{sec}));
|
||||||
|
|
||||||
$evalSpecials = $h->{evalSpecials};
|
$evalSpecials = $h->{evalSpecials};
|
||||||
my $ret = AnalyzeCommandChain($h->{cl}, $h->{cmd});
|
my $ret = AnalyzeCommandChain($h->{cl}, $h->{cmd});
|
||||||
Log 2, "After sleep: $ret" if($ret && !$h->{quiet});
|
Log 2, "After sleep: $ret" if($ret && !$h->{quiet});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
CommandCancel($$)
|
CommandCancel($$)
|
||||||
{
|
{
|
||||||
@ -3151,16 +3156,18 @@ CommandCancel($$)
|
|||||||
|
|
||||||
if( !$id ) {
|
if( !$id ) {
|
||||||
my $ret;
|
my $ret;
|
||||||
foreach $id (keys %sleepers) {
|
foreach $id (sort keys %sleepers) {
|
||||||
|
my $h = $sleepers{$id};
|
||||||
$ret .= "\n" if( $ret );
|
$ret .= "\n" if( $ret );
|
||||||
$ret .= sprintf( "%-10s %s", $id, $sleepers{$id}->{cmd} );
|
$ret .= sprintf( "%-12s %-19s %s", $id, $h->{till}, $h->{cmd} );
|
||||||
}
|
}
|
||||||
$ret = "no pending sleeps" if( !$ret );
|
$ret = "no pending sleeps" if(!$ret);
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
} elsif( my $h = $sleepers{$id} ) {
|
} elsif( my $h = $sleepers{$id} ) {
|
||||||
RemoveInternalTimer( $h );
|
RemoveInternalTimer($id, "sleep_WakeUpFn") if(defined($h->{sec}));
|
||||||
delete $sleepers{$h->{id}};
|
CommandDelete($cl, $h->{name}) if(!defined($h->{sec}));
|
||||||
|
delete $sleepers{$id};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "no such id: $id" if( !$quiet );
|
return "no such id: $id" if( !$quiet );
|
||||||
@ -3179,24 +3186,47 @@ CommandSleep($$)
|
|||||||
$quiet = $id;
|
$quiet = $id;
|
||||||
$id = undef;
|
$id = undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Argument missing" if(!defined($sec));
|
return "Argument missing" if(!defined($sec));
|
||||||
return "Cannot interpret $sec as seconds" if($sec !~ m/^[0-9\.]+$/);
|
|
||||||
return "Last parameter must be quiet" if($quiet && $quiet ne "quiet");
|
return "Last parameter must be quiet" if($quiet && $quiet ne "quiet");
|
||||||
|
|
||||||
Log 4, "sleeping for $sec";
|
my $name = ".sleep_".(++$intAtCnt);
|
||||||
|
$id = $name if(!$id);
|
||||||
|
|
||||||
|
my $till;
|
||||||
|
if($sec !~ m/^[0-9\.]+$/) {
|
||||||
|
my ($err, $hr,$min,$s, $fn) = GetTimeSpec($sec);
|
||||||
|
if($err) { # not a valid timespec => treat as regex
|
||||||
|
if(@cmdList && $init_done) {
|
||||||
|
CommandDelete($cl, $name) if($defs{$name});
|
||||||
|
$err = CommandDefine($cl,
|
||||||
|
"-temporary $name notify $sec {sleep_WakeUpFn('$id')}");
|
||||||
|
$attr{$name}{ignore} = 1;
|
||||||
|
return $err if($err);
|
||||||
|
}
|
||||||
|
$till = $sec;
|
||||||
|
$sec = undef;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$sec = 3600*$hr+60*$min+$s;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$till = gettimeofday()+$sec if(defined($sec));
|
||||||
|
|
||||||
if(@cmdList && $init_done) {
|
if(@cmdList && $init_done) {
|
||||||
my %h = (cmd => join(";", @cmdList),
|
my %h = (cmd => join(";", @cmdList),
|
||||||
evalSpecials => $evalSpecials,
|
evalSpecials => $evalSpecials,
|
||||||
quiet => $quiet,
|
quiet => $quiet,
|
||||||
|
till => defined($sec) ? FmtDateTime($till) : $till,
|
||||||
|
sec => $sec,
|
||||||
|
name => $name,
|
||||||
cl => $cl,
|
cl => $cl,
|
||||||
id => $id);
|
id => $id);
|
||||||
if( $id ) {
|
if(defined($sec)) {
|
||||||
RemoveInternalTimer( $sleepers{$id} ) if( $sleepers{$id} );
|
RemoveInternalTimer($id, "sleep_WakeUpFn");
|
||||||
$sleepers{$id} = \%h;
|
InternalTimer($till, "sleep_WakeUpFn", $id, 0);
|
||||||
}
|
}
|
||||||
InternalTimer(gettimeofday()+$sec, "WakeUpFn", \%h, 0);
|
$sleepers{$id} = \%h;
|
||||||
@cmdList=();
|
@cmdList=();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user