mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
SHC: add support for analog inputs (EnvSensor) and new device RGB_Dimmer
git-svn-id: https://svn.fhem.de/fhem/trunk@6580 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
7d86d6c032
commit
8e5254396b
@ -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: SHC: support for analog inputs (EnvSensor) and new device
|
||||||
|
RGB_Dimmer added (rr2000)
|
||||||
- feature: PRESENCE: MAC address support for mode fritzbox (by Markus M.)
|
- feature: PRESENCE: MAC address support for mode fritzbox (by Markus M.)
|
||||||
- bugfix: PRESENCE: fixing presence detection in mode fritzbox with new
|
- bugfix: PRESENCE: fixing presence detection in mode fritzbox with new
|
||||||
Fritz!OS 6.20 (by Markus M.)
|
Fritz!OS 6.20 (by Markus M.)
|
||||||
|
@ -35,13 +35,15 @@ my $parser = new SHC_parser();
|
|||||||
my %dev_state_icons = (
|
my %dev_state_icons = (
|
||||||
"PowerSwitch" => "on:on:toggle off:off:toggle set.*:light_question:off",
|
"PowerSwitch" => "on:on:toggle off:off:toggle set.*:light_question:off",
|
||||||
"Dimmer" => "on:on off:off set.*:light_question:off",
|
"Dimmer" => "on:on off:off set.*:light_question:off",
|
||||||
"EnvSensor" => undef
|
"EnvSensor" => undef,
|
||||||
|
"RGB_Dimmer" => undef
|
||||||
);
|
);
|
||||||
|
|
||||||
my %web_cmds = (
|
my %web_cmds = (
|
||||||
"PowerSwitch" => "on:off:toggle:statusRequest",
|
"PowerSwitch" => "on:off:toggle:statusRequest",
|
||||||
"Dimmer" => "on:off:statusRequest",
|
"Dimmer" => "on:off:statusRequest",
|
||||||
"EnvSensor" => undef
|
"EnvSensor" => undef,
|
||||||
|
"RGB_Dimmer" => undef
|
||||||
);
|
);
|
||||||
|
|
||||||
# Array format: [ reading1, str_format1, reading2, str_format2 ... ]
|
# Array format: [ reading1, str_format1, reading2, str_format2 ... ]
|
||||||
@ -55,7 +57,12 @@ my %dev_state_format = (
|
|||||||
"humidity", "H: ",
|
"humidity", "H: ",
|
||||||
"barometric_pressure", "Baro: ",
|
"barometric_pressure", "Baro: ",
|
||||||
"brightness", "B: ",
|
"brightness", "B: ",
|
||||||
"distance", "D: "
|
"distance", "D: ",
|
||||||
|
"dins", "Din: ",
|
||||||
|
"ains", "Ain: "
|
||||||
|
],
|
||||||
|
"RGB_Dimmer" => [
|
||||||
|
"color", "Color: "
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -71,6 +78,8 @@ my %sets = (
|
|||||||
# Used from SetExtensions.pm
|
# Used from SetExtensions.pm
|
||||||
"blink on-for-timer on-till off-for-timer off-till intervals",
|
"blink on-for-timer on-till off-for-timer off-till intervals",
|
||||||
"EnvSensor" => "",
|
"EnvSensor" => "",
|
||||||
|
"RGB_Dimmer" => "Color " .
|
||||||
|
"ColorAnimation",
|
||||||
"Custom" => "PowerSwitch.SwitchState " .
|
"Custom" => "PowerSwitch.SwitchState " .
|
||||||
"PowerSwitch.SwitchStateExt " .
|
"PowerSwitch.SwitchStateExt " .
|
||||||
"Dimmer.Brightness " .
|
"Dimmer.Brightness " .
|
||||||
@ -82,7 +91,8 @@ my %sets = (
|
|||||||
my %gets = (
|
my %gets = (
|
||||||
"PowerSwitch" => "",
|
"PowerSwitch" => "",
|
||||||
"Dimmer" => "",
|
"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" => ""
|
"Custom" => ""
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -96,8 +106,11 @@ my %auto_devtype = (
|
|||||||
"Environment.Brightness" => "EnvSensor",
|
"Environment.Brightness" => "EnvSensor",
|
||||||
"Environment.Distance" => "EnvSensor",
|
"Environment.Distance" => "EnvSensor",
|
||||||
"GPIO.DigitalPin" => "EnvSensor",
|
"GPIO.DigitalPin" => "EnvSensor",
|
||||||
|
"GPIO.AnalogPin" => "EnvSensor",
|
||||||
"PowerSwitch.SwitchState" => "PowerSwitch",
|
"PowerSwitch.SwitchState" => "PowerSwitch",
|
||||||
"Dimmer.Brightness" => "Dimmer"
|
"Dimmer.Brightness" => "Dimmer",
|
||||||
|
"Dimmer.Color" => "RGB_Dimmer",
|
||||||
|
"Dimmer.ColorAnimation" => "RGB_Dimmer"
|
||||||
);
|
);
|
||||||
|
|
||||||
sub SHCdev_Parse($$);
|
sub SHCdev_Parse($$);
|
||||||
@ -117,7 +130,7 @@ sub SHCdev_Initialize($)
|
|||||||
." readonly:1"
|
." readonly:1"
|
||||||
." forceOn:1"
|
." forceOn:1"
|
||||||
." $readingFnAttributes"
|
." $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++) {
|
for (my $i = 0 ; $i < 8 ; $i++) {
|
||||||
my $pinx = $parser->getField("On", $i);
|
my $pinx = $parser->getField("On", $i);
|
||||||
my $channel = $i + 1;
|
my $channel = $i + 1;
|
||||||
readingsBulkUpdate($rhash, "pin" . $channel, $pinx);
|
readingsBulkUpdate($rhash, "din" . $channel, $pinx);
|
||||||
$pins .= $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, "on", $on);
|
||||||
readingsBulkUpdate($rhash, "brightness", $brightness);
|
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);
|
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;
|
return undef;
|
||||||
@ -505,9 +593,9 @@ sub SHCdev_Get($@)
|
|||||||
|
|
||||||
given ($devtype) {
|
given ($devtype) {
|
||||||
when ('EnvSensor') {
|
when ('EnvSensor') {
|
||||||
if ($cmd eq 'input') {
|
if ($cmd eq 'din') {
|
||||||
if ($arg =~ /[1-8]/) {
|
if ($arg =~ /[1-8]/) {
|
||||||
my $channel = "pin" . $arg;
|
my $channel = "din" . $arg;
|
||||||
if ( defined($hash->{READINGS}{$channel})
|
if ( defined($hash->{READINGS}{$channel})
|
||||||
&& defined($hash->{READINGS}{$channel}{VAL}))
|
&& defined($hash->{READINGS}{$channel}{VAL}))
|
||||||
{
|
{
|
||||||
@ -517,14 +605,45 @@ sub SHCdev_Get($@)
|
|||||||
}
|
}
|
||||||
elsif ($arg eq "all")
|
elsif ($arg eq "all")
|
||||||
{
|
{
|
||||||
if ( defined($hash->{READINGS}{pins})
|
if ( defined($hash->{READINGS}{dins})
|
||||||
&& defined($hash->{READINGS}{pins}{VAL}))
|
&& 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";
|
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
|
# This return is required to provide the get commands in the web interface
|
||||||
return "Unknown argument $cmd, choose one of " . $gets{$devtype};
|
return "Unknown argument $cmd, choose one of " . $gets{$devtype};
|
||||||
@ -603,6 +722,16 @@ sub SHCdev_Send($)
|
|||||||
<li>statusRequest<br>
|
<li>statusRequest<br>
|
||||||
Supported by Dimmer and PowerSwitch.
|
Supported by Dimmer and PowerSwitch.
|
||||||
</li><br>
|
</li><br>
|
||||||
|
<li>Color <ColorNumber><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.
|
||||||
|
</li><br>
|
||||||
|
<li>ColorAnimation <Repeat> <AutoReverse> <Time0> <ColorNumber0> <Time1> <ColorNumber1> ... 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.
|
||||||
|
</li><br>
|
||||||
<li><a href="#setExtensions"> set extensions</a><br>
|
<li><a href="#setExtensions"> set extensions</a><br>
|
||||||
Supported by Dimmer and PowerSwitch.</li>
|
Supported by Dimmer and PowerSwitch.</li>
|
||||||
</ul><br>
|
</ul><br>
|
||||||
@ -610,8 +739,22 @@ sub SHCdev_Send($)
|
|||||||
<a name="SHCdev_Get"></a>
|
<a name="SHCdev_Get"></a>
|
||||||
<b>Get</b>
|
<b>Get</b>
|
||||||
<ul>
|
<ul>
|
||||||
<li>input <pin><br>
|
<li>din <pin><br>
|
||||||
Returns the state of the specified pin for pin = 1..8 or the state of all pins for pin = all.
|
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.
|
||||||
|
</li><br>
|
||||||
|
<li>ain <pin><br>
|
||||||
|
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.
|
||||||
|
</li><br>
|
||||||
|
<li>ain <pin><br>
|
||||||
|
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.
|
||||||
|
</li><br>
|
||||||
|
<li>ain_volt <pin><br>
|
||||||
|
Returns the voltage of the specified analog input pin for pin = 1..5 in millivolts, ranging from 0 .. 1100 mV.
|
||||||
Supported by EnvSensor.
|
Supported by EnvSensor.
|
||||||
</li><br>
|
</li><br>
|
||||||
</ul><br>
|
</ul><br>
|
||||||
@ -621,7 +764,7 @@ sub SHCdev_Send($)
|
|||||||
<ul>
|
<ul>
|
||||||
<li>devtype<br>
|
<li>devtype<br>
|
||||||
The device type determines the command set, default web commands and the
|
The device type determines the command set, default web commands and the
|
||||||
default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch.<br><br>
|
default devStateicon. Currently supported are: EnvSensor, Dimmer, PowerSwitch, RGB_Dimmer.<br><br>
|
||||||
|
|
||||||
Note: If the device is not set manually, it will be determined automatically
|
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
|
on reception of a device type specific message. For example: If a
|
||||||
|
@ -97,6 +97,7 @@ sub setUIntBits($$$$$)
|
|||||||
# if length is smaller than 8 bits, get the old value from array
|
# if length is smaller than 8 bits, get the old value from array
|
||||||
if ($length_bits < 8) {
|
if ($length_bits < 8) {
|
||||||
$b = @$byteArrayRef[$byte];
|
$b = @$byteArrayRef[$byte];
|
||||||
|
|
||||||
$b = clear_bits($b, $bit, $length_bits);
|
$b = clear_bits($b, $bit, $length_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ sub setUInt($$$$)
|
|||||||
{
|
{
|
||||||
my ($byteArrayRef, $offset, $length_bits, $value) = @_;
|
my ($byteArrayRef, $offset, $length_bits, $value) = @_;
|
||||||
|
|
||||||
my $byte = $offset / 8;
|
my $byte = int($offset / 8);
|
||||||
my $bit = $offset % 8;
|
my $bit = $offset % 8;
|
||||||
|
|
||||||
# move bits to the left border
|
# move bits to the left border
|
||||||
@ -125,7 +126,7 @@ sub setUInt($$$$)
|
|||||||
my $len = min($length_bits, 8 - $bit);
|
my $len = min($length_bits, 8 - $bit);
|
||||||
my $val8 = get_bits($value, $src_start, $len);
|
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);
|
setUIntBits($byteArrayRef, $byte, $dst_start, $len, $val8);
|
||||||
|
|
||||||
@ -137,7 +138,7 @@ sub setUInt($$$$)
|
|||||||
$val8 = get_bits($value, $src_start, $len);
|
$val8 = get_bits($value, $src_start, $len);
|
||||||
$byte++;
|
$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);
|
setUIntBits($byteArrayRef, $byte, $dst_start, $len, $val8);
|
||||||
|
|
||||||
@ -175,6 +176,8 @@ sub new
|
|||||||
_id => shift,
|
_id => shift,
|
||||||
_offset => shift,
|
_offset => shift,
|
||||||
_bits => shift,
|
_bits => shift,
|
||||||
|
_length => shift,
|
||||||
|
_arrayElementBits => shift
|
||||||
};
|
};
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
return $self;
|
return $self;
|
||||||
@ -182,16 +185,16 @@ sub new
|
|||||||
|
|
||||||
sub getValue
|
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
|
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 -----------
|
# ----------- IntValue class -----------
|
||||||
@ -205,6 +208,8 @@ sub new
|
|||||||
_id => shift,
|
_id => shift,
|
||||||
_offset => shift,
|
_offset => shift,
|
||||||
_bits => shift,
|
_bits => shift,
|
||||||
|
_length => shift,
|
||||||
|
_arrayElementBits => shift
|
||||||
};
|
};
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
return $self;
|
return $self;
|
||||||
@ -212,16 +217,16 @@ sub new
|
|||||||
|
|
||||||
sub getValue
|
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
|
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 -----------
|
# ----------- BoolValue class -----------
|
||||||
@ -235,6 +240,7 @@ sub new
|
|||||||
_id => shift,
|
_id => shift,
|
||||||
_offset => shift,
|
_offset => shift,
|
||||||
_length => shift,
|
_length => shift,
|
||||||
|
_arrayElementBits => shift
|
||||||
};
|
};
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
return $self;
|
return $self;
|
||||||
@ -244,14 +250,15 @@ sub getValue
|
|||||||
{
|
{
|
||||||
my ($self, $byteArrayRef, $index) = @_;
|
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
|
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 -----------
|
# ----------- EnumValue class -----------
|
||||||
@ -268,6 +275,8 @@ sub new
|
|||||||
_id => shift,
|
_id => shift,
|
||||||
_offset => shift,
|
_offset => shift,
|
||||||
_bits => shift,
|
_bits => shift,
|
||||||
|
_length => shift,
|
||||||
|
_arrayElementBits => shift
|
||||||
};
|
};
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
return $self;
|
return $self;
|
||||||
@ -283,18 +292,18 @@ sub addValue
|
|||||||
|
|
||||||
sub getValue
|
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};
|
return $value2name{$value};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setValue
|
sub setValue
|
||||||
{
|
{
|
||||||
my ($self, $byteArrayRef, $name) = @_;
|
my ($self, $byteArrayRef, $name, $index) = @_;
|
||||||
|
|
||||||
my $value = $name2value{$name};
|
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;
|
1;
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
# $parser->parse("Packet Data: SenderID=22;...");
|
# $parser->parse("Packet Data: SenderID=22;...");
|
||||||
# 3.) Get MessageGroupName: my $grp = $parser->getMessageGroupName();
|
# 3.) Get MessageGroupName: my $grp = $parser->getMessageGroupName();
|
||||||
# 4.) Get MessageName: my $msg = $parser->getMessageName();
|
# 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");
|
# $val = $parser->getField("Temperature");
|
||||||
#
|
#
|
||||||
# Sending packets:
|
# Sending packets:
|
||||||
@ -74,6 +74,8 @@ my %messageID2bits = ();
|
|||||||
my @msgData = ();
|
my @msgData = ();
|
||||||
my $sendMode = 0;
|
my $sendMode = 0;
|
||||||
|
|
||||||
|
my $offset = 0;
|
||||||
|
|
||||||
sub new
|
sub new
|
||||||
{
|
{
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
@ -92,6 +94,104 @@ sub new
|
|||||||
return $self;
|
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,
|
# Read packet layout from XML file and remember the defined MessageGroups,
|
||||||
# Messages and data fields (incl. positions, length).
|
# Messages and data fields (incl. positions, length).
|
||||||
sub init_datafield_positions()
|
sub init_datafield_positions()
|
||||||
@ -121,75 +221,21 @@ sub init_datafield_positions()
|
|||||||
$messageID2messageName{$messageGroupID . "-" . $messageID} = $messageName;
|
$messageID2messageName{$messageGroupID . "-" . $messageID} = $messageName;
|
||||||
$messageName2messageID{$messageGroupName . "-" . $messageName} = $messageID;
|
$messageName2messageID{$messageGroupName . "-" . $messageName} = $messageID;
|
||||||
|
|
||||||
my $offset = 0;
|
$offset = 0;
|
||||||
my $arrayLength = 1;
|
|
||||||
|
|
||||||
for my $field ($message->findnodes("Array|UIntValue|IntValue|BoolValue|EnumValue")) {
|
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
|
# When an array is detected, remember the array length and change the current field node
|
||||||
# to the inner node for further processing.
|
# to the inner node for further processing.
|
||||||
if ($field->nodeName eq 'Array') {
|
if ($field->nodeName eq 'Array') {
|
||||||
$arrayLength = int(($field->findnodes("Length"))[0]->textContent);
|
init_datafield_positions_array($messageGroupID, $messageID, $field);
|
||||||
# DEBUG print "Next field is an array with " . $arrayLength . " elements!\n";
|
} else {
|
||||||
|
init_datafield_positions_noarray($messageGroupID, $messageID, $field, 1, 0);
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# DEBUG print "Remember packet length " . $offset . " bits for MessageGroupID " . $messageGroupID . ", MessageID " . $messageID . "\n";
|
||||||
|
|
||||||
$messageID2bits{$messageGroupID . "-" . $messageID} = $offset;
|
$messageID2bits{$messageGroupID . "-" . $messageID} = $offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,8 +321,14 @@ sub getField
|
|||||||
{
|
{
|
||||||
my ($self, $fieldName, $index) = @_;
|
my ($self, $fieldName, $index) = @_;
|
||||||
|
|
||||||
|
if (!defined $index) {
|
||||||
|
$index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
my $obj = $dataFields{$self->{_messageGroupID} . "-" . $self->{_messageID} . "-" . $fieldName};
|
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);
|
return $obj->getValue(\@tmpArray, $index);
|
||||||
}
|
}
|
||||||
@ -290,23 +342,27 @@ sub initPacket
|
|||||||
$self->{_messageGroupID} = $messageGroupName2messageGroupID{$messageGroupName};
|
$self->{_messageGroupID} = $messageGroupName2messageGroupID{$messageGroupName};
|
||||||
$self->{_messageID} = $messageName2messageID{$messageGroupName . "-" . $messageName};
|
$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;
|
$sendMode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setField
|
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 $gID = $messageGroupName2messageGroupID{$messageGroupName};
|
||||||
my $mID = $messageName2messageID{$messageGroupName . "-" . $messageName};
|
my $mID = $messageName2messageID{$messageGroupName . "-" . $messageName};
|
||||||
|
|
||||||
my $obj = $dataFields{$gID . "-" . $mID . "-" . $fieldName};
|
my $obj = $dataFields{$gID . "-" . $mID . "-" . $fieldName};
|
||||||
|
|
||||||
$obj->setValue(\@msgData, $value);
|
$obj->setValue(\@msgData, $value, $index);
|
||||||
}
|
}
|
||||||
|
|
||||||
# sKK01RRRRGGMMDD
|
# sKK01RRRRGGMMDD
|
||||||
@ -322,6 +378,10 @@ sub getSendString
|
|||||||
# Add lookup table device -> AES key?
|
# Add lookup table device -> AES key?
|
||||||
# Automatically gather used AES key after reception from device?
|
# Automatically gather used AES key after reception from device?
|
||||||
|
|
||||||
|
if (!defined $aesKeyNr) {
|
||||||
|
$aesKeyNr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
my $s = "s"
|
my $s = "s"
|
||||||
. sprintf("%02X", $aesKeyNr)
|
. sprintf("%02X", $aesKeyNr)
|
||||||
. sprintf("%02X", $self->{_messageTypeID})
|
. sprintf("%02X", $self->{_messageTypeID})
|
||||||
|
@ -260,6 +260,35 @@
|
|||||||
</BoolValue>
|
</BoolValue>
|
||||||
</Array>
|
</Array>
|
||||||
</Message>
|
</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>
|
||||||
|
<MessageID>2</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>
|
||||||
|
<Bits>11</Bits>
|
||||||
|
<MinVal>0</MinVal>
|
||||||
|
<MaxVal>1100</MaxVal>
|
||||||
|
</UIntValue>
|
||||||
|
</Array>
|
||||||
|
</Message>
|
||||||
</MessageGroup>
|
</MessageGroup>
|
||||||
<MessageGroup>
|
<MessageGroup>
|
||||||
<Name>Weather</Name>
|
<Name>Weather</Name>
|
||||||
@ -491,5 +520,64 @@
|
|||||||
<MaxVal>100</MaxVal>
|
<MaxVal>100</MaxVal>
|
||||||
</UIntValue>
|
</UIntValue>
|
||||||
</Message>
|
</Message>
|
||||||
|
<Message>
|
||||||
|
<Name>Color</Name>
|
||||||
|
<Description>This is to set a fixed color.</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>
|
||||||
|
<UIntValue>
|
||||||
|
<ID>Color</ID>
|
||||||
|
<Description>The color is according to the 6 bit color palette used in SHC.</Description>
|
||||||
|
<Bits>6</Bits>
|
||||||
|
<MinVal>0</MinVal>
|
||||||
|
<MaxVal>63</MaxVal>
|
||||||
|
</UIntValue>
|
||||||
|
</Message>
|
||||||
|
<Message>
|
||||||
|
<Name>ColorAnimation</Name>
|
||||||
|
<Description>This is to set a color animation.</Description>
|
||||||
|
<MessageID>11</MessageID>
|
||||||
|
<MessageType>0</MessageType>
|
||||||
|
<MessageType>1</MessageType>
|
||||||
|
<MessageType>2</MessageType>
|
||||||
|
<MessageType>8</MessageType>
|
||||||
|
<MessageType>9</MessageType>
|
||||||
|
<MessageType>10</MessageType>
|
||||||
|
<Validity>test</Validity>
|
||||||
|
<UIntValue>
|
||||||
|
<ID>Repeat</ID>
|
||||||
|
<Description>The number of times the animation will be repeated. 0 means infinitely.</Description>
|
||||||
|
<Bits>4</Bits>
|
||||||
|
<MinVal>0</MinVal>
|
||||||
|
<MaxVal>15</MaxVal>
|
||||||
|
</UIntValue>
|
||||||
|
<BoolValue>
|
||||||
|
<ID>AutoReverse</ID>
|
||||||
|
<Description>If true, the animation will be played back in the normal direction and then in reverse order.</Description>
|
||||||
|
</BoolValue>
|
||||||
|
<Array>
|
||||||
|
<Length>10</Length>
|
||||||
|
<UIntValue>
|
||||||
|
<ID>Time</ID>
|
||||||
|
<Description>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.</Description>
|
||||||
|
<Bits>5</Bits>
|
||||||
|
<MinVal>0</MinVal>
|
||||||
|
<MaxVal>31</MaxVal>
|
||||||
|
</UIntValue>
|
||||||
|
<UIntValue>
|
||||||
|
<ID>Color</ID>
|
||||||
|
<Description>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.</Description>
|
||||||
|
<Bits>6</Bits>
|
||||||
|
<MinVal>0</MinVal>
|
||||||
|
<MaxVal>63</MaxVal>
|
||||||
|
</UIntValue>
|
||||||
|
</Array>
|
||||||
|
</Message>
|
||||||
</MessageGroup>
|
</MessageGroup>
|
||||||
</Packet>
|
</Packet>
|
||||||
|
@ -260,8 +260,11 @@ FHEM/HttpUtils.pm rudolfkoenig http://forum.fhem.de Automatis
|
|||||||
FHEM/MaxCommon.pm mgehre http://forum.fhem.de MAX
|
FHEM/MaxCommon.pm mgehre http://forum.fhem.de MAX
|
||||||
FHEM/ONKYOdb.pm loredo http://forum.fhem.de Multimedia
|
FHEM/ONKYOdb.pm loredo http://forum.fhem.de Multimedia
|
||||||
FHEM/SetExtensions.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
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/TcpServerUtils.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||||
FHEM/lib/Device/Firmata/* ntruchsess http://forum.fhem.de Sonstiges
|
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/lib/SWAP/* justme1968 http://forum.fhem.de Sonstige Systeme
|
||||||
FHEM/FhemUtils/* mfr69bs http://forum.fhem.de Sonstiges
|
FHEM/FhemUtils/* mfr69bs http://forum.fhem.de Sonstiges
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user