2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

37_SHC: now add all files for the previous commit (rr2000)

git-svn-id: https://svn.fhem.de/fhem/trunk@8182 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rr2000 2015-03-09 19:03:15 +00:00
parent 8443d9b4bb
commit b7f5a515d2
6 changed files with 405 additions and 130 deletions

View File

@ -1,5 +1,6 @@
# 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.
- changed: 37_SHC: now add all files for the previous commit (rr2000)
- feature: 37_SHC: add new support for SoilMoistureMeter and add
support for DigPort and DigPin in Powerswitch (rr2000)
- feature: 02_HTTPSRV: query string sets readings (Stefan Strobel)

View File

@ -2,6 +2,7 @@
# This file is part of the smarthomatic module for FHEM.
#
# Copyright (c) 2014 Stefan Baumann
# 2015 Uwe Freese
#
# You can find smarthomatic at www.smarthomatic.org.
# You can find FHEM at www.fhem.de.
@ -26,6 +27,7 @@ package main;
use strict;
use warnings;
use Time::HiRes qw(gettimeofday);
use Digest::CRC qw(crc32); # linux packet libdigest-crc-perl
sub SHC_Parse($$$$);
sub SHC_Read($);
@ -37,7 +39,7 @@ sub SHC_SimpleWrite(@);
my $clientsSHC = ":SHCdev:BASE:xxx:";
my %matchListSHC = (
"1:SHCdev" => "^Packet Data: SenderID=[1-9]|0[1-9]|[1-9][0-9]|[0-9][0-9][0-9]|[0-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-6]", #1-4096 with leading zeros
"1:SHCdev" => "^PKT:SID=([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-6]);", #1-4096
"2:xxx" => "^\\S+\\s+22",
"3:xxx" => "^\\S+\\s+11",
"4:xxx" => "^\\S+\\s+9 ",
@ -269,11 +271,15 @@ sub SHC_Parse($$$$)
next if (!$dmsg || length($dmsg) < 1); # Bogus messages
if ($dmsg !~ m/^Packet Data: SenderID=/) {
if ($dmsg =~ m/^PKT:SID=0;/) { # "echo" from message sent by FHEM itself
return;
}
if ($dmsg !~ m/^PKT:SID=/) {
# Messages just to dipose
if ( $dmsg =~ m/^\*\*\* Enter AES key nr/
|| $dmsg =~ m/^\*\*\* Received character/)
if ( $dmsg =~ m/^\*\*\* Enter data/
|| $dmsg =~ m/^\*\*\* 0x/)
{
return;
}
@ -294,17 +300,34 @@ sub SHC_Parse($$$$)
# -Verbosity level 4
if ( $dmsg =~ m/^Request added to queue/
|| $dmsg =~ m/^Request Buffer/
|| $dmsg =~ m/^Request (q|Q)ueue/)
|| $dmsg =~ m/^Request Queue/)
{
Log3 $name, 4, "$name: $dmsg";
return;
}
# -Verbosity level 1
if ( $dmsg =~ m/^CRC Error/ )
{
Log3 $name, 1, "$name: $dmsg";
return;
}
# Anything else in verbosity level 3
Log3 $name, 3, "$name: $dmsg";
return;
}
# check CRC of "PKT:..." message and ignore message if necessary
my $crc = crc32(substr($dmsg, 4, length($dmsg) - 12));
$crc = sprintf("%08x", $crc);
if ($crc ne substr($dmsg, length($dmsg) - 8))
{
Log3 $name, 1, "$name: CRC Error (" . $crc . ") $dmsg";
return;
}
$hash->{"${name}_MSGCNT"}++;
$hash->{"${name}_TIME"} = TimeNow();
$hash->{RAWMSG} = $rmsg;

View File

@ -1,7 +1,8 @@
##########################################################################
# This file is part of the smarthomatic module for FHEM.
#
# Copyright (c) 2014 Stefan Baumann, Uwe Freese
# Copyright (c) 2014 Stefan Baumann
# 2014..2015 Uwe Freese
#
# You can find smarthomatic at www.smarthomatic.org.
# You can find FHEM at www.fhem.de.
@ -33,37 +34,41 @@ use SHC_parser;
my $parser = new SHC_parser();
my %dev_state_icons = (
"PowerSwitch" => "on:on:toggle off:off:toggle set.*:light_question:off",
"Dimmer" => "on:on off:off set.*:light_question:off",
"EnvSensor" => undef,
"RGB_Dimmer" => undef
"PowerSwitch" => ".*1\\d{7}:on:off .*0\\d{7}:off:on set.*:light_question:off",
"Dimmer" => "on:on off:off set.*:light_question:off",
"EnvSensor" => undef,
"RGBDimmer" => undef,
"SoilMoistureMeter" => ".*H:\\s\\d\\..*:ampel_rot"
);
my %web_cmds = (
"PowerSwitch" => "on:off:toggle:statusRequest",
"Dimmer" => "on:off:statusRequest",
"EnvSensor" => undef,
"RGB_Dimmer" => undef
"PowerSwitch" => "on:off:toggle:statusRequest",
"Dimmer" => "on:off:statusRequest",
"EnvSensor" => undef,
"RGBDimmer" => undef,
"SoilMoistureMeter" => undef
);
# Array format: [ reading1, str_format1, reading2, str_format2 ... ]
# "on" reading translates 0 -> "off"
# 1 -> "on"
my %dev_state_format = (
"PowerSwitch" => ["on", ""],
"Dimmer" => ["on", "", "brightness", "B: "],
"EnvSensor" => [ # Results in "T: 23.4 H: 27.3 Baro: 978.34 B: 45"
"PowerSwitch" => ["port", "Port: "],
"Dimmer" => ["on", "", "brightness", "B: "],
"EnvSensor" => [ # Results in "T: 23.4 H: 27.3 Baro: 978.34 B: 45"
"temperature", "T: ",
"humidity", "H: ",
"barometric_pressure", "Baro: ",
"brightness", "B: ",
"distance", "D: ",
"dins", "Din: ",
"port", "Port: ",
"ains", "Ain: "
],
"RGB_Dimmer" => [
"color", "Color: "
]
"RGBDimmer" => [
"color", "Color: ",
"brightness", "Brightness: "
],
"SoilMoistureMeter" => ["humidity", "H: "]
);
# Supported set commands
@ -71,19 +76,23 @@ my %dev_state_format = (
# use "cmd_name:cmd_additional_info"
# cmd_additional_info: Description available at http://www.fhemwiki.de/wiki/DevelopmentModuleIntro#X_Set
my %sets = (
"PowerSwitch" => "on:noArg off:noArg toggle:noArg statusRequest:noArg " .
# Used from SetExtensions.pm
"blink on-for-timer on-till off-for-timer off-till intervals",
"Dimmer" => "on:noArg off:noArg toggle:noArg statusRequest:noArg pct:slider,0,1,100 ani " .
# Used from SetExtensions.pm
"blink on-for-timer on-till off-for-timer off-till intervals",
"EnvSensor" => "",
"RGB_Dimmer" => "Color " .
"ColorAnimation",
"Custom" => "PowerSwitch.SwitchState " .
"PowerSwitch.SwitchStateExt " .
"Dimmer.Brightness " .
"Dimmer.Animation"
"PowerSwitch" => "on:noArg off:noArg toggle:noArg statusRequest:noArg " .
# Used from SetExtensions.pm
"blink on-for-timer on-till off-for-timer off-till intervals " .
"DigitalPort " .
"DigitalPortTimeout " .
"DigitalPin " .
"DigitalPinTimeout",
"Dimmer" => "on:noArg off:noArg toggle:noArg statusRequest:noArg pct:slider,0,1,100 ani " .
# Used from SetExtensions.pm
"blink on-for-timer on-till off-for-timer off-till intervals",
"EnvSensor" => "",
"RGBDimmer" => "Color " .
"ColorAnimation " .
"Dimmer.Brightness:slider,0,1,100",
"SoilMoistureMeter" => "",
"Custom" => "Dimmer.Brightness " .
"Dimmer.Animation"
);
# Supported get commands
@ -92,27 +101,10 @@ my %gets = (
"PowerSwitch" => "",
"Dimmer" => "",
"EnvSensor" => "din:all,1,2,3,4,5,6,7,8 ain:all,1,2,3,4,5 ain_volt:1,2,3,4,5",
"RGB_Dimmer" => "",
"RGBDimmer" => "",
"Custom" => ""
);
# Hashtable for automatic device type assignment
# Format:
# "MessageGroupName:MessageName" => "Auto Device Type"
my %auto_devtype = (
"Weather.Temperature" => "EnvSensor",
"Weather.HumidityTemperature" => "EnvSensor",
"Weather.BarometricPressureTemperature" => "EnvSensor",
"Environment.Brightness" => "EnvSensor",
"Environment.Distance" => "EnvSensor",
"GPIO.DigitalPin" => "EnvSensor",
"GPIO.AnalogPin" => "EnvSensor",
"PowerSwitch.SwitchState" => "PowerSwitch",
"Dimmer.Brightness" => "Dimmer",
"Dimmer.Color" => "RGB_Dimmer",
"Dimmer.ColorAnimation" => "RGB_Dimmer"
);
sub SHCdev_Parse($$);
#####################################
@ -120,7 +112,7 @@ sub SHCdev_Initialize($)
{
my ($hash) = @_;
$hash->{Match} = "^Packet Data: SenderID=[1-9]|0[1-9]|[1-9][0-9]|[0-9][0-9][0-9]|[0-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-6]";
$hash->{Match} = "^PKT:SID=([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-3][0-9][0-9][0-9]|40[0-8][0-9]|409[0-6]);";
$hash->{SetFn} = "SHCdev_Set";
$hash->{GetFn} = "SHCdev_Get";
$hash->{DefFn} = "SHCdev_Define";
@ -130,7 +122,7 @@ sub SHCdev_Initialize($)
." readonly:1"
." forceOn:1"
." $readingFnAttributes"
." devtype:EnvSensor,Dimmer,PowerSwitch,RGB_Dimmer";
." devtype:EnvSensor,Dimmer,PowerSwitch,RGBDimmer,SoilMoistureMeter";
}
#####################################
@ -198,7 +190,7 @@ sub SHCdev_Parse($$)
my $name = $hash->{NAME};
if (!$parser->parse($msg)) {
Log3 $hash, 4, "SHC_TEMP: parser error: $msg";
Log3 $name, 1, "$name: Parser error: $msg";
return "";
}
@ -210,7 +202,7 @@ sub SHCdev_Parse($$)
my $rname = $rhash ? $rhash->{NAME} : $raddr;
if (!$modules{SHCdev}{defptr}{$raddr}) {
Log3 $name, 3, "SHC_TEMP: Unknown device $rname, please define it";
Log3 $name, 3, "$name: Unknown device $rname, please define it";
return "UNDEFINED SHCdev_$rname SHCdev $raddr";
}
@ -234,9 +226,6 @@ sub SHCdev_Parse($$)
given ($msggroupname) {
when ('Generic') {
given ($msgname) {
when ('BatteryStatus') {
readingsBulkUpdate($rhash, "battery", $parser->getField("Percentage"));
}
when ('Version') {
my $major = $parser->getField("Major");
my $minor = $parser->getField("Minor");
@ -244,22 +233,61 @@ sub SHCdev_Parse($$)
my $vhash = $parser->getField("Hash");
readingsBulkUpdate($rhash, "version", "$major.$minor.$patch-$vhash");
}
when ('DeviceInfo') {
my $devtype = $parser->getField("DeviceType");
my $major = $parser->getField("VersionMajor");
my $minor = $parser->getField("VersionMinor");
my $patch = $parser->getField("VersionPatch");
my $vhash = $parser->getField("VersionHash");
# Assign device type
my $devtypeOld = AttrVal( $rname, "devtype", undef );
if (!defined($devtypeOld)) {
$attr{$rname}{devtype} = $devtype;
Log3 $name, 3, "$rname: Assign device type = " . $attr{$rname}{devtype};
}
readingsBulkUpdate($rhash, "version", "$major.$minor.$patch-$vhash");
}
when ('BatteryStatus') {
readingsBulkUpdate($rhash, "battery", $parser->getField("Percentage"));
}
}
}
when ('GPIO') {
given ($msgname) {
when ('DigitalPin') {
when ('DigitalPortTimeout') {
my $pins = "";
for (my $i = 0 ; $i < 8 ; $i++) {
my $pinx = $parser->getField("On", $i);
my $timeoutx = $parser->getField("TimeoutSec", $i);
my $channel = $i + 1;
if ($channel == 1)
{
readingsBulkUpdate($rhash, "on", $pinx);
}
readingsBulkUpdate($rhash, "pin" . $channel, $pinx);
readingsBulkUpdate($rhash, "timeout" . $channel, $timeoutx);
$pins .= $pinx;
}
readingsBulkUpdate($rhash, "port", $pins);
}
when ('DigitalPort') {
my $pins = "";
for (my $i = 0 ; $i < 8 ; $i++) {
my $pinx = $parser->getField("On", $i);
my $channel = $i + 1;
readingsBulkUpdate($rhash, "din" . $channel, $pinx);
if ($channel == 1)
{
readingsBulkUpdate($rhash, "on", $pinx);
}
readingsBulkUpdate($rhash, "pin" . $channel, $pinx);
$pins .= $pinx;
}
readingsBulkUpdate($rhash, "dins", $pins);
readingsBulkUpdate($rhash, "port", $pins);
}
when ('AnalogPin') {
when ('AnalogPort') {
my $pins = "";
for (my $i = 0 ; $i < 5 ; $i++) {
my $pinx_on = $parser->getField("On", $i);
@ -294,6 +322,11 @@ sub SHCdev_Parse($$)
readingsBulkUpdate($rhash, "barometric_pressure", $bar);
readingsBulkUpdate($rhash, "temperature", $tmp);
}
when ('Humidity') {
my $hum = $parser->getField("Humidity") / 10; # parser returns 1/10 percent
readingsBulkUpdate($rhash, "humidity", $hum);
}
}
}
when ('Environment') {
@ -308,17 +341,6 @@ sub SHCdev_Parse($$)
}
}
}
when ('PowerSwitch') {
given ($msgname) {
when ('SwitchState') {
my $on = $parser->getField("On");
my $timeout = $parser->getField("TimeoutSec");
readingsBulkUpdate($rhash, "on", $on);
readingsBulkUpdate($rhash, "timeout", $timeout);
}
}
}
when ('Dimmer') {
given ($msgname) {
when ('Brightness') {
@ -348,13 +370,6 @@ sub SHCdev_Parse($$)
}
}
# Autoassign device type
my $devtype = AttrVal( $rname, "devtype", undef );
if (!defined($devtype) && (defined($auto_devtype{"$msggroupname.$msgname"}))) {
$attr{$rname}{devtype} = $auto_devtype{"$msggroupname.$msgname"};
Log3 $name, 3, "$rname: Autoassign device type = " . $attr{$rname}{devtype};
}
# If the devtype is defined add, if not already done, the according webCmds and devStateIcons
my $devtype2 = AttrVal( $rname, "devtype", undef );
if (defined($devtype2)) {
@ -446,23 +461,56 @@ sub SHCdev_Set($@)
# is able to do this as well. Even more it supports intervals, off-for-timer, off-till ...
if ($cmd eq 'toggle') {
$cmd = ReadingsVal($name, "state", "on") eq "off" ? "on" : "off";
$cmd = ReadingsVal($name, "on", "0") eq "0" ? "on" : "off";
}
if (!$readonly && $cmd eq 'off') {
readingsSingleUpdate($hash, "state", "set-$cmd", 1);
$parser->initPacket("PowerSwitch", "SwitchState", "SetGet");
$parser->setField("PowerSwitch", "SwitchState", "TimeoutSec", 0);
$parser->setField("PowerSwitch", "SwitchState", "On", 0);
$parser->initPacket("GPIO", "DigitalPin", "SetGet");
$parser->setField("GPIO", "DigitalPin", "Pos", 0);
$parser->setField("GPIO", "DigitalPin", "On", 0);
SHCdev_Send($hash);
} elsif (!$readonly && $cmd eq 'on') {
readingsSingleUpdate($hash, "state", "set-$cmd", 1);
$parser->initPacket("PowerSwitch", "SwitchState", "SetGet");
$parser->setField("PowerSwitch", "SwitchState", "TimeoutSec", 0);
$parser->setField("PowerSwitch", "SwitchState", "On", 1);
$parser->initPacket("GPIO", "DigitalPin", "SetGet");
$parser->setField("GPIO", "DigitalPin", "Pos", 0);
$parser->setField("GPIO", "DigitalPin", "On", 1);
SHCdev_Send($hash);
} elsif ($cmd eq 'statusRequest') {
$parser->initPacket("PowerSwitch", "SwitchState", "Get");
$parser->initPacket("GPIO", "DigitalPin", "Get");
SHCdev_Send($hash);
} elsif ($cmd eq 'DigitalPort') {
$parser->initPacket("GPIO", "DigitalPort", "SetGet");
# if not enough (less than 8) pinbits are available use zero as default
my $pinbits = $arg . "00000000";
for (my $i = 0 ; $i < 8 ; $i = $i + 1) {
$parser->setField("GPIO", "DigitalPort", "On", substr($pinbits, $i , 1), $i);
}
SHCdev_Send($hash);
} elsif ($cmd eq 'DigitalPortTimeout') { # TODO implement correctly
$parser->initPacket("GPIO", "DigitalPortTimeout", "SetGet");
# if not enough (less than 8) pinbits are available use zero as default
my $pinbits = $arg . "00000000";
for (my $i = 0 ; $i < 8 ; $i = $i + 1) {
my $pintimeout = "0"; # default value for timeout
if (exists $aa[$i + 2]) {
$pintimeout = $aa[$i + 2];
}
Log3 $name, 3, "$name: $i: Pin: " . substr($pinbits, $i , 1) . " Timeout: $pintimeout";
$parser->setField("GPIO", "DigitalPortTimeout", "On", substr($pinbits, $i , 1), $i);
$parser->setField("GPIO", "DigitalPortTimeout", "TimeoutSec", $pintimeout, $i);
}
SHCdev_Send($hash);
} elsif ($cmd eq 'DigitalPin') {
$parser->initPacket("GPIO", "DigitalPin", "SetGet");
$parser->setField("GPIO", "DigitalPin", "Pos", $arg);
$parser->setField("GPIO", "DigitalPin", "On", $arg2);
SHCdev_Send($hash);
} elsif ($cmd eq 'DigitalPinTimeout') {
$parser->initPacket("GPIO", "DigitalPinTimeout", "SetGet");
$parser->setField("GPIO", "DigitalPinTimeout", "Pos", $arg);
$parser->setField("GPIO", "DigitalPinTimeout", "On", $arg2);
$parser->setField("GPIO", "DigitalPinTimeout", "TimeoutSec", $arg3);
SHCdev_Send($hash);
} else {
return SetExtensions($hash, "", $name, @aa);
@ -519,7 +567,7 @@ sub SHCdev_Set($@)
return SetExtensions($hash, "", $name, @aa);
}
}
when ('RGB_Dimmer') {
when ('RGBDimmer') {
if ($cmd eq 'Color') {
#TODO Verify argument values
my $color = $arg;
@ -562,6 +610,16 @@ sub SHCdev_Set($@)
}
readingsSingleUpdate($hash, "state", "set-coloranimation", 1);
SHCdev_Send($hash);
} elsif ($cmd eq 'Dimmer.Brightness') {
my $brightness = $arg;
# DEBUG
# Log3 $name, 3, "$name: Args: $arg, $arg2, $arg3, $brightness";
readingsSingleUpdate($hash, "state", "set-brightness:$brightness", 1);
$parser->initPacket("Dimmer", "Brightness", "SetGet");
$parser->setField("Dimmer", "Brightness", "Brightness", $brightness);
SHCdev_Send($hash);
} else {
return SetExtensions($hash, "", $name, @aa);
}
@ -605,10 +663,10 @@ sub SHCdev_Get($@)
}
elsif ($arg eq "all")
{
if ( defined($hash->{READINGS}{dins})
&& defined($hash->{READINGS}{dins}{VAL}))
if ( defined($hash->{READINGS}{port})
&& defined($hash->{READINGS}{port}{VAL}))
{
return "$name.dins => " . $hash->{READINGS}{dins}{VAL};
return "$name.port => " . $hash->{READINGS}{port}{VAL};
}
return "Error: \"input all\" readings not yet available or not supported by device";
}
@ -676,7 +734,7 @@ sub SHCdev_Send($)
<h3>SHCdev</h3>
<ul>
SHC is the device module that supports several device types available
at <a href="http://http://www.smarthomatic.org">www.smarthomatic.org</a>.<br><br>
at <a href="http://www.smarthomatic.org">www.smarthomatic.org</a>.<br><br>
These device are connected to the FHEM server through the SHC base station (<a href="#SHC">SHC</a>).<br><br>
Currently supported are:<br>
@ -684,6 +742,8 @@ sub SHCdev_Send($)
<li>EnvSensor</li>
<li>PowerSwitch</li>
<li>Dimmer</li>
<li>RGBDimmer</li>
<li>SoilMoistureMeter</li>
</ul><br>
<a name="SHCdev_Define"></a>
@ -707,10 +767,10 @@ sub SHCdev_Send($)
<b>Set</b>
<ul>
<li>on<br>
Supported by Dimmer and PowerSwitch.
Supported by Dimmer and PowerSwitch (on always refers to pin1).
</li><br>
<li>off<br>
Supported by Dimmer, PowerSwitch.
Supported by Dimmer and PowerSwitch (off always refers to pin1).
</li><br>
<li>pct &lt;0..100&gt;<br>
Sets the brightness in percent. Supported by Dimmer.
@ -725,12 +785,36 @@ sub SHCdev_Send($)
<li>Color &lt;ColorNumber&gt;<br>
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#Dimmer_Color">www.smarthomatic.org</a>
The color palette can be found <a href="http://www.smarthomatic.org/devices/rgb_dimmer.html">here</a>
Supported by RGB_Dimmer.
Supported by RGBDimmer.
</li><br>
<li>ColorAnimation &lt;Repeat&gt; &lt;AutoReverse&gt; &lt;Time0&gt; &lt;ColorNumber0&gt; &lt;Time1&gt; &lt;ColorNumber1&gt; ... up to 10 time/color pairs<br>
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#Dimmer_ColorAnimation">www.smarthomatic.org</a>
The color palette can be found <a href="http://www.smarthomatic.org/devices/rgb_dimmer.html">here</a>
Supported by RGB_Dimmer.
Supported by RGBDimmer.
</li><br>
<li>DigitalPin &lt;Pos&gt; &lt;On&gt;<br>
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#GPIO_DigitalPin">www.smarthomatic.org</a>
Supported by PowerSwitch.
</li><br>
<li>DigitalPinTimeout &lt;Pos&gt; &lt;On&gt; &lt;Timeout&gt;<br>
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#GPIO_DigitalPinTimeout">www.smarthomatic.org</a>
Supported by PowerSwitch.
</li><br>
<li>DigitalPort &lt;On&gt;<br>
&lt;On&gt;<br>
is a bit array (0 or 1) describing the port state. If less than eight bits were provided zero is assumed.
Example: set SHC_device DigitalPort 10110000 will set pin0, pin2 and pin3 to 1.<br>
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#GPIO_DigitalPort">www.smarthomatic.org</a>
Supported by PowerSwitch.
</li><br>
<li>DigitalPortTimeout &lt;On&gt; &lt;Timeout0&gt; .. &lt;Timeout7&gt;<br>
&lt;On&gt;<br>
is a bit array (0 or 1) describing the port state. If less than eight bits were provided zero is assumed.
Example: set SHC_device DigitalPort 10110000 will set pin0, pin2 and pin3 to 1.<br>
&lt;Timeout0&gt; .. &lt;Timeout7&gt;<br>
are the timeouts for each pin. If no timeout is provided zero is assumed.
A detailed description is available at <a href="http://www.smarthomatic.org/basics/message_catalog.html#GPIO_DigitalPortTimeout">www.smarthomatic.org</a>
Supported by PowerSwitch.
</li><br>
<li><a href="#setExtensions"> set extensions</a><br>
Supported by Dimmer and PowerSwitch.</li>
@ -764,7 +848,7 @@ sub SHCdev_Send($)
<ul>
<li>devtype<br>
The device type determines the command set, default web commands and the
default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch, RGB_Dimmer.<br><br>
default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch, RGBDimmer, SoilMoistureMeter.<br><br>
Note: If the device is not set manually, it will be determined automatically
on reception of a device type specific message. For example: If a

View File

@ -150,19 +150,16 @@ sub getInt($$$)
{
my ($byteArrayRef, $offset, $length_bits) = @_;
# FIX ME! DOES NOT WORK WITH NEGATIVE VALUES!
$x = getUInt($byteArrayRef, $offset, $length_bits);
# If MSB is 1 (value is negative interpreted as signed int),
# set all higher bits also to 1.
if ((($x >> ($length_bits - 1)) & 1) == 1) {
$x = $x | ~((1 << ($length_bits - 1)) - 1);
if ($x >= 2 ** ($length_bits - 1))
{
$x = $x - 2 ** $length_bits;
}
$y = $x;
# DEBUG print "UInt = " . $x . ", length_bits = " . length_bits . "\r\n";
return $y;
return $x;
}
# ----------- UIntValue class -----------
@ -219,14 +216,14 @@ sub getValue
{
my ($self, $byteArrayRef, $index) = @_;
return SHC_util::getUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits});
return SHC_util::getInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits});
}
sub setValue
{
my ($self, $byteArrayRef, $value, $index) = @_;
SHC_util::setUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits}, $value);
SHC_util::setInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits}, $value);
}
# ----------- BoolValue class -----------

