2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

set extensions (on-for-timer, etc)

git-svn-id: https://svn.fhem.de/fhem/trunk@2582 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2013-01-27 21:30:41 +00:00
parent 6449ed79ed
commit 0340785260
7 changed files with 290 additions and 28 deletions

View File

@ -51,10 +51,11 @@
- feature: telnet client mode - feature: telnet client mode
- bugfix: FHEMWEB longpoll misses initial state change (HM: set_on vs. on) - bugfix: FHEMWEB longpoll misses initial state change (HM: set_on vs. on)
- change: 20_OWFS.pm, 21_OWTEMP modules flagged as "deprecated". These - change: 20_OWFS.pm, 21_OWTEMP modules flagged as "deprecated". These
modules will be removed in a future release. Use OWServer / OWDevice modules will be removed in a future release. Use OWServer /
instead. (M. Fischer) OWDevice instead. (M. Fischer)
- feature: a lot of new features and known 1-wire slaves to OWServer / - feature: a lot of new features and known 1-wire slaves to OWServer /
OWDevice added (M. Fischer) OWDevice added (M. Fischer)
- feature: set-extensions (additional set commands) for FS20, EnOcean, ZWave
- 2012-10-28 (5.3) - 2012-10-28 (5.3)
- feature: added functions trim, ltrim, rtrim, UntoggleDirect, - feature: added functions trim, ltrim, rtrim, UntoggleDirect,

View File

