diff --git a/fhem/CHANGED b/fhem/CHANGED
index 3e6c0b3f8..70d358343 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -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: SHC: support for analog inputs (EnvSensor) and new device
+ RGB_Dimmer added (rr2000)
- feature: PRESENCE: MAC address support for mode fritzbox (by Markus M.)
- bugfix: PRESENCE: fixing presence detection in mode fritzbox with new
Fritz!OS 6.20 (by Markus M.)
diff --git a/fhem/FHEM/37_SHCdev.pm b/fhem/FHEM/37_SHCdev.pm
index 1d986dfc4..4905ab894 100644
--- a/fhem/FHEM/37_SHCdev.pm
+++ b/fhem/FHEM/37_SHCdev.pm
@@ -35,13 +35,15 @@ 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
+ "EnvSensor" => undef,
+ "RGB_Dimmer" => undef
);
my %web_cmds = (
"PowerSwitch" => "on:off:toggle:statusRequest",
"Dimmer" => "on:off:statusRequest",
- "EnvSensor" => undef
+ "EnvSensor" => undef,
+ "RGB_Dimmer" => undef
);
# Array format: [ reading1, str_format1, reading2, str_format2 ... ]
@@ -50,12 +52,17 @@ my %web_cmds = (
my %dev_state_format = (
"PowerSwitch" => ["on", ""],
"Dimmer" => ["on", "", "brightness", "B: "],
- "EnvSensor" => [ # Results in "T: 23.4 H: 27.3 Baro: 978.34 B: 45"
+ "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: "
+ "distance", "D: ",
+ "dins", "Din: ",
+ "ains", "Ain: "
+ ],
+ "RGB_Dimmer" => [
+ "color", "Color: "
]
);
@@ -71,6 +78,8 @@ my %sets = (
# 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 " .
@@ -82,7 +91,8 @@ my %sets = (
my %gets = (
"PowerSwitch" => "",
"Dimmer" => "",
- "EnvSensor" => "input:all,1,2,3,4,5,6,7,8 ",
+ "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" => "",
"Custom" => ""
);
@@ -96,8 +106,11 @@ my %auto_devtype = (
"Environment.Brightness" => "EnvSensor",
"Environment.Distance" => "EnvSensor",
"GPIO.DigitalPin" => "EnvSensor",
+ "GPIO.AnalogPin" => "EnvSensor",
"PowerSwitch.SwitchState" => "PowerSwitch",
- "Dimmer.Brightness" => "Dimmer"
+ "Dimmer.Brightness" => "Dimmer",
+ "Dimmer.Color" => "RGB_Dimmer",
+ "Dimmer.ColorAnimation" => "RGB_Dimmer"
);
sub SHCdev_Parse($$);
@@ -117,7 +130,7 @@ sub SHCdev_Initialize($)
." readonly:1"
." forceOn:1"
." $readingFnAttributes"
- ." devtype:EnvSensor,Dimmer,PowerSwitch";
+ ." devtype:EnvSensor,Dimmer,PowerSwitch,RGB_Dimmer";
}
#####################################
@@ -241,10 +254,22 @@ sub SHCdev_Parse($$)
for (my $i = 0 ; $i < 8 ; $i++) {
my $pinx = $parser->getField("On", $i);
my $channel = $i + 1;
- readingsBulkUpdate($rhash, "pin" . $channel, $pinx);
+ readingsBulkUpdate($rhash, "din" . $channel, $pinx);
$pins .= $pinx;
}
- readingsBulkUpdate($rhash, "pins", $pins);
+ readingsBulkUpdate($rhash, "dins", $pins);
+ }
+ when ('AnalogPin') {
+ my $pins = "";
+ for (my $i = 0 ; $i < 5 ; $i++) {
+ my $pinx_on = $parser->getField("On", $i);
+ my $pinx_volt = $parser->getField("Voltage", $i);
+ my $channel = $i + 1;
+ readingsBulkUpdate($rhash, "ain" . $channel, $pinx_on);
+ readingsBulkUpdate($rhash, "ain_volt" . $channel, $pinx_volt);
+ $pins .= $pinx_on;
+ }
+ readingsBulkUpdate($rhash, "ains", $pins);
}
}
}
@@ -303,6 +328,22 @@ sub SHCdev_Parse($$)
readingsBulkUpdate($rhash, "on", $on);
readingsBulkUpdate($rhash, "brightness", $brightness);
}
+ when ('Color') {
+ my $color = $parser->getField("Color");
+ readingsBulkUpdate($rhash, "color", $color);
+ }
+ when ('ColorAnimation') {
+ my $repeat = $parser->getField("Repeat");
+ my $autoreverse = $parser->getField("AutoReverse");
+ readingsBulkUpdate($rhash, "repeat", $repeat);
+ readingsBulkUpdate($rhash, "autoreverse", $autoreverse);
+ for (my $i = 0 ; $i < 10 ; $i = $i + 1) {
+ my $time = $parser->getField("Time" , $i);
+ my $color = $parser->getField("Color", $i);
+ readingsBulkUpdate($rhash, "time$i", $time);
+ readingsBulkUpdate($rhash, "color$i", $color);
+ }
+ }
}
}
}
@@ -478,6 +519,53 @@ sub SHCdev_Set($@)
return SetExtensions($hash, "", $name, @aa);
}
}
+ when ('RGB_Dimmer') {
+ if ($cmd eq 'Color') {
+ #TODO Verify argument values
+ my $color = $arg;
+
+ # DEBUG
+ # Log3 $name, 3, "$name: Color args: $arg, $arg2, $arg3, $arg4";
+
+ readingsSingleUpdate($hash, "state", "set-color:$color", 1);
+ $parser->initPacket("Dimmer", "Color", "SetGet");
+ $parser->setField("Dimmer", "Color", "Color", $color);
+ SHCdev_Send($hash);
+ } elsif ($cmd eq 'ColorAnimation') {
+ #TODO Verify argument values
+
+ $parser->initPacket("Dimmer", "ColorAnimation", "SetGet");
+ $parser->setField("Dimmer", "ColorAnimation", "Repeat", $arg);
+ $parser->setField("Dimmer", "ColorAnimation", "AutoReverse", $arg2);
+
+ my $curtime = 0;
+ my $curcolor = 0;
+ # Iterate over all given command line parameters and set Time and Color
+ # accordingly. Fill the remaining values with zero.
+ for (my $i = 0 ; $i < 10 ; $i = $i + 1) {
+ if (!defined($aa[($i * 2) + 3])) {
+ $curtime = 0;
+ } else {
+ $curtime = $aa[($i * 2) + 3];
+ }
+ if (!defined($aa[($i * 2) + 4])) {
+ $curcolor = 0;
+ } else {
+ $curcolor = $aa[($i * 2) + 4];
+ }
+
+ # DEBUG
+ # Log3 $name, 3, "$name: Nr: $i Time: $curtime Color: $curcolor";
+
+ $parser->setField("Dimmer", "ColorAnimation", "Time" , $curtime, $i);
+ $parser->setField("Dimmer", "ColorAnimation", "Color", $curcolor, $i);
+ }
+ readingsSingleUpdate($hash, "state", "set-coloranimation", 1);
+ SHCdev_Send($hash);
+ } else {
+ return SetExtensions($hash, "", $name, @aa);
+ }
+ }
}
return undef;
@@ -505,9 +593,9 @@ sub SHCdev_Get($@)
given ($devtype) {
when ('EnvSensor') {
- if ($cmd eq 'input') {
+ if ($cmd eq 'din') {
if ($arg =~ /[1-8]/) {
- my $channel = "pin" . $arg;
+ my $channel = "din" . $arg;
if ( defined($hash->{READINGS}{$channel})
&& defined($hash->{READINGS}{$channel}{VAL}))
{
@@ -517,14 +605,45 @@ sub SHCdev_Get($@)
}
elsif ($arg eq "all")
{
- if ( defined($hash->{READINGS}{pins})
- && defined($hash->{READINGS}{pins}{VAL}))
+ if ( defined($hash->{READINGS}{dins})
+ && defined($hash->{READINGS}{dins}{VAL}))
{
- return "$name.pins => " . $hash->{READINGS}{pins}{VAL};
+ return "$name.dins => " . $hash->{READINGS}{dins}{VAL};
}
return "Error: \"input all\" readings not yet available or not supported by device";
}
}
+ if ($cmd eq 'ain') {
+ if ($arg =~ /[1-5]/) {
+ my $channel = "ain" . $arg;
+ if ( defined($hash->{READINGS}{$channel})
+ && defined($hash->{READINGS}{$channel}{VAL}))
+ {
+ return "$name.$channel => " . $hash->{READINGS}{$channel}{VAL};
+ }
+ return "Error: \"input " . $channel . "\" readings not yet available or not supported by device";
+ }
+ elsif ($arg eq "all")
+ {
+ if ( defined($hash->{READINGS}{ains})
+ && defined($hash->{READINGS}{ains}{VAL}))
+ {
+ return "$name.ains => " . $hash->{READINGS}{ains}{VAL};
+ }
+ return "Error: \"input all\" readings not yet available or not supported by device";
+ }
+ }
+ if ($cmd eq 'ain_volt') {
+ if ($arg =~ /[1-5]/) {
+ my $channel = "ain_volt" . $arg;
+ if ( defined($hash->{READINGS}{$channel})
+ && defined($hash->{READINGS}{$channel}{VAL}))
+ {
+ return "$name.$channel => " . $hash->{READINGS}{$channel}{VAL};
+ }
+ return "Error: \"input " . $channel . "\" readings not yet available or not supported by device";
+ }
+ }
# This return is required to provide the get commands in the web interface
return "Unknown argument $cmd, choose one of " . $gets{$devtype};
@@ -603,6 +722,16 @@ sub SHCdev_Send($)
statusRequest
Supported by Dimmer and PowerSwitch.
+ Color <ColorNumber>
+ A detailed description is available at www.smarthomatic.org
+ The color palette can be found here
+ Supported by RGB_Dimmer.
+
+ ColorAnimation <Repeat> <AutoReverse> <Time0> <ColorNumber0> <Time1> <ColorNumber1> ... up to 10 time/color pairs
+ A detailed description is available at www.smarthomatic.org
+ The color palette can be found here
+ Supported by RGB_Dimmer.
+
set extensions
Supported by Dimmer and PowerSwitch.
@@ -610,8 +739,22 @@ sub SHCdev_Send($)
Get
- - input <pin>
- Returns the state of the specified pin for pin = 1..8 or the state of all pins for pin = all.
+ - din <pin>
+ Returns the state of the specified digital input pin for pin = 1..8. Or the state of all pins for pin = all.
+ Supported by EnvSensor.
+
+ - ain <pin>
+ Returns the state of the specified analog input pin for pin = 1..5. Or the state of all pins for pin = all.
+ If the voltage of the pin is over the specied trigger threshold) it return 1 otherwise 0.
+ Supported by EnvSensor.
+
+ - ain <pin>
+ Returns the state of the specified analog input pin for pin = 1..5. Or the state of all pins for pin = all.
+ If the voltage of the pin is over the specied trigger threshold) it return 1 otherwise 0.
+ Supported by EnvSensor.
+
+ - ain_volt <pin>
+ Returns the voltage of the specified analog input pin for pin = 1..5 in millivolts, ranging from 0 .. 1100 mV.
Supported by EnvSensor.
@@ -621,7 +764,7 @@ sub SHCdev_Send($)
- devtype
The device type determines the command set, default web commands and the
- default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch.
+ default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch, RGB_Dimmer.
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
diff --git a/fhem/FHEM/SHC_datafields.pm b/fhem/FHEM/SHC_datafields.pm
index 7b424eaae..f9a665fd5 100644
--- a/fhem/FHEM/SHC_datafields.pm
+++ b/fhem/FHEM/SHC_datafields.pm
@@ -97,6 +97,7 @@ sub setUIntBits($$$$$)
# if length is smaller than 8 bits, get the old value from array
if ($length_bits < 8) {
$b = @$byteArrayRef[$byte];
+
$b = clear_bits($b, $bit, $length_bits);
}
@@ -111,7 +112,7 @@ sub setUInt($$$$)
{
my ($byteArrayRef, $offset, $length_bits, $value) = @_;
- my $byte = $offset / 8;
+ my $byte = int($offset / 8);
my $bit = $offset % 8;
# move bits to the left border
@@ -125,7 +126,7 @@ sub setUInt($$$$)
my $len = min($length_bits, 8 - $bit);
my $val8 = get_bits($value, $src_start, $len);
- # DEBUG print " Write bits to byte " . $byte . ", dst_start " . $dst_start . ", len " . $len . ", val8 " . $val8 . "\r\n";
+# DEBUG print " Write value " . $val8 . " (" . $len . " bits) to byte " . $byte . ", dst_start " . $dst_start . "\r\n";
setUIntBits($byteArrayRef, $byte, $dst_start, $len, $val8);
@@ -137,7 +138,7 @@ sub setUInt($$$$)
$val8 = get_bits($value, $src_start, $len);
$byte++;
- # DEBUG print " Byte nr. " . $byte . ", src_start " . $src_start . ", len " . $len . ", val8 " . $val8 . "\r\n";
+# DEBUG print " Write value " . $val8 . " (" . $len . " bits) from src_start " . $src_start . " to byte " . $byte . ", dst_start " . $dst_start . "\r\n";
setUIntBits($byteArrayRef, $byte, $dst_start, $len, $val8);
@@ -172,9 +173,11 @@ sub new
{
my $class = shift;
my $self = {
- _id => shift,
- _offset => shift,
- _bits => shift,
+ _id => shift,
+ _offset => shift,
+ _bits => shift,
+ _length => shift,
+ _arrayElementBits => shift
};
bless $self, $class;
return $self;
@@ -182,16 +185,16 @@ sub new
sub getValue
{
- my ($self, $byteArrayRef) = @_;
+ my ($self, $byteArrayRef, $index) = @_;
- return SHC_util::getUInt($byteArrayRef, $self->{_offset}, $self->{_bits});
+ return SHC_util::getUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits});
}
sub setValue
{
- my ($self, $byteArrayRef, $value) = @_;
+ my ($self, $byteArrayRef, $value, $index) = @_;
- SHC_util::setUInt($byteArrayRef, $self->{_offset}, $self->{_bits}, $value);
+ SHC_util::setUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits}, $value);
}
# ----------- IntValue class -----------
@@ -202,9 +205,11 @@ sub new
{
my $class = shift;
my $self = {
- _id => shift,
- _offset => shift,
- _bits => shift,
+ _id => shift,
+ _offset => shift,
+ _bits => shift,
+ _length => shift,
+ _arrayElementBits => shift
};
bless $self, $class;
return $self;
@@ -212,16 +217,16 @@ sub new
sub getValue
{
- my ($self, $byteArrayRef) = @_;
+ my ($self, $byteArrayRef, $index) = @_;
- return SHC_util::getUInt($byteArrayRef, $self->{_offset}, $self->{_bits});
+ return SHC_util::getUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits});
}
sub setValue
{
- my ($self, $byteArrayRef, $value) = @_;
+ my ($self, $byteArrayRef, $value, $index) = @_;
- SHC_util::setUInt($byteArrayRef, $self->{_offset}, $self->{_bits}, $value);
+ SHC_util::setUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits}, $value);
}
# ----------- BoolValue class -----------
@@ -232,9 +237,10 @@ sub new
{
my $class = shift;
my $self = {
- _id => shift,
- _offset => shift,
- _length => shift,
+ _id => shift,
+ _offset => shift,
+ _length => shift,
+ _arrayElementBits => shift
};
bless $self, $class;
return $self;
@@ -244,14 +250,15 @@ sub getValue
{
my ($self, $byteArrayRef, $index) = @_;
- return SHC_util::getUInt($byteArrayRef, $self->{_offset} + $index, 1) == 1 ? 1 : 0;
+ return SHC_util::getUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, 1) == 1 ? 1 : 0;
}
sub setValue
{
- my ($self, $byteArrayRef, $value) = @_;
+ my ($self, $byteArrayRef, $value, $index) = @_;
- return SHC_util::setUInt($byteArrayRef, $self->{_offset}, 1, $value == 0 ? 0 : 1);
+ return SHC_util::setUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, 1,
+ $value == 0 ? 0 : 1);
}
# ----------- EnumValue class -----------
@@ -265,9 +272,11 @@ sub new
{
my $class = shift;
my $self = {
- _id => shift,
- _offset => shift,
- _bits => shift,
+ _id => shift,
+ _offset => shift,
+ _bits => shift,
+ _length => shift,
+ _arrayElementBits => shift
};
bless $self, $class;
return $self;
@@ -283,18 +292,18 @@ sub addValue
sub getValue
{
- my ($self, $byteArrayRef) = @_;
+ my ($self, $byteArrayRef, $index) = @_;
- my $value = SHC_util::getUInt($byteArrayRef, $self->{_offset}, $self->{_bits});
+ my $value = SHC_util::getUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits});
return $value2name{$value};
}
sub setValue
{
- my ($self, $byteArrayRef, $name) = @_;
+ my ($self, $byteArrayRef, $name, $index) = @_;
my $value = $name2value{$name};
- SHC_util::setUInt($byteArrayRef, $self->{_offset}, $self->{_bits}, $value);
+ SHC_util::setUInt($byteArrayRef, $self->{_offset} + $self->{_arrayElementBits} * $index, $self->{_bits}, $value);
}
1;
diff --git a/fhem/FHEM/SHC_parser.pm b/fhem/FHEM/SHC_parser.pm
index 950cd2fa5..4e960f1b3 100644
--- a/fhem/FHEM/SHC_parser.pm
+++ b/fhem/FHEM/SHC_parser.pm
@@ -34,7 +34,7 @@
# $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.
+# 5.) Get data fields depending on MessageGroupName and MessageName, e.g.
# $val = $parser->getField("Temperature");
#
# Sending packets:
@@ -74,6 +74,8 @@ my %messageID2bits = ();
my @msgData = ();
my $sendMode = 0;
+my $offset = 0;
+
sub new
{
my $class = shift;
@@ -92,6 +94,104 @@ sub new
return $self;
}
+sub init_datafield_positions_noarray($$$$$)
+{
+ my ($messageGroupID, $messageID, $field, $arrayLength, $arrayElementBits) = @_;
+
+ given ($field->nodeName) {
+ when ('UIntValue') {
+ my $id = ($field->findnodes("ID"))[0]->textContent;
+ my $bits = ($field->findnodes("Bits"))[0]->textContent;
+
+ # print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
+
+ $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} =
+ new UIntValue($id, $offset, $bits, $arrayLength, $arrayElementBits);
+
+ $offset += $bits;
+ }
+
+ when ('IntValue') {
+ my $id = ($field->findnodes("ID"))[0]->textContent;
+ my $bits = ($field->findnodes("Bits"))[0]->textContent;
+
+ # print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
+
+ $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} =
+ new IntValue($id, $offset, $bits, $arrayLength, $arrayElementBits);
+
+ $offset += $bits;
+ }
+
+ when ('BoolValue') {
+ my $id = ($field->findnodes("ID"))[0]->textContent;
+ my $bits = 1;
+
+ # print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
+
+ $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} =
+ new BoolValue($id, $offset, $arrayLength, $arrayElementBits);
+
+ $offset += $bits;
+ }
+
+ when ('EnumValue') {
+ my $id = ($field->findnodes("ID"))[0]->textContent;
+ my $bits = ($field->findnodes("Bits"))[0]->textContent;
+
+ # print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
+
+ my $object = new EnumValue($id, $offset, $bits, $arrayLength, $arrayElementBits);
+ $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} = $object;
+
+ for my $element ($field->findnodes("Element")) {
+ my $value = ($element->findnodes("Value"))[0]->textContent;
+ my $name = ($element->findnodes("Name"))[0]->textContent;
+
+ $object->addValue($name, $value);
+ }
+
+ $offset += $bits;
+ }
+ }
+}
+
+sub init_datafield_positions_array($$$)
+{
+ my ($messageGroupID, $messageID, $field) = @_;
+ my $offsetStartArray = $offset;
+
+ my $arrayLength = int(($field->findnodes("Length"))[0]->textContent);
+
+ my $arrayElementBits =
+ calc_array_bits_ovr($field); # number of bits for one struct ("set of sub-elements") in a structured array
+ # print "Next field is an array with " . $arrayLength . " elements (" . $arrayElementBits . " ovr bits per array element)!\n";
+
+ for my $subfield ($field->findnodes("UIntValue|IntValue|BoolValue|EnumValue")) {
+ my $bits =
+ init_datafield_positions_noarray($messageGroupID, $messageID, $subfield, $arrayLength, $arrayElementBits);
+ }
+
+ $offset = $offsetStartArray + $arrayLength * $arrayElementBits;
+}
+
+# Calculate the overall bits for one struct in a structured array
+sub calc_array_bits_ovr($)
+{
+ my ($field) = @_;
+ my $bits = 0;
+
+ for my $subfield ($field->findnodes("BoolValue")) {
+ $bits += 1;
+ }
+
+ for my $subfield ($field->findnodes("UIntValue|IntValue|EnumValue")) {
+ $bits += ($subfield->findnodes("Bits"))[0]->textContent;
+ }
+
+ return $bits;
+}
+
# Read packet layout from XML file and remember the defined MessageGroups,
# Messages and data fields (incl. positions, length).
sub init_datafield_positions()
@@ -121,75 +221,21 @@ sub init_datafield_positions()
$messageID2messageName{$messageGroupID . "-" . $messageID} = $messageName;
$messageName2messageID{$messageGroupName . "-" . $messageName} = $messageID;
- my $offset = 0;
- my $arrayLength = 1;
+ $offset = 0;
for my $field ($message->findnodes("Array|UIntValue|IntValue|BoolValue|EnumValue")) {
# When an array is detected, remember the array length and change the current field node
# to the inner node for further processing.
if ($field->nodeName eq 'Array') {
- $arrayLength = int(($field->findnodes("Length"))[0]->textContent);
- # DEBUG print "Next field is an array with " . $arrayLength . " elements!\n";
-
- $field = ($field->findnodes("UIntValue|IntValue|BoolValue|EnumValue"))[0];
- }
-
- given ($field->nodeName) {
- when ('UIntValue') {
- my $id = ($field->findnodes("ID"))[0]->textContent;
- my $bits = ($field->findnodes("Bits"))[0]->textContent;
-
- # DEBUG print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
-
- $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} = new UIntValue($id, $offset, $bits);
-
- $offset += $bits * $arrayLength;
- }
-
- when ('IntValue') {
- my $id = ($field->findnodes("ID"))[0]->textContent;
- my $bits = ($field->findnodes("Bits"))[0]->textContent;
-
- # DEBUG print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
-
- $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} = new IntValue($id, $offset, $bits);
-
- $offset += $bits * $arrayLength;
- }
-
- when ('BoolValue') {
- my $id = ($field->findnodes("ID"))[0]->textContent;
- my $bits = 1;
-
- # DEBUG print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
-
- $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} = new BoolValue($id, $offset, $arrayLength);
-
- $offset += $bits * $arrayLength;
- }
-
- when ('EnumValue') {
- my $id = ($field->findnodes("ID"))[0]->textContent;
- my $bits = ($field->findnodes("Bits"))[0]->textContent;
-
- # DEBUG print "Data field " . $id . " starts at " . $offset . " with " . $bits . " bits.\n";
-
- my $object = new EnumValue($id, $offset, $bits);
- $dataFields{$messageGroupID . "-" . $messageID . "-" . $id} = $object;
-
- for my $element ($field->findnodes("Element")) {
- my $value = ($element->findnodes("Value"))[0]->textContent;
- my $name = ($element->findnodes("Name"))[0]->textContent;
-
- $object->addValue($name, $value);
- }
-
- $offset += $bits * $arrayLength;
- }
+ init_datafield_positions_array($messageGroupID, $messageID, $field);
+ } else {
+ init_datafield_positions_noarray($messageGroupID, $messageID, $field, 1, 0);
}
}
+# DEBUG print "Remember packet length " . $offset . " bits for MessageGroupID " . $messageGroupID . ", MessageID " . $messageID . "\n";
+
$messageID2bits{$messageGroupID . "-" . $messageID} = $offset;
}
}
@@ -275,8 +321,14 @@ sub getField
{
my ($self, $fieldName, $index) = @_;
+ if (!defined $index) {
+ $index = 0;
+ }
+
my $obj = $dataFields{$self->{_messageGroupID} . "-" . $self->{_messageID} . "-" . $fieldName};
- my @tmpArray = map hex("0x$_"), $self->{_messageData} =~ /(..)/g;
+
+ # add 256 "empty" bytes to have enough data in the array because the message may be truncated
+ my @tmpArray = map hex("0x$_"), ($self->{_messageData} . ("00" x 256)) =~ /(..)/g;
return $obj->getValue(\@tmpArray, $index);
}
@@ -290,23 +342,27 @@ sub initPacket
$self->{_messageGroupID} = $messageGroupName2messageGroupID{$messageGroupName};
$self->{_messageID} = $messageName2messageID{$messageGroupName . "-" . $messageName};
- my $lenBytes = $messageID2bits{$self->{_messageGroupID} . "-" . $self->{_messageID}} / 8;
+ my $lenBytes = int(($messageID2bits{$self->{_messageGroupID} . "-" . $self->{_messageID}} + 7) / 8);
- @msgData = 0 x $lenBytes;
+ @msgData = (0) x $lenBytes;
$sendMode = 1;
}
sub setField
{
- my ($self, $messageGroupName, $messageName, $fieldName, $value) = @_;
+ my ($self, $messageGroupName, $messageName, $fieldName, $value, $index) = @_;
+
+ if (!defined $index) {
+ $index = 0;
+ }
my $gID = $messageGroupName2messageGroupID{$messageGroupName};
my $mID = $messageName2messageID{$messageGroupName . "-" . $messageName};
my $obj = $dataFields{$gID . "-" . $mID . "-" . $fieldName};
- $obj->setValue(\@msgData, $value);
+ $obj->setValue(\@msgData, $value, $index);
}
# sKK01RRRRGGMMDD
@@ -322,6 +378,10 @@ sub getSendString
# Add lookup table device -> AES key?
# Automatically gather used AES key after reception from device?
+ if (!defined $aesKeyNr) {
+ $aesKeyNr = 0;
+ }
+
my $s = "s"
. sprintf("%02X", $aesKeyNr)
. sprintf("%02X", $self->{_messageTypeID})
diff --git a/fhem/FHEM/lib/SHC_packet_layout.xml b/fhem/FHEM/lib/SHC_packet_layout.xml
index a62f4d8b7..62d0d76ef 100644
--- a/fhem/FHEM/lib/SHC_packet_layout.xml
+++ b/fhem/FHEM/lib/SHC_packet_layout.xml
@@ -260,6 +260,35 @@
+
+ AnalogPin
+ 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.
+ 2
+ 0
+ 1
+ 2
+ 8
+ 9
+ 10
+ test
+
+ 8
+
+ On
+ Tells if the pin is on (voltage over trigger threshold) or not.
+
+
+
+ 8
+
+ Voltage
+ This is the voltage level in mV.
+ 11
+ 0
+ 1100
+
+
+
Weather
@@ -491,5 +520,64 @@
100
+
+ Color
+ This is to set a fixed color.
+ 10
+ 0
+ 1
+ 2
+ 8
+ 9
+ 10
+ test
+
+ Color
+ The color is according to the 6 bit color palette used in SHC.
+ 6
+ 0
+ 63
+
+
+
+ ColorAnimation
+ This is to set a color animation.
+ 11
+ 0
+ 1
+ 2
+ 8
+ 9
+ 10
+ test
+
+ Repeat
+ The number of times the animation will be repeated. 0 means infinitely.
+ 4
+ 0
+ 15
+
+
+ AutoReverse
+ If true, the animation will be played back in the normal direction and then in reverse order.
+
+
+ 10
+
+ Time
+ The time for the animation between the current color and the next one. The number of seconds used is 0.05 * 1.3 ^ Time and covers the range from 0.03s to 170s. Use 0 to mark the end of the animation. Further values will be ignored.
+ 5
+ 0
+ 31
+
+
+ Color
+ The color is according to the 6 bit color palette used in SHC. The last color (or the first when AutoReverse is true) of the animation will remain visible after the animation is completed.
+ 6
+ 0
+ 63
+
+
+
diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt
index fc849d443..7c2e7aa30 100644
--- a/fhem/MAINTAINER.txt
+++ b/fhem/MAINTAINER.txt
@@ -260,8 +260,11 @@ FHEM/HttpUtils.pm rudolfkoenig http://forum.fhem.de Automatis
FHEM/MaxCommon.pm mgehre http://forum.fhem.de MAX
FHEM/ONKYOdb.pm loredo http://forum.fhem.de Multimedia
FHEM/SetExtensions.pm rudolfkoenig http://forum.fhem.de Automatisierung
+FHEM/SHC_datafields.pm rr2000 http://forum.fhem.de Sonstige Systeme
+FHEM/SHC_parser.pm rr2000 http://forum.fhem.de Sonstige Systeme
FHEM/TcpServerUtils.pm rudolfkoenig http://forum.fhem.de Automatisierung
FHEM/lib/Device/Firmata/* ntruchsess http://forum.fhem.de Sonstiges
+FHEM/lib/SHC_packet_layout.xml rr2000 http://forum.fhem.de Sonstige Systeme
FHEM/lib/SWAP/* justme1968 http://forum.fhem.de Sonstige Systeme
FHEM/FhemUtils/* mfr69bs http://forum.fhem.de Sonstiges