View File

@ -3,7 +3,7 @@
##########################################################################
# This file is part of the smarthomatic module for FHEM.
#
# Copyright (c) 2014 Uwe Freese
# Copyright (c) 2014, 2015 Uwe Freese
#
# You can find smarthomatic at www.smarthomatic.org.
# You can find FHEM at www.fhem.de.
@ -30,11 +30,12 @@
# Receiving packets:
# ------------------
# 1.) Receive string from base station (over UART).
# 2.) Parse received string:
# $parser->parse("Packet Data: SenderID=22;...");
# 3.) Get MessageGroupName: my $grp = $parser->getMessageGroupName();
# 4.) Get MessageName: my $msg = $parser->getMessageName();
# 5.) Get data fields depending on MessageGroupName and MessageName, e.g.
# 2.) Check CRC (last 8 characters, optional).
# 3.) Parse received string:
# $parser->parse("PKT:SID=22;...");
# 4.) Get MessageGroupName: my $grp = $parser->getMessageGroupName();
# 5.) Get MessageName: my $msg = $parser->getMessageName();
# 6.) Get data fields depending on MessageGroupName and MessageName, e.g.
# $val = $parser->getField("Temperature");
#
# Sending packets:
@ -44,6 +45,7 @@
# 2.) Set fields:
# $parser->setField("PowerSwitch", "SwitchState", "TimeoutSec", 8);
# 3.) Get send string: $str = $parser->getSendString($receiverID);
# It includes a CRC32 as last 8 characters.
# 4.) Send string to base station (over UART).
##########################################################################
# $Id$
@ -54,6 +56,7 @@ use strict;
use feature qw(switch);
use XML::LibXML;
use SHC_datafields;
use Digest::CRC qw(crc32); # linux packet libdigest-crc-perl
# Hash for data field definitions.
my %dataFields = ();
@ -250,10 +253,10 @@ sub parse
if (
(
$msg =~
/^Packet Data: SenderID=(\d*);PacketCounter=(\d*);MessageType=(\d*);MessageGroupID=(\d*);MessageID=(\d*);MessageData=([^;]*);.*/
/^PKT:SID=(\d+);PC=(\d+);MT=(\d+);MGID=(\d+);MID=(\d+);MD=([^;]+);.*/
)
|| ($msg =~
/^Packet Data: SenderID=(\d*);PacketCounter=(\d*);MessageType=(\d*);AckSenderID=\d*;AckPacketCounter=\d*;Error=\d*;MessageGroupID=(\d*);MessageID=(\d*);MessageData=([^;]*);.*/
/^PKT:SID=(\d+);PC=(\d+);MT=(\d+);ASID=\d+;APC=\d+;E=\d+;MGID=(\d+);MID=(\d+);MD=([^;]+);.*/
)
)
{
@ -311,6 +314,9 @@ sub getMessageData
$res .= sprintf("%02X", $_);
}
# strip trailing zeros (pairwise)
$res =~ s/(00)+$//;
return $res;
} else {
return $self->{_messageData};
@ -365,8 +371,8 @@ sub setField
$obj->setValue(\@msgData, $value, $index);
}
# sKK01RRRRGGMMDD
# s0001003D3C0164 = SET Dimmer Switch Brightness 50%
# cKK01RRRRGGMMDD{CRC32}
# c0001003D3C0164 = SET Dimmer Switch Brightness 50%
sub getSendString
{
my ($self, $receiverID, $aesKeyNr) = @_;
@ -382,13 +388,15 @@ sub getSendString
$aesKeyNr = 0;
}
my $s = "s"
my $s = "c"
. sprintf("%02X", $aesKeyNr)
. sprintf("%02X", $self->{_messageTypeID})
. sprintf("%04X", $receiverID)
. sprintf("%02X", $self->{_messageGroupID})
. sprintf("%02X", $self->{_messageID})
. getMessageData();
return $s . sprintf("%08x", crc32($s));
}
1;