@ -4,6 +4,7 @@ package main;
use strict; use strict;
use warnings; use warnings;
use SetExtensions;
sub EnOcean_Define($$); sub EnOcean_Define($$);
sub EnOcean_Initialize($); sub EnOcean_Initialize($);
@ -221,8 +222,10 @@ EnOcean_Set($@)
$dimVal=0; $dimVal=0;
} else { } else {
return "Unknown argument $cmd, choose one of dim:slider,0,1,100 ". my $list = "dim:slider,0,1,100 dimup:slider,0,1,100 ".
"dimup:slider,0,1,100 dimdown:slider,0,1,100 on off teach" "dimdown:slider,0,1,100 on off teach";
return SetExtensions($hash, $list, $name, @a);
} }
if($sendDimCmd) { if($sendDimCmd) {
@ -288,11 +291,12 @@ EnOcean_Set($@)
########################### ###########################
} else { # Simulate a PTM } else { # Simulate a PTM
my ($c1,$c2) = split(",", $cmd, 2); my ($c1,$c2) = split(",", $cmd, 2);
return "Unknown argument $cmd, choose one of " .
join(" ", sort keys %EnO_ptm200btn) if(!defined($EnO_ptm200btn{$c1}) ||
if(!defined($EnO_ptm200btn{$c1}) || ($c2 && !defined($EnO_ptm200btn{$c2}))) {
($c2 && !defined($EnO_ptm200btn{$c2}))); my $list = join(" ", sort keys %EnO_ptm200btn);
Log $ll2, "EnOcean: set $name $cmd"; return SetExtensions($hash, $list, $name, @a);
}
my ($db_3, $status) = split(":", $EnO_ptm200btn{$c1}, 2); my ($db_3, $status) = split(":", $EnO_ptm200btn{$c1}, 2);
$db_3 <<= 5; $db_3 <<= 5;
@ -636,6 +640,7 @@ EnOcean_A5Cmd($$$)
<a name="EnOceanset"></a> <a name="EnOceanset"></a>
<b>Set</b> <b>Set</b>
<ul> <ul>
<br>
<li>MD15 commands. Note: The command is not sent until the MD15 <li>MD15 commands. Note: The command is not sent until the MD15
wakes up and sends a mesage, usually every 10 minutes. wakes up and sends a mesage, usually every 10 minutes.
<ul> <ul>
@ -705,6 +710,10 @@ EnOcean_A5Cmd($$$)
attr eventMap BI:on B0:off<br> attr eventMap BI:on B0:off<br>
set switch1 on<br> set switch1 on<br>
</code></ul> </code></ul>
<b>Note</b>: <a href="#setExtensions">set extensions</a> are supported,
if the corresponding <a href="#eventMap">eventMap</a> specifies
the on and off mappings.
<br>
</li> </li>
</ul> </ul>

View File

@ -4,6 +4,7 @@ package main;
use strict; use strict;
use warnings; use warnings;
use SetExtensions;
my %codes = ( my %codes = (
"00" => "off", "00" => "off",
@ -167,7 +168,7 @@ FS20_Set($@)
my $ret = undef; my $ret = undef;
my $na = int(@a); my $na = int(@a);
return "no set value specified" if($na < 2 || $na > 3); return "no set value specified" if($na < 2);
return "Readonly value $a[1]" if(defined($readonly{$a[1]})); return "Readonly value $a[1]" if(defined($readonly{$a[1]}));
if($na > 2 && $a[1] eq "dim") { if($na > 2 && $a[1] eq "dim") {
@ -181,16 +182,14 @@ FS20_Set($@)
if(!defined($c)) { if(!defined($c)) {
# Model specific set arguments # Model specific set arguments
my $list;
if(defined($attr{$name}) && defined($attr{$name}{"model"})) { if(defined($attr{$name}) && defined($attr{$name}{"model"})) {
my $mt = $models{$attr{$name}{"model"}}; my $mt = $models{$attr{$name}{"model"}};
return "Unknown argument $a[1], choose one of " $list = "" if($mt && $mt eq "sender");
if($mt && $mt eq "sender"); $list = $fs20_simple if($mt && $mt eq "simple");
return "Unknown argument $a[1], choose one of $fs20_simple"
if($mt && $mt eq "simple");
} }
return "Unknown argument $a[1], choose one of " . $list = join(" ", sort keys %fs20_c2b) if(!defined($list));
join(" ", sort keys %fs20_c2b) . return SetExtensions($hash, $list, @a);
" dim:slider,0,6.25,100";
} }
@ -538,6 +537,8 @@ four2hex($$)
toggle # between off and previous dim val toggle # between off and previous dim val
on-till # Special, see the note on-till # Special, see the note
</pre> </pre>
The <a href="#setExtensions"> set extensions</a> are also supported.<br>
<br>
Examples: Examples:
<ul> <ul>
<code>set lamp on</code><br> <code>set lamp on</code><br>
@ -546,6 +547,7 @@ four2hex($$)
<code>set lamp on-for-timer 12</code><br> <code>set lamp on-for-timer 12</code><br>
</ul> </ul>
<br> <br>
Notes: Notes:
<ul> <ul>
<li>Use reset with care: the device forgets even the housecode. <li>Use reset with care: the device forgets even the housecode.

View File

@ -14,6 +14,7 @@ package main;
use strict; use strict;
use warnings; use warnings;
use SetExtensions;
sub ZWave_Parse($$@); sub ZWave_Parse($$@);
sub ZWave_Set($@); sub ZWave_Set($@);
@ -236,6 +237,7 @@ ZWave_Cmd($$@)
my $name = shift(@a); my $name = shift(@a);
my $cmd = shift(@a); my $cmd = shift(@a);
# Collect the commands from the distinct classes # Collect the commands from the distinct classes
my %cmdList; my %cmdList;
my $classes = AttrVal($name, "classes", ""); my $classes = AttrVal($name, "classes", "");
@ -249,14 +251,23 @@ ZWave_Cmd($$@)
} }
} }
} }
if(!$cmdList{$cmd}) { if(!$cmdList{$cmd}) {
my $list = join(" ",sort keys %cmdList); my $list = join(" ",sort keys %cmdList);
foreach my $cmd (keys %zwave_cmdArgs) { # add slider & co foreach my $cmd (keys %zwave_cmdArgs) { # add slider & co
$list =~ s/\b$cmd\b/$cmd:$zwave_cmdArgs{$cmd}/; $list =~ s/\b$cmd\b/$cmd:$zwave_cmdArgs{$cmd}/;
} }
return "Unknown $type argument $cmd, choose one of $list";
if($type eq "set") {
unshift @a, $name, $cmd;
return SetExtensions($hash, $list, @a);
} else {
return "Unknown argument $cmd, choose one of $list";
}
} }
Log GetLogLevel($name,2), "ZWave $type $name $cmd";
################################ ################################
# ZW_SEND_DATA,nodeId,CMD,ACK|AUTO_ROUTE # ZW_SEND_DATA,nodeId,CMD,ACK|AUTO_ROUTE
@ -525,8 +536,11 @@ ZWave_Undef($$)
<a name="ZWaveset"></a> <a name="ZWaveset"></a>
<b>Set</b> <b>Set</b>
<ul> <ul>
<br>
<b>Note</b>: devices with on/off functionality support the <a
href="#setExtensions"> set extensions</a>.
<br><b>Class BASIC</b> <br><br><b>Class BASIC</b>
<li>basicValue value<br> <li>basicValue value<br>
Send value (0-255) to this device. The interpretation is device dependent, Send value (0-255) to this device. The interpretation is device dependent,
e.g. for a SWITCH_BINARY device 0 is off and anything else is on.</li> e.g. for a SWITCH_BINARY device 0 is off and anything else is on.</li>
@ -571,7 +585,6 @@ ZWave_Undef($$)
<li>associationDel groupId nodeId ...<br> <li>associationDel groupId nodeId ...<br>
Remove the specified list of nodeIds from the assotion group groupId.</li> Remove the specified list of nodeIds from the assotion group groupId.</li>
</ul> </ul>
<br> <br>

