2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-05-04 20:17:45 +00:00

state definition and split attribute added to 66_ECMD, 67_ECMDDevice

git-svn-id: https://svn.fhem.de/fhem/trunk@6456 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
borisneubert 2014-08-24 21:00:55 +00:00
parent 7d0deb744d
commit 88252a74a5
3 changed files with 82 additions and 37 deletions

View File

@ -1,5 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: state definition and split attribute added to 66_ECMD,
67_ECMDDevice
- FHEMWEB: JavaScripts and CssFiles attributes added - FHEMWEB: JavaScripts and CssFiles attributes added
- change: avoid updating weather information on get (59_Weather.pm) - change: avoid updating weather information on get (59_Weather.pm)
- change: removed noshutdown=0 for HTTP connections made in 57_Calendar.pm - change: removed noshutdown=0 for HTTP connections made in 57_Calendar.pm

View File

@ -64,7 +64,7 @@ ECMD_Initialize($)
$hash->{GetFn} = "ECMD_Get"; $hash->{GetFn} = "ECMD_Get";
$hash->{SetFn} = "ECMD_Set"; $hash->{SetFn} = "ECMD_Set";
$hash->{AttrFn} = "ECMD_Attr"; $hash->{AttrFn} = "ECMD_Attr";
$hash->{AttrList}= "classdefs logTraffic:0,1,2,3,4,5 timeout"; $hash->{AttrList}= "classdefs split logTraffic:0,1,2,3,4,5 timeout";
} }
##################################### #####################################
@ -316,6 +316,12 @@ ECMD_EvalClassDef($$$)
Log3 $hash, 5, "$name: parameters are $def"; Log3 $hash, 5, "$name: parameters are $def";
$hash->{fhem}{classDefs}{$classname}{params}= $def; $hash->{fhem}{classDefs}{$classname}{params}= $def;
# #
# state
#
} elsif($cmd eq "state") {
Log3 $hash, 5, "$name: state is determined as $def";
$hash->{fhem}{classDefs}{$classname}{state}= $def;
#
# reading # reading
# #
} elsif($cmd eq "reading") { } elsif($cmd eq "reading") {
@ -487,6 +493,7 @@ sub ECMD_Read($)
{ {
my ($hash) = @_; my ($hash) = @_;
my $buf = ECMD_SimpleRead($hash); my $buf = ECMD_SimpleRead($hash);
return unless(defined($buf));
return if($buf eq ""); return if($buf eq "");
ECMD_Log $hash, 5, "Spontaneously received " . dq($buf); ECMD_Log $hash, 5, "Spontaneously received " . dq($buf);
@ -631,6 +638,13 @@ ECMD_Write($$$)
<li>classdefs<br>A colon-separated list of &lt;classname&gt;=&lt;filename&gt;. <li>classdefs<br>A colon-separated list of &lt;classname&gt;=&lt;filename&gt;.
The list is automatically updated if a class definition is added. You can The list is automatically updated if a class definition is added. You can
directly set the attribute.</li> directly set the attribute.</li>
<li>split<br>
Some devices send several readings in one transmission. The split attribute defines the
separator to split such transmissions into separate messages. The regular expression for
matching a reading is then applied to each message in turn. After splitting, the separator
is <b>not</b> part of the single messages.
Example: <code>attr myECMD \n</code> splits <code>foo 12\nbar off</code> into
<code>foo 12</code> and <code>bar off</code>.</li>
<li>logTraffic &lt;loglevel&gt;<br>Enables logging of sent and received datagrams with the given loglevel. Control characters in the logged datagrams are escaped, i.e. a double backslash is shown for a single backslash, \n is shown for a line feed character, etc.</li> <li>logTraffic &lt;loglevel&gt;<br>Enables logging of sent and received datagrams with the given loglevel. Control characters in the logged datagrams are escaped, i.e. a double backslash is shown for a single backslash, \n is shown for a line feed character, etc.</li>
<li>timeout &lt;seconds&gt;<br>Time in seconds to wait for a reply from the physical ECMD device before FHEM assumes that something has gone wrong. The default is 3 seconds if this attribute is not set.</li> <li>timeout &lt;seconds&gt;<br>Time in seconds to wait for a reply from the physical ECMD device before FHEM assumes that something has gone wrong. The default is 3 seconds if this attribute is not set.</li>
<!-- <!--
@ -681,6 +695,12 @@ ECMD_Write($$$)
<br><br> <br><br>
</li> </li>
<li><code>state &lt;reading&gt;</code><br><br>
Normally, the state reading is set to the latest command or reading name followed
by the value, if any. This command sets the state reading to the value of the
named reading if and only if the reading is updated.<br><br>
</li>
<li><code>set &lt;commandname&gt; cmd { <a href="#perl">&lt;perl special&gt;</a> }</code><br> <li><code>set &lt;commandname&gt; cmd { <a href="#perl">&lt;perl special&gt;</a> }</code><br>
<code>get &lt;commandname&gt; cmd { <a href="#perl">&lt;perl special&gt;</a> }</code> <code>get &lt;commandname&gt; cmd { <a href="#perl">&lt;perl special&gt;</a> }</code>
<br><br> <br><br>

View File

@ -108,18 +108,30 @@ sub
ECMDDevice_Changed($$$) ECMDDevice_Changed($$$)
{ {
my ($hash, $cmd, $value)= @_; my ($hash, $cmd, $value)= @_;
#Debug "Device changed: $cmd $value";
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
my $state= $cmd;
if(defined($value) && $value ne "") { readingsBulkUpdate($hash, $cmd, $value) if(defined($value) && $value ne "");
readingsBulkUpdate($hash, $cmd, $value);
$state.= " $value"; my $state;
} my $classname= $hash->{fhem}{classname};
readingsBulkUpdate($hash, "state", $state); my $IOhash= $hash->{IODev};
if(defined($IOhash->{fhem}{classDefs}{$classname}{state})) {
if($cmd eq $IOhash->{fhem}{classDefs}{$classname}{state}) {
$state= defined($value) ? $value : "?";
#Debug "cmd= $cmd, setting state to $state (OVERRIDE)";
}
} else {
$state= $cmd;
$state.= " $value" if(defined($value) && $value ne "");
#Debug "cmd= $cmd, setting state to $state (DEFAULT)";
}
readingsBulkUpdate($hash, "state", $state) if(defined($state));
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
my $name= $hash->{NAME}; my $name= $hash->{NAME};
Log3 $hash, 4 , "ECMDDevice $name $state"; #Log3 $hash, 4 , "ECMDDevice $name $state" if(defined($state));
return $state; return $state;
} }
@ -247,41 +259,52 @@ ECMDDevice_Parse($$)
# NOTE: we will update all matching readings for all devices, not just the first! # NOTE: we will update all matching readings for all devices, not just the first!
my ($IOhash, $msg) = @_; # IOhash points to the ECMD, not to the ECMDDevice my ($IOhash, $message) = @_; # IOhash points to the ECMD, not to the ECMDDevice
my @matches; my @matches;
my $name= $IOhash->{NAME}; my $name= $IOhash->{NAME};
#Debug "Trying to find a match for \"" . escapeLogLine($msg) ."\""; my @msgs;
# walk over all clients if(defined(AttrVal($name, "split", undef))) {
foreach my $d (keys %defs) { @msgs= split(AttrVal($name, "split", undef), $message);
my $hash= $defs{$d}; } else {
if($hash->{TYPE} eq "ECMDDevice" && $hash->{IODev} eq $IOhash) { push @msgs, $message;
my $classname= $hash->{fhem}{classname}; }
my $classDef= $IOhash->{fhem}{classDefs}{$classname};
#Debug " Checking device $d with class $classname..."; foreach my $msg (@msgs) {
next unless(defined($classDef->{readings})); #Debug "Trying to find a match for \"" . escapeLogLine($msg) ."\"";
#Debug " Trying to find a match in class $classname..."; # walk over all clients
my %specials= ECMDDevice_DeviceParams2Specials($hash); foreach my $d (keys %defs) {
# we run over all readings in that classdef my $hash= $defs{$d};
foreach my $r (keys %{$classDef->{readings}}) { if($hash->{TYPE} eq "ECMDDevice" && $hash->{IODev} eq $IOhash) {
my $regex= ECMDDevice_ReplaceSpecials($classDef->{readings}{$r}{match}, %specials); my $classname= $hash->{fhem}{classname};
#Debug " Trying to match reading $r with regular expressing \"$regex\"."; my $classDef= $IOhash->{fhem}{classDefs}{$classname};
if($msg =~ m/$regex/) { #Debug " Checking device $d with class $classname...";
# we found a match next unless(defined($classDef->{readings}));
Log3 $IOhash, 5, "$name: match regex $regex for reading $r of device $d with class $classname"; #Debug " Trying to find a match in class $classname...";
push @matches, $d; my %specials= ECMDDevice_DeviceParams2Specials($hash);
my $postproc= $classDef->{readings}{$r}{postproc}; # we run over all readings in that classdef
my $value= ECMDDevice_PostProc($hash, $postproc, $msg); foreach my $r (keys %{$classDef->{readings}}) {
Log3 $hash, 5, "postprocessed value is $value"; my $regex= ECMDDevice_ReplaceSpecials($classDef->{readings}{$r}{match}, %specials);
ECMDDevice_Changed($hash, $r, $value); #Debug " Trying to match reading $r with regular expressing \"$regex\".";
} if($msg =~ m/$regex/) {
} # we found a match
} Log3 $IOhash, 5, "$name: match regex $regex for reading $r of device $d with class $classname";
push @matches, $d;
my $postproc= $classDef->{readings}{$r}{postproc};
my $value= ECMDDevice_PostProc($hash, $postproc, $msg);
Log3 $hash, 5, "postprocessed value is $value";
ECMDDevice_Changed($hash, $r, $value);
}
}
}
}
} }
return @matches if(@matches); return @matches if(@matches);
return "UNDEFINED ECMDDevice message $msg"; # NOTE: In a split message, undefined messages are not reported if there was at least one match.
return "UNDEFINED ECMDDevice message $message";
} }