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.
# 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
- change: avoid updating weather information on get (59_Weather.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->{SetFn} = "ECMD_Set";
$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";
$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
#
} elsif($cmd eq "reading") {
@ -487,6 +493,7 @@ sub ECMD_Read($)
{
my ($hash) = @_;
my $buf = ECMD_SimpleRead($hash);
return unless(defined($buf));
return if($buf eq "");
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;.
The list is automatically updated if a class definition is added. You can
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>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>
</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>
<code>get &lt;commandname&gt; cmd { <a href="#perl">&lt;perl special&gt;</a> }</code>
<br><br>

View File

@ -108,18 +108,30 @@ sub
ECMDDevice_Changed($$$)
{
my ($hash, $cmd, $value)= @_;
#Debug "Device changed: $cmd $value";
readingsBeginUpdate($hash);
my $state= $cmd;
if(defined($value) && $value ne "") {
readingsBulkUpdate($hash, $cmd, $value);
$state.= " $value";
}
readingsBulkUpdate($hash, "state", $state);
readingsBulkUpdate($hash, $cmd, $value) if(defined($value) && $value ne "");
my $state;
my $classname= $hash->{fhem}{classname};
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);
my $name= $hash->{NAME};
Log3 $hash, 4 , "ECMDDevice $name $state";
#Log3 $hash, 4 , "ECMDDevice $name $state" if(defined($state));
return $state;
}
@ -247,41 +259,52 @@ ECMDDevice_Parse($$)
# 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 $name= $IOhash->{NAME};
#Debug "Trying to find a match for \"" . escapeLogLine($msg) ."\"";
# walk over all clients
foreach my $d (keys %defs) {
my $hash= $defs{$d};
if($hash->{TYPE} eq "ECMDDevice" && $hash->{IODev} eq $IOhash) {
my $classname= $hash->{fhem}{classname};
my $classDef= $IOhash->{fhem}{classDefs}{$classname};
#Debug " Checking device $d with class $classname...";
next unless(defined($classDef->{readings}));
#Debug " Trying to find a match in class $classname...";
my %specials= ECMDDevice_DeviceParams2Specials($hash);
# we run over all readings in that classdef
foreach my $r (keys %{$classDef->{readings}}) {
my $regex= ECMDDevice_ReplaceSpecials($classDef->{readings}{$r}{match}, %specials);
#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);
}
my @msgs;
if(defined(AttrVal($name, "split", undef))) {
@msgs= split(AttrVal($name, "split", undef), $message);
} else {
push @msgs, $message;
}
foreach my $msg (@msgs) {
#Debug "Trying to find a match for \"" . escapeLogLine($msg) ."\"";
# walk over all clients
foreach my $d (keys %defs) {
my $hash= $defs{$d};
if($hash->{TYPE} eq "ECMDDevice" && $hash->{IODev} eq $IOhash) {
my $classname= $hash->{fhem}{classname};
my $classDef= $IOhash->{fhem}{classDefs}{$classname};
#Debug " Checking device $d with class $classname...";
next unless(defined($classDef->{readings}));
#Debug " Trying to find a match in class $classname...";
my %specials= ECMDDevice_DeviceParams2Specials($hash);
# we run over all readings in that classdef
foreach my $r (keys %{$classDef->{readings}}) {
my $regex= ECMDDevice_ReplaceSpecials($classDef->{readings}{$r}{match}, %specials);
#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 "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";
}