152
fhem/FHEM/SetExtensions.pm Normal file
View File

@ -0,0 +1,152 @@
##############################################
# $Id: $
package main;
use strict;
use warnings;
sub SetExtensions($$@);
sub SetExtensionsFn($);
sub
SetExtensions($$@)
{
my ($hash, $list, $name, $cmd, @a) = @_;
my %se_list = (
"on-for-timer" => 1,
"off-for-timer" => 1,
"on-till" => 1,
"off-till" => 1,
"blink" => 2,
"intervals" => 0,
);
my $hasOn = ($list =~ m/\bon\b/);
my $hasOff = ($list =~ m/\bon\b/);
if(!$hasOn || !$hasOff) {
my $em = AttrVal($name, "eventMap", undef);
if($em) {
$hasOn = ($em =~ m/:on\b/) if(!$hasOn);
$hasOff = ($em =~ m/:off\b/) if(!$hasOff);
}
$cmd = ReplaceEventMap($name, $cmd, 1) if($cmd ne "?"); # Fix B0-for-timer
}
if(!$hasOn || !$hasOff) { # No extension
return "Unknown argument $cmd, choose one of $list";
}
if(!defined($se_list{$cmd})) {
# Add only "new" commands
my @mylist = grep { $list !~ m/\b$_\b/ } keys %se_list;
return "Unknown argument $cmd, choose one of $list " .
join(" ", @mylist);
}
if($se_list{$cmd} && $se_list{$cmd} != int(@a)) {
return "$cmd requires $se_list{$cmd} parameter";
}
my $cmd1 = ($cmd =~ m/on.*/ ? "on" : "off");
my $cmd2 = ($cmd =~ m/on.*/ ? "off" : "on");
my $param = $a[0];
if($cmd eq "on-for-timer" || $cmd eq "off-for-timer") {
RemoveInternalTimer("SE $name $cmd");
return "$cmd requires a number as argument" if($param !~ m/^\d*\.?\d*$/);
if($param) {
DoSet($name, $cmd1);
InternalTimer(gettimeofday()+$param,"SetExtensionsFn","SE $name $cmd",0);
}
} elsif($cmd eq "on-till" || $cmd eq "off-till") {
my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($param);
return "$cmd: $err" if($err);
my $at = $name . "_till";
CommandDelete(undef, $at) if($defs{$at});
my @lt = localtime;
my $hms_till = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
my $hms_now = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);
if($hms_now ge $hms_till) {
Log 4, "$cmd: won't switch as now ($hms_now) is later than $hms_till";
return "";
}
DoSet($name, $cmd1);
CommandDefine(undef, "$at at $hms_till set $name $cmd2");
} elsif($cmd eq "blink") {
my $p2 = $a[1];
delete($hash->{SE_BLINKPARAM});
return "$cmd requires 2 numbers as argument"
if($param !~ m/^\d+$/ || $p2 !~ m/^\d*\d?\d*$/);
if($param) {
DoSet($name, "on-for-timer", $p2);
$param--;
if($param) {
$hash->{SE_BLINKPARAM} = "$param $p2";
InternalTimer(gettimeofday()+2*$p2,"SetExtensionsFn","SE $name $cmd",0);
}
}
} elsif($cmd eq "intervals") {
my $at0 = "${name}_till";
my $at1 = "${name}_intervalFrom",
my $at2 = "${name}_intervalNext";
CommandDelete(undef, $at0) if($defs{$at0});
CommandDelete(undef, $at1) if($defs{$at1});
CommandDelete(undef, $at2) if($defs{$at2});
my $intSpec = shift(@a);
if($intSpec) {
my ($from, $till) = split("-", $intSpec);
my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($from);
return "$cmd: $err" if($err);
my @lt = localtime;
my $hms_from = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
my $hms_now = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);
if($hms_from le $hms_now) { # By slight delays at will schedule tomorrow.
SetExtensions($hash, $list, $name, "on-till", $till);
} else {
CommandDefine(undef, "$at1 at $from set $name on-till $till");
}
if(@a) {
my $rest = join(" ", @a);
my ($from, $till) = split("-", shift @a);
CommandDefine(undef, "$at2 at $from set $name intervals $rest");
}
}
}
return undef;
}
sub
SetExtensionsFn($)
{
my (undef, $name, $cmd) = split(" ", shift, 3);
return if(!defined($defs{$name}));
if($cmd eq "on-for-timer") {
DoSet($name, "off");
} elsif($cmd eq "off-for-timer") {
DoSet($name, "on");
} elsif($cmd eq "blink") {
DoSet($name, "blink", split(" ", $defs{$name}{SE_BLINKPARAM}, 2));
}
}
1;