View File

@ -190,7 +190,7 @@
<MessageType>0</MessageType>
<MessageType>8</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<Validity>deprecated</Validity>
<UIntValue>
<ID>Major</ID>
<Description>Different major version means incompatible changes.</Description>
@ -220,6 +220,76 @@
<MaxVal>4294967295</MaxVal>
</UIntValue>
</Message>
<Message>
<Name>DeviceInfo</Name>
<Description>Reports DeviceType and current firmware version. Version information is only available when set in source code, which is usually only done for official builds by the build robot.</Description>
<MessageID>2</MessageID>
<MessageType>0</MessageType>
<MessageType>8</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<EnumValue>
<ID>DeviceType</ID>
<Description>The DeviceType can be used to adapt the behavior or representation of the SHC device at the server software (e.g. FHEM).</Description>
<Bits>8</Bits>
<Element>
<Value>0</Value>
<Name>BaseStation</Name>
</Element>
<Element>
<Value>20</Value>
<Name>EnvSensor</Name>
</Element>
<Element>
<Value>40</Value>
<Name>PowerSwitch</Name>
</Element>
<Element>
<Value>50</Value>
<Name>RGBDimmer</Name>
</Element>
<Element>
<Value>60</Value>
<Name>Dimmer</Name>
</Element>
<Element>
<Value>70</Value>
<Name>SoilMoistureMeter</Name>
</Element>
<Element>
<Value>80</Value>
<Name>Thermostat</Name>
</Element>
</EnumValue>
<UIntValue>
<ID>VersionMajor</ID>
<Description>Different major version means incompatible changes.</Description>
<Bits>8</Bits>
<MinVal>0</MinVal>
<MaxVal>255</MaxVal>
</UIntValue>
<UIntValue>
<ID>VersionMinor</ID>
<Description>Different minor number means new functionality without breaking compatibility.</Description>
<Bits>8</Bits>
<MinVal>0</MinVal>
<MaxVal>255</MaxVal>
</UIntValue>
<UIntValue>
<ID>VersionPatch</ID>
<Description>The patch version is changed when backwards-compatible bug fixes are made.</Description>
<Bits>8</Bits>
<MinVal>0</MinVal>
<MaxVal>255</MaxVal>
</UIntValue>
<UIntValue>
<ID>VersionHash</ID>
<Description>The beginning of the revision ID hash (as reported by Git).</Description>
<Bits>32</Bits>
<MinVal>0</MinVal>
<MaxVal>4294967295</MaxVal>
</UIntValue>
</Message>
<Message>
<Name>BatteryStatus</Name>
<Description>Tells the current battery status in percent. Please note that the "Get" may not be answered because a device does not listen to requests.</Description>
@ -242,8 +312,8 @@
<Description>This group contains messages for general I/O functions. The meaning of the values is not known to the SHC devices. It depends on the connected parts (e.g. switches). The values have to be processed by the user/server software appropriately.</Description>
<MessageGroupID>1</MessageGroupID>
<Message>
<Name>DigitalPin</Name>
<Description>This is the state of up to 8 pins.</Description>
<Name>DigitalPort</Name>
<Description>This is the state of the complete digital port, containing up to 8 pins.</Description>
<MessageID>1</MessageID>
<MessageType>0</MessageType>
<MessageType>1</MessageType>
@ -261,8 +331,8 @@
</Array>
</Message>
<Message>
<Name>AnalogPin</Name>
<Description>This is the voltage of up to 8 ADC channels. The ATMega328 in the PDIP package has only 6 ADCs and one ADC may be blocked by the battery voltage measurement, so there may be less than 8 ADC values reported depending on the device and configuration.</Description>
<Name>DigitalPortTimeout</Name>
<Description>This is the state of the complete digital port, containing up to 8 pins, including a timeout value per pin.</Description>
<MessageID>2</MessageID>
<MessageType>0</MessageType>
<MessageType>1</MessageType>
@ -271,15 +341,91 @@
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<Array>
<Length>8</Length>
<BoolValue>
<ID>On</ID>
<Description>Tells if the pin is on (at high level) or not (low level).</Description>
</BoolValue>
<UIntValue>
<ID>TimeoutSec</ID>
<Description>The time after which the switch is automatically toggled again. Use 0 to disable this.</Description>
<Bits>16</Bits>
<MinVal>0</MinVal>
<MaxVal>65535</MaxVal>
</UIntValue>
</Array>
</Message>
<Message>
<Name>DigitalPin</Name>
<Description>This represents the state of one pin of the digital port.</Description>
<MessageID>5</MessageID>
<MessageType>0</MessageType>
<MessageType>1</MessageType>
<MessageType>2</MessageType>
<MessageType>8</MessageType>
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<UIntValue>
<ID>Pos</ID>
<Description>The number of the pin in the port.</Description>
<Bits>3</Bits>
<MinVal>0</MinVal>
<MaxVal>7</MaxVal>
</UIntValue>
<BoolValue>
<ID>On</ID>
<Description>Tells if the pin is on (at high level) or not (low level).</Description>
</BoolValue>
</Message>
<Message>
<Name>DigitalPinTimeout</Name>
<Description>This represents the state of one pin of the digital port, including a timeout value.</Description>
<MessageID>6</MessageID>
<MessageType>0</MessageType>
<MessageType>1</MessageType>
<MessageType>2</MessageType>
<MessageType>8</MessageType>
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<UIntValue>
<ID>Pos</ID>
<Description>The number of the pin in the port.</Description>
<Bits>3</Bits>
<MinVal>0</MinVal>
<MaxVal>7</MaxVal>
</UIntValue>
<BoolValue>
<ID>On</ID>
<Description>Tells if the pin is on (at high level) or not (low level).</Description>
</BoolValue>
<UIntValue>
<ID>TimeoutSec</ID>
<Description>The time after which the switch is automatically toggled again. Use 0 to disable this.</Description>
<Bits>16</Bits>
<MinVal>0</MinVal>
<MaxVal>65535</MaxVal>
</UIntValue>
</Message>
<Message>
<Name>AnalogPort</Name>
<Description>This is the voltage of up to 8 ADC channels. The ATMega328 in the PDIP package has only 6 ADCs and one ADC may be blocked by the battery voltage measurement, so there may be less than 8 ADC values reported depending on the device and configuration.</Description>
<MessageID>10</MessageID>
<MessageType>0</MessageType>
<MessageType>1</MessageType>
<MessageType>2</MessageType>
<MessageType>8</MessageType>
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<Array>
<Length>8</Length>
<BoolValue>
<ID>On</ID>
<Description>Tells if the pin is on (voltage over trigger threshold) or not.</Description>
</BoolValue>
</Array>
<Array>
<Length>8</Length>
<UIntValue>
<ID>Voltage</ID>
<Description>This is the voltage level in mV.</Description>
@ -356,6 +502,22 @@
<MaxVal>32767</MaxVal>
</IntValue>
</Message>
<Message>
<Name>Humidity</Name>
<Description>This is a message containing humidity.</Description>
<MessageID>4</MessageID>
<MessageType>0</MessageType>
<MessageType>8</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<UIntValue>
<ID>Humidity</ID>
<Description>relative humidity permill, 0..1000 (other values not defined)</Description>
<Bits>10</Bits>
<MinVal>0</MinVal>
<MaxVal>1000</MaxVal>
</UIntValue>
</Message>
</MessageGroup>
<MessageGroup>
<Name>Environment</Name>
@ -408,7 +570,7 @@
<MessageType>8</MessageType>
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<Validity>deprecated</Validity>
<BoolValue>
<ID>On</ID>
<Description>Tells if the switch is on (active).</Description>
@ -431,7 +593,7 @@
<MessageType>8</MessageType>
<MessageType>9</MessageType>
<MessageType>10</MessageType>
<Validity>test</Validity>
<Validity>deprecated</Validity>
<Array>
<Length>8</Length>
<BoolValue>