diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html
index 04bd6a1c6..bc59ca00e 100644
--- a/fhem/docs/commandref_frame.html
+++ b/fhem/docs/commandref_frame.html
@@ -38,6 +38,7 @@
attr
backup
CULflash
+ cancel
cmdalias
configdb
copy
@@ -732,6 +733,15 @@ The following local attributes are used by a wider range of devices:
+
+
cancel
+
+ cancel [<id> [quiet]]
+
+ Cancels a named sleep.
+
+
+
define
@@ -1250,13 +1260,16 @@ The following local attributes are used by a wider range of devices:
sleep
- sleep <sec> [quiet]
+ sleep <sec> [<id>] [quiet]
sleep followed by another command is comparable to a nameless at, it executes the following commands after waiting the
specified time. The unit is seconds, with millisecond accuracy, as you can
specify decimal places.
+ A sleep with an <id< will replace a sleep with the same <id<
+ and can be canceled by cancel.
+
When called in a notify/at/etc, then nonempty return values of the following
commands are logged to the global logfile with loglevel 2.
If quiet is
specified, then skip this logging.
diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html
index 0439506bf..fa0235c2d 100644
--- a/fhem/docs/commandref_frame_DE.html
+++ b/fhem/docs/commandref_frame_DE.html
@@ -38,6 +38,7 @@
attr
backup
CULflash
+ cancel
cmdalias
configdb
copy
@@ -761,6 +762,14 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
+
+cancel
+
+ cancel [<id> [quiet]]
+
+ Entfernt ein benanntes sleep.
+
+
define
@@ -1336,6 +1345,9 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
Sekunde, Millisekunden genau, da man Nachkommastellen spezifizieren
kann.
+ Ein sleep mit einer <id< ersetzt ein sleep mit der gleichen <id<
+ and can mit cancel entfernt werden.
+
Falls sleep in at/notify/etc aufgerufen wurde, und die nachfolgenden
Kommandos einen nicht leeren Text zurückgeliefert haben, dann wird
dieser Text mit loglevel 2 protokolliert.
diff --git a/fhem/fhem.pl b/fhem/fhem.pl
index 041c1f1b7..7aad1fcb1 100755
--- a/fhem/fhem.pl
+++ b/fhem/fhem.pl
@@ -127,6 +127,7 @@ sub setReadingsVal($$$$);
sub utf8ToLatin1($);
sub CommandAttr($$);
+sub CommandCancel($$);
sub CommandDefaultAttr($$);
sub CommandDefine($$);
sub CommandDefMod($$);
@@ -240,6 +241,7 @@ my $wbName = ".WRITEBUFFER"; # Buffer-name for delayed writing via select
my %comments; # Comments from the include files
my %duplicate; # Pool of received msg for multi-fhz/cul setups
my @cmdList; # Remaining commands in a chain. Used by sleep
+my %sleepers; # list of sleepers
$init_done = 0;
$lastDefChange = 0;
@@ -307,6 +309,8 @@ $readingFnAttributes = "event-on-change-reading event-on-update-reading ".
"?" => { ReplacedBy => "help" },
"attr" => { Fn=>"CommandAttr",
Hlp=>" [],set attribute for "},
+ "cancel" => { Fn=>"CommandCancel",
+ Hlp=>"[ [quiet]],list sleepers, cancel sleeper with " },
"createlog"=> { ModuleName => "autocreate" },
"define" => { Fn=>"CommandDefine",
Hlp=>" ,define a device" },
@@ -361,7 +365,7 @@ $readingFnAttributes = "event-on-change-reading event-on-update-reading ".
"shutdown"=> { Fn=>"CommandShutdown",
Hlp=>"[restart],terminate the server" },
"sleep" => { Fn=>"CommandSleep",
- Hlp=>" [quiet],sleep for sec, 3 decimal places" },
+ Hlp=>" [] [quiet],sleep for sec, 3 decimal places" },
"trigger" => { Fn=>"CommandTrigger",
Hlp=>" ,trigger notify command" },
"update" => {
@@ -2625,28 +2629,65 @@ sub
WakeUpFn($)
{
my $h = shift;
+ delete $sleepers{$h->{id}} if( $h->{id} );
+
$evalSpecials = $h->{evalSpecials};
my $ret = AnalyzeCommandChain(undef, $h->{cmd});
Log 2, "After sleep: $ret" if($ret && !$h->{quiet});
}
+sub
+CommandCancel($$)
+{
+ my ($cl, $param) = @_;
+ my ($id, $quiet) = split(" ", $param, 3);
+ return "Last parameter must be quiet" if($quiet && $quiet ne "quiet");
+ if( !$id ) {
+ my $ret;
+ foreach $id (keys %sleepers) {
+ $ret .= "\n" if( $ret );
+ $ret .= sprintf( "%-10s %s", $id, $sleepers{$id}->{cmd} );
+ }
+ $ret = "no pending sleeps" if( !$ret );
+ return $ret;
+
+ } elsif( my $h = $sleepers{$id} ) {
+ RemoveInternalTimer( $h );
+ delete $sleepers{$h->{id}};
+
+ } else {
+ return "no such id: $id" if( !$quiet );
+
+ }
+
+ return undef;
+}
sub
CommandSleep($$)
{
my ($cl, $param) = @_;
- my ($sec, $quiet) = split(" ", $param);
+ my ($sec, $id, $quiet) = split(" ", $param, 3);
+ if( $id && $id eq 'quiet' ) {
+ $quiet = $id;
+ $id = undef;
+ }
return "Argument missing" if(!defined($sec));
return "Cannot interpret $sec as seconds" if($sec !~ m/^[0-9\.]+$/);
- return "Second 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";
if(@cmdList && $sec && $init_done) {
my %h = (cmd => join(";", @cmdList),
evalSpecials => $evalSpecials,
- quiet => $quiet);
+ quiet => $quiet,
+ id => $id);
+ if( $id ) {
+ RemoveInternalTimer( $sleepers{$id} ) if( $sleepers{$id} );
+ $sleepers{$id} = \%h;
+ }
InternalTimer(gettimeofday()+$sec, "WakeUpFn", \%h, 0);
@cmdList=();