View File

@ -782,7 +782,45 @@ A line ending with \ will be concatenated with the next one, so long lines
Each device has different set parameters, see the corresponding device Each device has different set parameters, see the corresponding device
section for details.<br> section for details.<br>
<br> <br>
<br>
<a name="setExtensions"></a>
Some modules support a common list of <b>set extensions</b>, and point in
their documentation to this section. If the module itself implements one of
the following commands, then the module-implementation takes precedence.
<ul>
<li>on-for-timer &lt;seconds&gt<br>
Issue the on command for the device, and after &lt;seconds&gt; the off
command. For issuing the off command an internal timer will be
scheduled, which is deleted upon a restart. To delete this internal
timer without restart specify 0 as argument.</li>
<li>off-for-timer &lt;seconds&gt<br>
see on-for-timer above.</li>
<li>on-till &lt;timedet&gt<br>
Issue the on command for the device, and create an at definition with
&lt;timedet&gt; (in the form HH:MM[:SS]) to set it off. This definition
is visible, and its name is deviceName+"_till". To cancel the scheduled
off, delete the at definition.</li>
<li>off-till &lt;timedet&gt<br>
see on-till above.</li>
<li>blink &lt;number&gt; &lt;blink-period&gt;<br>
set the device on for &lt;blink-period&gt; then off for
&lt;blink-period&gt; and repeat this &lt;number&gt; times.
To stop blinking specify "0 0" as argument.</li>
<li>intervals &lt;from1&gt;-&lt;till1&gt; &lt;from2&gt;-&lt;till2&gt;...
</br>
set the device on for the specified intervals, which are all timespecs
in the form HH:MM[:SS]. The intervals are space separated.</li>
</ul>
Examples:
<ul>
<code>
set switch on-for-timer 12.5<br>
set switch on-till {sunset()}<br>
set switch blink 3 1<br>
set switch intervals 08:00-12:00 13:00-18:00<br>
</code>
</ul>
</ul> </ul>

View File

