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

devspec added

delattr reenamed to deleteattr


git-svn-id: https://svn.fhem.de/fhem/trunk@135 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2007-12-29 15:57:42 +00:00
parent 88003d6b52
commit 5b6dbf91d7
6 changed files with 332 additions and 162 deletions

View File

@ -369,6 +369,8 @@
- feature: Generate warning if too many commands were sent in the last hour
- doc: linux.html: Introduction (Peter S.)
- feature: contrib/82_M232Voltage.pm (by Boris, 24.12)
- feature: delattr renamed to deleteattr (Rudi, 29.12)
- feature: device spec (list/range/regexp) for most commands implemented
- TODO
emem -2.5kW / getDevData for emwz -1

View File

@ -71,7 +71,7 @@ sr($$$$)
$sst += ($seconds/3600);
my $diff = 0;
if($nh > $sst) {
if($nh >= $sst) {
$nt += 86400; # Tommorow
$diff = 24;
@lt = localtime($nt);

View File

@ -2,7 +2,7 @@
Created the file HISTORY and the file README.DEV
- Pest, Thu Feb 1 20:45 MET 2007
Added description for attribute "model" in commandref.html
Added description for attribute ,
- Rudi, Sun Feb 11 18:56:05 MET 2007
- showtime added for pgm2 (useful for FS20 piri display)
@ -23,7 +23,7 @@
- Rudi, Sun Mar 4 11:18:10 MET 2007
Reorganization. Goal: making attribute adding/deleting more uniform
("at/notify" and other device differences), and making web-configuration
(,
possible (i.e. saving the configfile, list of possible devices etc).
Internal changes:
@ -34,24 +34,24 @@
-> User written scripts can more easily analyze device states
User visible changes:
- at/notify "renamed" to "define <name> at/notify", both moved to external
- at/notify ,
modules. Now it is possible
- to have a further "at" or "notify" modules
- to have a further ,
(notify & filelog use the same interface)
- to have more than one notify for the same event
- to delete at commands without strange escapes.
The delete syntax changed (no more def/at/ntfy needed)
- at/notify can have attributes
Drawback: each at and notify must have a name, which is strange first.
- logfile/modpath/pidfile/port/verbose "renamed" to "attr global xxx"
- logfile/modpath/pidfile/port/verbose ,
Dumping and extending these attributes is easier, no special handling
required in the web-frontend.
- savefile renamed to "attr global statefile"
- savefile renamed to ,
- configfile global attribute added.
- save command added, it writes the statefile and then the configfile.
- delattr added to delete single attributes
- list/xmllist format changed, they contain more information.
- "define/set/get/attr name ?" returns a list of possible arguments
- ,
in the same format. This data is contained in the xmllist.
- disable attribute for at/notify/filelog
- rename added
@ -92,7 +92,7 @@
- feature: modify command added. It helps change e.g. only the time component
for an at command, without deleting and creating it again and then
reapplying all the attributes.
- feature: the "-" character is disallowed in defined names. Use dot (.) or _
- feature: the ,
instead. The - is used to separate ranges in the set command.
- Rudi, Sun May 27 12:51:52 MEST 2007
@ -164,3 +164,9 @@
- Peter Sun Dec 23 19:59:00 MEST 2007
- linux.html: Introduction refinement.
- Rudi Sat Dec 29 16:27:14 MET 2007
- delattr renamed to deleteattr
- devicespec introduced:
it may contain a list of devices, a range of devices, or multiple devices
identified by regexp. Following commands take a devicespec as argument:
attr, deleteattr, delete, get, list, set, setstate, trigger

View File

@ -15,7 +15,7 @@
<a href="#attr">attr</a><br>
<a href="#defattr">defattr</a><br>
<a href="#define">define</a><br>
<a href="#delattr">delattr</a><br>
<a href="#deleteattr">deleteattr</a><br>
<a href="#delete">delete</a><br>
<a href="#get">get</a><br>
<a href="#include">include</a><br>
@ -32,6 +32,7 @@
<a href="#trigger">trigger</a><br>
<a href="#sleep">sleep</a><br>
<a href="#xmllist">xmllist</a><br>
<a href="#devspec">Device specification</a><br>
<a href="#perl">Perl specials</a><br>
<a name="intro"></a>
@ -115,7 +116,7 @@ split in multiple lines<br><br>
<a name="attr"></a>
<h3>attr</h3>
<ul>
<code>attr &lt;name&gt; &lt;attrname&gt; [&lt;value&gt;] </code><br>
<code>attr &lt;devspec&gt; &lt;attrname&gt; [&lt;value&gt;] </code><br>
or <br>
<code>attr at &lt;at-spec-regexp&gt; &lt;attribute&gt; </code><br>
@ -126,6 +127,8 @@ split in multiple lines<br><br>
below.<br>
Use "attr &lt;name&gt; ?" to get a list of possible attributes.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.
<br><br>
Following are attributes of the global device:<br>
@ -470,7 +473,7 @@ split in multiple lines<br><br>
Notes:<br>
<ul>
<li>See <a href="#delattr">delattr</a> to delete attributes.</li>
<li>See <a href="#deleteattr">deleteattr</a> to delete attributes.</li>
</ul>
</ul>
@ -1093,18 +1096,20 @@ split in multiple lines<br><br>
</ul>
<a name="delattr"></a>
<h3>delattr</h3>
<a name="deleteattr"></a>
<h3>deleteattr</h3>
<ul>
<code>delattr &lt;name&gt; [&lt;attrname&gt;]</code> <br>
<code>deleteattr &lt;devspec&gt; [&lt;attrname&gt;]</code> <br>
<br>
Delete either a single attribute (see the <a href="#attr">attr</a> command)
or all attributes for a device (if no &lt;attrname&gt; is defined).<br>
or all attributes for a device (if no &lt;attrname&gt; is defined).
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.<br>
Examples:
<ul>
<code>delattr lamp follow-on-for-timer</code><br>
<code>delattr lamp</code><br>
<code>deleteattr lamp follow-on-for-timer</code><br>
<code>deleteattr lamp</code><br>
</ul>
<br>
</ul>
@ -1112,10 +1117,11 @@ split in multiple lines<br><br>
<a name="delete"></a>
<h3>delete</h3>
<ul>
<code>delete &lt;name&gt;</code> <br>
<code>delete &lt;devspec&gt;</code> <br>
<br>
Delete something created with the <a href="#define">define</a> command.
<br>
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.<br>
Examples:
<ul>
<code>delete lamp</code><br>
@ -1126,12 +1132,13 @@ split in multiple lines<br><br>
<a name="get"></a>
<h3>get</h3>
<ul>
<code>get &lt;name&gt; &lt;type-specific&gt;</code>
<code>get &lt;devspec&gt; &lt;type-specific&gt;</code>
<br><br>
Ask a value directly from the device, and wait for an answer. In general, you
can get a list of possible commands by<br><code>get &lt;device&gt; ?</code>
<br>
Right now only the FHZ module supports this function.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.<br>
<h4>Type FHZ:</h4>
<ul>
@ -1231,11 +1238,13 @@ split in multiple lines<br><br>
<a name="list"></a>
<h3>list</h3>
<ul>
<code>list [name]</code>
<code>list [devspec]</code>
<br><br>
Output a list of all definitions, all notify settings and all at
entries. This is one of the few commands which return a string in a
normal case.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.
<br><br>
Example:
<pre><code> FHZ> list
@ -1404,13 +1413,13 @@ Send buffer:<br /> 2007-10-19 00:31:24 desired-temp 22.5
<a name="set"></a>
<h3>set</h3>
<ul>
<code>set &lt;name&gt; &lt;type-specific&gt;</code>
<code>set &lt;devspec&gt; &lt;type-specific&gt;</code>
<br><br>
Set parameters of a device / send signals to a device. You can
get a list of possible commands by<br><code>set &lt;name&gt; ?</code>
<br>
Instead of &lt;name&gt; you can also use an enumeration (separated by comma)
or ranges (separated by -), see the FS20 examples.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.<br>
<a name="FHZset"></a>
<h4>Type FHZ:</h4>
@ -1687,12 +1696,14 @@ must between 5.5 and 30.5 Celsius. Value 5.5 set the actuator to OFF, value 30.
<a name="setstate"></a>
<h3>setstate</h3>
<ul>
<code>setstate &lt;name&gt; &lt;value&gt;</code>
<code>setstate &lt;devspec&gt; &lt;value&gt;</code>
<br><br>
Set the "STATE" for <code>&lt;name&gt;</code> as shown in paranthesis in the
<a href="#list">list</a> command
to <code>&lt;value&gt;</code> without sending any signals to the device
itself. This command is also used in the <a href="#statefile">statefile</a>.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.
<br><br>
Examples:
<ul>
@ -1726,9 +1737,12 @@ must between 5.5 and 30.5 Celsius. Value 5.5 set the actuator to OFF, value 30.
<a name="trigger"></a>
<h3>trigger</h3>
<ul>
<code>trigger &lt;dev&gt; &lt;state&gt;</code>
<code>trigger &lt;devspec&gt; &lt;state&gt;</code>
<br><br>
Trigger a <a href="#notify">notify</a> definition.
See the <a href="#devspec">Device specification</a> section for details on
&lt;devspec&gt;.
<br><br>
Example:
<ul>
@ -1777,6 +1791,45 @@ must between 5.5 and 30.5 Celsius. Value 5.5 set the actuator to OFF, value 30.
</ul>
<a name="devspec"></a>
<h3>Device specification</h3>
<ul>
The commands
<a href="#attr">attr</a>,
<a href="#deleteattr">deleteattr</a>,
<a href="#delete">delete</a>,
<a href="#get">get</a>,
<a href="#list">list</a>,
<a href="#set">set</a>,
<a href="#setstate">setstate</a>,
<a href="#trigger">trigger</a>
can take a more complex device specification as argument,
which will be expanded to a list of devices. A devspec can be:
<ul>
<li>a list of devices, separated by comma (,)</li>
<li>a range of devices, separated by dash (-)</li>
<li>a regular expression, if the the spec contains on e of the following
characters: ^*[]$</li>
</ul>
Example:
<ul>
<code>set lamp1,lamp2,lamp3 on</code><br>
<code>set lamp[1-3] on</code><br>
<code>set lamp.* on</code><br>
<code>set lamp1-lamp3 on</code><br>
<code>set lamp1-lamp3,lamp3 on</code><br>
</ul>
Notes:
<ul>
<li>first the spec is separated by komma, then the range or the regular
expression operations are executed.</li>
<li>if there is a device which xactly corresponds to the spec, then
no special processing is done.</li>
<li>the returned list can contain the same device more than once, so
int tha last example the list will contain lamp3 twice.</li>
</ul>
</ul>
<a name="perl"></a>
<h3>Perl specials</h3>
<ul>

View File

@ -93,7 +93,7 @@ define roll_eg_wz1 FS20 fb02 0c fg f2 lm 8f
define roll_wz1_off1 at *20:00:00 { if( $value{roll_eg_wz1} ne "off" ) { \
if( $attr{roll_eg_wz1}{freigabe} ) { \
fhem("set roll_eg_wz1 off");; \
fhem("delattr roll_eg_wz1 freigabe") \
fhem("deleteattr roll_eg_wz1 freigabe") \
} else { \
fhem("attr roll_eg_wz1 freigabe") \
} \
@ -102,11 +102,11 @@ define roll_wz1_off1 at *20:00:00 { if( $value{roll_eg_wz1} ne "of
define roll_wz1_off2 at +*{sunset_rel(+3600)} { if( $value{roll_eg_wz1} ne "off" ) { \
if( $attr{roll_eg_wz1}{freigabe} ) { \
fhem("set roll_eg_wz1 off");; \
fhem("delattr roll_eg_wz1 freigabe") \
fhem("deleteattr roll_eg_wz1 freigabe") \
} else { \
fhem("attr roll_eg_wz1 freigabe") \
} \
} }
define roll_wz1_off3 at *22:00:00 { fhem("set roll_eg_wz1 off") if($value{roll_eg_wz1} ne "off");; \
fhem("delattr roll_eg_wz1 freigabe") }
fhem("deleteattr roll_eg_wz1 freigabe") }

View File

@ -64,11 +64,12 @@ sub fhem($);
sub fhz($);
sub doGlobalDef($);
sub PrintHash($$);
sub devspec2array($);
sub CommandAttr($$);
sub CommandDefAttr($$);
sub CommandDefine($$);
sub CommandDelAttr($$);
sub CommandDeleteAttr($$);
sub CommandDelete($$);
sub CommandGet($$);
sub CommandHelp($$);
@ -137,7 +138,7 @@ my %intAt; # Internal at timer hash.
my $intAtCnt=0;
my $reread_active = 0;
my $AttrList = "room comment";
my $cvsid = '$Id: fhem.pl,v 1.32 2007-12-13 15:26:27 rudolfkoenig Exp $';
my $cvsid = '$Id: fhem.pl,v 1.33 2007-12-29 15:57:42 rudolfkoenig Exp $';
$init_done = 0;
@ -152,17 +153,17 @@ my %cmds = (
"?" => { Fn=>"CommandHelp",
Hlp=>",get this help" },
"attr" => { Fn=>"CommandAttr",
Hlp=>"<name> <attrname> [<attrvalue>],set attributes for <name>" },
Hlp=>"<devspec> <attrname> [<attrval>],set attribute for <devspec>" },
"defattr" => { Fn=>"CommandDefAttr",
Hlp=>"<attrname> <attrvalue>,set attr for following definitions" },
"define" => { Fn=>"CommandDefine",
Hlp=>"<name> <type> <options>,define a device/at/notify entity" },
"delattr" => { Fn=>"CommandDelAttr",
Hlp=>"<name> [<attrname>],delete attribute <attrname> for <name>" },
"deleteattr" => { Fn=>"CommandDeleteAttr",
Hlp=>"<devspec> [<attrname>],delete attribute for <devspec>" },
"delete" => { Fn=>"CommandDelete",
Hlp=>"name,delete the corresponding definition"},
Hlp=>"<devspec>,delete the corresponding definition(s)"},
"get" => { Fn=>"CommandGet",
Hlp=>"<name> <type dependent>,request data from <name>" },
Hlp=>"<devspec> <type dependent>,request data from <devspec>" },
"help" => { Fn=>"CommandHelp",
Hlp=>",get this help" },
"include" => { Fn=>"CommandInclude",
@ -170,7 +171,7 @@ my %cmds = (
"inform" => { Fn=>"CommandInform",
Hlp=>"{on|off},echo all commands and events to this client" },
"list" => { Fn=>"CommandList",
Hlp=>"[device],list definitions and status info" },
Hlp=>"[devspec],list definitions and status info" },
"modify" => { Fn=>"CommandModify",
Hlp=>"device <options>,modify the definition (e.g. at, notify)" },
"quit" => { Fn=>"CommandQuit",
@ -184,15 +185,15 @@ my %cmds = (
"save" => { Fn=>"CommandSave",
Hlp=>"[configfile],write the configfile and the statefile" },
"set" => { Fn=>"CommandSet",
Hlp=>"<name> <type dependent>,transmit code for <name>" },
Hlp=>"<devspec> <type dependent>,transmit code for <devspec>" },
"setstate"=> { Fn=>"CommandSetstate",
Hlp=>"<name> <state>,set the state shown in the command list" },
Hlp=>"<devspec> <state>,set the state shown in the command list" },
"shutdown"=> { Fn=>"CommandShutdown",
Hlp=>",terminate the server" },
"sleep" => { Fn=>"CommandSleep",
Hlp=>"<sec>,sleep for sec, 3 decimal places are interpreted" },
"trigger" => { Fn=>"CommandTrigger",
Hlp=>"<dev> <state>,trigger notify command" },
Hlp=>"<devspec> <state>,trigger notify command" },
"xmllist" => { Fn=>"CommandXmlList",
Hlp=>",list definitions and status info as xml" },
);
@ -533,6 +534,38 @@ AnalyzeCommand($$)
}
}
#####################################
my $namedef =
"where <name> is either:\n" .
"- a single device name\n" .
"- a list seperated by komma (,)\n" .
"- a regexp, if contains one of the following characters: *[]^\$\n" .
"- a range seperated by dash (-)\n";
sub
devspec2array($)
{
my ($name) = @_;
return $name if(defined($defs{$name}));
my @ret;
foreach my $l (split(",", $name)) { # List
if($l =~ m/[*\[\]^\$]/) { # Regexp
push @ret, grep($_ =~ m/$l/, sort keys %defs);
next;
}
if($l =~ m/-/) { # Range
my ($lower, $upper) = split("-", $l, 2);
push @ret, grep($_ ge $lower && $_ le $upper, sort keys %defs);
next;
}
push @ret, $l;
}
return $name if(!@ret); # No match, return the input
return @ret;
}
#####################################
sub
CommandHelp($$)
@ -782,7 +815,6 @@ CommandShutdown($$)
exit(0);
}
#####################################
sub
DoSet(@)
@ -798,6 +830,7 @@ DoSet(@)
return DoTrigger($dev, join(" ", @a));
}
#####################################
sub
CommandSet($$)
@ -805,32 +838,10 @@ CommandSet($$)
my ($cl, $param) = @_;
my @a = split("[ \t][ \t]*", $param);
return "Usage: set <name> <type-dependent-options>\n" .
" <name> can be an enumeration (separated by comma)\n" .
" or a range (separated by -)" if(int(@a)<1);
"$namedef" if(int(@a)<1);
my $dev = $a[0];
my @rets;
foreach my $sdev (split(",", $dev)) {
if($sdev =~ m/-/) { # Range (separated by -)
if(defined($defs{$sdev})) {
$a[0] = $sdev;
my $ret = DoSet(@a);
push @rets, $ret if($ret);
next;
}
my @lim = split("-", $sdev);
foreach my $sd (sort keys %defs) {
next if($sd lt $lim[0] || $sd gt $lim[1]);
$a[0] = $sd;
my $ret = DoSet(@a);
push @rets, $ret if($ret);
}
next;
}
foreach my $sdev (devspec2array($a[0])) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
@ -853,12 +864,26 @@ CommandGet($$)
my ($cl, $param) = @_;
my @a = split("[ \t][ \t]*", $param);
return "Usage: get <name> <type-dependent-options>" if(int(@a) < 1);
my $dev = $a[0];
return "Please define $dev first ($param)" if(!defined($defs{$dev}));
return "No get implemented for $dev" if(!$modules{$defs{$dev}{TYPE}}{GetFn});
return "Usage: get <name> <type-dependent-options>\n" .
"$namedef" if(int(@a) < 1);
return CallFn($a[0], "GetFn", $defs{$dev}, @a);
my @rets;
foreach my $sdev (devspec2array($a[0])) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
if(!$modules{$defs{$sdev}{TYPE}}{GetFn}) {
push @rets, "No get implemented for $sdev";
next;
}
$a[0] = $sdev;
my $ret = CallFn($sdev, "GetFn", $defs{$sdev}, @a);
push @rets, $ret if($ret);
}
return join("\n", @rets);
}
#####################################
@ -985,38 +1010,65 @@ CommandDelete($$)
{
my ($cl, $def) = @_;
return "Please define $def first" if(!defined($defs{$def}));
my $ret = CallFn($def, "UndefFn", $defs{$def}, $def);
return $ret if($ret);
return "Usage: delete <name>\n" .
"$namedef" if(!$def);
delete($attr{$def});
delete($defs{$def});
my @rets;
foreach my $sdev (devspec2array($def)) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
return undef;
my $ret = CallFn($sdev, "UndefFn", $defs{$sdev}, $sdev);
if($ret) {
push @rets, $ret;
next;
}
delete($attr{$sdev});
delete($defs{$sdev});
}
return join("\n", @rets);
}
#############
sub
CommandDelAttr($$)
CommandDeleteAttr($$)
{
my ($cl, $def) = @_;
my @a = split(" ", $def, 2);
return "Usage: delattr <name> [<attrname>]" if(@a < 1);
return "Cannot delete global parameters" if($a[0] eq "global");
return "No definition found for $a[0]\n" if(!$defs{$a[0]});
return "Usage: deleteattr <name> [<attrname>]\n" .
"$namedef" if(@a < 1);
$ret = CallFn($a[0], "AttrFn", "del", @a);
return $ret if($ret);
my @rets;
foreach my $sdev (devspec2array($a[0])) {
if($sdev eq "global") {
push @rets, "Cannot delete global parameters";
next;
}
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
$a[0] = $sdev;
$ret = CallFn($sdev, "AttrFn", "del", @a);
if($ret) {
push @rets, $ret;
next;
}
if(@a == 1) {
delete($attr{$sdev});
} else {
delete($attr{$sdev}{$a[1]}) if(defined($attr{$sdev}));
}
if(@a == 1) {
delete($attr{$a[0]});
return undef;
}
return "Attribute not defined"
if(!defined($attr{$a[0]}) || !defined($attr{$a[0]}{$a[1]}));
delete($attr{$a[0]}{$a[1]});
return undef;
return join("\n", @rets);
}
sub
@ -1071,11 +1123,15 @@ CommandList($$)
} else {
return "No device named $param found" if(!defined($defs{$param}));
my $d = $defs{$param};
foreach my $sdev (devspec2array($param)) {
if(!defined($defs{$sdev})) {
$str .= "No device named $param found";
next;
}
$str .= "Internals:\n";
$str .= PrintHash($defs{$sdev}, 2);
}
$str .= "Internals:\n";
$str .= PrintHash($d, 2);
}
return $str;
@ -1224,40 +1280,15 @@ getAllAttr($)
return $list;
}
#####################################
sub
CommandAttr($$)
GlobalAttr($$)
{
my ($cl, $param) = @_;
my $ret = undef;
my @a = split(" ", $param, 3);
return "Usage: attr <name> <attrname> [<attrvalue>]" if(@a < 2);
return "Please define $a[0] first: no definition found"
if(!defined($defs{$a[0]}));
my $list = getAllAttr($a[0]);
return "Unknown argument $a[1], choose one of $list" if($a[1] eq "?");
return "Unknown attribute $a[1], use attr global userattr ($list)"
if(" $list " !~ m/ ${a[1]}[ :;]/);
$ret = CallFn($a[0], "AttrFn", "set", @a);
return $ret if($ret);
if(defined($a[2])) {
$attr{$a[0]}{$a[1]} = $a[2];
} else {
$attr{$a[0]}{$a[1]} = "1";
}
return if($a[0] ne "global"); # Global specials ahead
my ($name, $val) = @_;
################
if($a[1] eq "logfile") {
if($name eq "logfile") {
my @t = localtime;
my $ret = OpenLogfile(ResolveDateWildcards($a[2], @t));
my $ret = OpenLogfile(ResolveDateWildcards($val, @t));
if($ret) {
return $ret if($init_done);
die($ret);
@ -1265,10 +1296,10 @@ CommandAttr($$)
}
################
elsif($a[1] eq "port") {
elsif($name eq "port") {
return undef if($reread_active);
my ($port, $global) = split(" ", $a[2]);
my ($port, $global) = split(" ", $val);
if($global && $global ne "global") {
return "Bad syntax, usage: attr global port <portnumber> [global]";
}
@ -1289,8 +1320,8 @@ CommandAttr($$)
}
################
elsif($a[1] eq "verbose") {
if($a[2] =~ m/^[0-5]$/) {
elsif($name eq "verbose") {
if($val =~ m/^[0-5]$/) {
return undef;
} else {
$attr{global}{verbose} = 3;
@ -1298,10 +1329,10 @@ CommandAttr($$)
}
}
elsif($a[1] eq "modpath") {
elsif($name eq "modpath") {
return "modpath must point to a directory where the FHEM subdir is"
if(! -d "$a[2]/FHEM");
my $modpath = "$a[2]/FHEM";
if(! -d "$val/FHEM");
my $modpath = "$val/FHEM";
opendir(DH, $modpath) || return "Can't read $modpath: $!";
my $counter = 0;
@ -1327,12 +1358,67 @@ CommandAttr($$)
"point modpath to a directory where the FHEM subdir is";
}
$modpath_set = $a[2];
$modpath_set = $val;
}
return undef;
}
#####################################
sub
CommandAttr($$)
{
my ($cl, $param) = @_;
my $ret = undef;
my @a = split(" ", $param, 3);
return "Usage: attr <name> <attrname> [<attrvalue>]\n" .
"$namedef" if(@a < 2);
my @rets;
foreach my $sdev (devspec2array($a[0])) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
my $list = getAllAttr($sdev);
if($a[1] eq "?") {
push @rets, "Unknown argument $a[1], choose one of $list";
next;
}
if(" $list " !~ m/ ${a[1]}[ :;]/) {
push @rets, "Unknown attribute $a[1], use attr global userattr ($list)";
next;
}
$a[0] = $sdev;
$ret = CallFn($sdev, "AttrFn", "set", @a);
if($ret) {
push @rets, $ret;
next;
}
if(defined($a[2])) {
$attr{$sdev}{$a[1]} = $a[2];
} else {
$attr{$sdev}{$a[1]} = "1";
}
if($sdev eq "global") {
$ret = GlobalAttr($a[1], $a[2]);
if($ret) {
push @rets, $ret;
next;
}
}
}
return join("\n", @rets);
}
#####################################
# Default Attr
@ -1357,42 +1443,52 @@ sub
CommandSetstate($$)
{
my ($cl, $param) = @_;
my $ret = undef;
my @a = split(" ", $param, 2);
return "Usage: setstate <name> <state>" if(@a != 2);
return "Please define $a[0] first" if(!defined($defs{$a[0]}));
return "Usage: setstate <name> <state>\n" .
"$namedef" if(@a != 2);
my $d = $defs{$a[0]};
# Detailed state with timestamp
if($a[1] =~ m/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} /) {
my @b = split(" ", $a[1], 4);
if($defs{$a[0]}{TYPE} eq "FS20" && $b[2] ne "state") { # Compatibility mode
$b[3] = $b[2] . ($b[3] ? " $b[3]" : "");
$b[2] = "state";
my @rets;
foreach my $sdev (devspec2array($a[0])) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
my $tim = "$b[0] $b[1]";
$ret = CallFn($a[0], "StateFn", $d, $tim, $b[2], $b[3]);
return $ret if($ret);
my $d = $defs{$sdev};
if(!$d->{READINGS}{$b[2]} || $d->{READINGS}{$b[2]}{TIME} lt $tim) {
$d->{READINGS}{$b[2]}{VAL} = $b[3];
$d->{READINGS}{$b[2]}{TIME} = $tim;
# Detailed state with timestamp
if($a[1] =~ m/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} /) {
my @b = split(" ", $a[1], 4);
if($defs{$sdev}{TYPE} eq "FS20" && $b[2] ne "state") { # Compatibility
$b[3] = $b[2] . ($b[3] ? " $b[3]" : "");
$b[2] = "state";
}
my $tim = "$b[0] $b[1]";
my $ret = CallFn($sdev, "StateFn", $d, $tim, $b[2], $b[3]);
if($ret) {
push @rets, $ret;
next;
}
if(!$d->{READINGS}{$b[2]} || $d->{READINGS}{$b[2]}{TIME} lt $tim) {
$d->{READINGS}{$b[2]}{VAL} = $b[3];
$d->{READINGS}{$b[2]}{TIME} = $tim;
}
} else {
$d->{STATE} = $a[1];
$oldvalue{$sdev}{VAL} = $a[1];
# This time is not the correct one, but we do not store a timestamp for
# this reading.
$oldvalue{$sdev}{TIME} = TimeNow();
}
} else {
$d->{STATE} = $a[1];
$oldvalue{$a[0]}{VAL} = $a[1];
# This time is not the correct one, but we do not store a timestamp for
# this reading.
$oldvalue{$a[0]}{TIME} = TimeNow();
}
return $ret;
return join("\n", @rets);
}
#####################################
@ -1402,9 +1498,22 @@ CommandTrigger($$)
my ($cl, $param) = @_;
my ($dev, $state) = split(" ", $param, 2);
return "Usage: trigger <device> <state>" if(!$state);
return "Please define $dev first" if(!defined($defs{$dev}));
return DoTrigger($dev, $state);
return "Usage: trigger <name> <state>\n" .
"$namedef" if(!$state);
my @rets;
foreach my $sdev (devspec2array($dev)) {
if(!defined($defs{$sdev})) {
push @rets, "Please define $sdev first";
next;
}
my $ret = DoTrigger($sdev, $state);
if($ret) {
push @rets, $ret;
next;
}
}
return join("\n", @rets);
}
#####################################