@ -800,19 +800,66 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.</p>
<ul> <ul>
<code>set &lt;devspec&gt; &lt;type-specific&gt;</code> <code>set &lt;devspec&gt; &lt;type-specific&gt;</code>
<br><br> <br><br>
Der Befehl setzt Ger&auml;teparameter/sendet Signale an ein Ger&auml;t. Sie erhalten Der Befehl setzt Ger&auml;teparameter/sendet Signale an ein Ger&auml;t. Sie
eine Liste verf&uuml;gbarer Parameter wenn Sie folgendes eingeben: erhalten eine Liste verf&uuml;gbarer Parameter wenn Sie folgendes eingeben:
<ul> <ul>
<code>set &lt;name&gt; ?</code> <code>set &lt;name&gt; ?</code>
</ul> </ul>
Lesen Sie bitte den Abschnitt <a href="#devspec">Device specification</a> f&uuml;r Lesen Sie bitte den Abschnitt <a href="#devspec">Device specification</a>
Details zu f&uuml;r Details zu &lt;devspec&gt;. Der &quot;set&quot;-Befehl gibt nur bei
&lt;devspec&gt;. Der &quot;set&quot;-Befehl gibt nur bei Fehler einen Wert zur&uuml;ck.<br> Fehler einen Wert zur&uuml;ck.
<br> <br><br>
Jedes Ger&auml;t hat verschiedene Parameter die mit &quot;set&quot; gesetzt werden k&ouml;nnen. Jedes Ger&auml;t hat verschiedene Parameter die mit &quot;set&quot; gesetzt
Lesen Sie bitte den entsprechenden Abschnitt f&uuml;r das Ger&auml;t f&uuml;r Details durch.<br> werden k&ouml;nnen. Lesen Sie bitte den entsprechenden Abschnitt f&uuml;r
das Ger&auml;t f&uuml;r Details durch.
<br> <br>
<br>
<a name="setExtensions"></a>
Manche Module unterst&uuml;tzen die sog. <b>set extensions</b>, und in der
entsprechenden Dokumentation ist ein Link auf diesem Text zu finden. Falls im
Modul selber einer der unten aufgef&uuml;hrten Befehle implementiert ist, dann
wird die Modul-Implementation verwendet.
<ul>
<li>on-for-timer &lt;sekunden&gt<br>
Das Ger&auml;t wird per "on" eingeschaltet, und ein interner Zeitgeber
wird erstellt, um nach &lt;sekunden&gt; ein "off" Kommando
auszuf&uuml;hren. Um diesen Zeitgeber zu entfernen sollte man das
Kommando mit dem Argument 0 erneut aufrufen. Achtung: dieser Zeitgeber
wird bei einem restart nicht gespeichert.</li>
<li>off-for-timer &lt;sekunden&gt<br>
siehe on-for-timer.</li>
<li>on-till &lt;timedet&gt<br>
Das Ger&auml;t wird per "on" eingeschaltet, und ein at Instanz wird
definiert, um es um &lt;timedet&gt; (Format: HH:MM[:SS]) per off
auszuschalten. Diese at Instanz ist sichtbar unter dem Namen
ger&auml;teName+"_till". Um das Ausschalten zu deaktivieren
l&ouml;scht man diese at Definition. </li>
<li>off-till &lt;timedet&gt<br>
siehe on-till.</li>
<li>blink &lt;anzahl&gt; &lt;blink-periode&gt;<br>
Das Ger&auml;t wird mit "on" f&uuml;r die &lt;blink-periode&gt;
eingeschaltet, und das wird nach &lt;blink-periode&gt; wiederholt. Um
das Blinken vorzeitig zu stoppen spezifiziert man "0 0" als
Argument.</li>
<li>intervals &lt;from1&gt;-&lt;till1&gt; &lt;from2&gt;-&lt;till2&gt;...
</br>
Das Ger&auml;t wird f&uuml;r die spezifizierten Intervalle
eingeschaltet. Die einzelnen Intervalle sind Leerzeichen getrennt, und
ein Intervall besteht aus zwei Zeitspezifikationen, die mit einem "-"
getrennt sind.
</li>
</ul>
Beispiele:
<ul>
<code>
set switch on-for-timer 12.5<br>
set switch on-till {sunset()}<br>
set switch blink 3 1<br>
set switch intervals 08:00-12:00 13:00-18:00<br>
</code>
</ul>
</ul>
</ul> </ul>