2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-22 02:10:32 +00:00

00_TCM: commandref changed

10_EnOcean: SmartAck added, new profile roomCtrlPanel.01 (D2-11-01 - D2-11-08)

git-svn-id: https://svn.fhem.de/fhem/trunk@11251 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klaus-schauer 2016-04-16 17:33:33 +00:00
parent 86abfa4ac9
commit 877063fdd9
2 changed files with 102 additions and 59 deletions

View File

@ -1,6 +1,6 @@
############################################## ##############################################
# $Id$ # $Id$
# 2016-03-28 # 2016-04-12
# by r.koenig at koeniglich.de # by r.koenig at koeniglich.de
# #
@ -523,7 +523,7 @@ TCM_Parse310($$$)
{ {
my ($hash,$rawmsg,$ptr) = @_; my ($hash,$rawmsg,$ptr) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
Log3 $name, 5, "TCM Parse $rawmsg"; Log3 $name, 5, "TCM_Parse $rawmsg";
my $rc = substr($rawmsg, 0, 2); my $rc = substr($rawmsg, 0, 2);
my $msg = ""; my $msg = "";
if($rc ne "00") { if($rc ne "00") {
@ -552,7 +552,7 @@ TCM_Parse310($$$)
$part1 = $part1 * 2; $part1 = $part1 * 2;
$part2 = $part2 * 2; $part2 = $part2 * 2;
$part3 = $part3 * 2; $part3 = $part3 * 2;
my $dataLen = length($data) / 2; my $dataLen = length($data);
my $dataOut = ''; my $dataOut = '';
while ($dataLen > 0) { while ($dataLen > 0) {
$data =~ m/^(.{$part1})(.{$part2})(.{$part3})(.*)$/; $data =~ m/^(.{$part1})(.{$part2})(.{$part3})(.*)$/;
@ -560,7 +560,8 @@ TCM_Parse310($$$)
$data = $4; $data = $4;
$dataLen -= $part1 + $part2 + $part3; $dataLen -= $part1 + $part2 + $part3;
} }
$data = chop($dataOut); chop($dataOut);
$data = $dataOut;
} }
} }
push @ans, "$k: $data"; push @ans, "$k: $data";
@ -1182,9 +1183,14 @@ TCM_Undef($$)
mode = 01: Advanced mode - ERP2 - gateway uses Packet Type 10 to transmit and receive radio telegrams mode = 01: Advanced mode - ERP2 - gateway uses Packet Type 10 to transmit and receive radio telegrams
(for FSK products with advanced protocol)</li> (for FSK products with advanced protocol)</li>
<li>smartAckLearn &lt;t/s&gt;<br> <li>smartAckLearn &lt;t/s&gt;<br>
Set Fhem in Smart Ack learning mode.</li> Set Fhem in Smart Ack learning mode.<br>
The post master fuctionality must be activated using the command <code>smartAckMailboxMax</code> in advance.<br>
The simple learnmode is supported, see <a href="#TCM_smartAckLearnMode">smartAckLearnMode</a><br>
A device, which is then also put in this state is to paired with
Fhem. Bidirectional learn in for 4BS, UTE and Generic Profiles are supported.<br>
<code>t/s</code> is the time for the learning period.</li>
<li>smartAckMailboxMax 0..20<br> <li>smartAckMailboxMax 0..20<br>
Set amount of mailboxes available, 0 = disable post master functionality. Enable the post master fuctionality and set amount of mailboxes available, 0 = disable post master functionality.
Maximum 28 mailboxes can be created. This upper limit is for each firmware restricted and may be smaller.</li> Maximum 28 mailboxes can be created. This upper limit is for each firmware restricted and may be smaller.</li>
<li>teach &lt;t/s&gt;<br> <li>teach &lt;t/s&gt;<br>
Set Fhem in learning mode for RBS, 1BS, 4BS, GP, STE and UTE teach-in / teach-out, see <a href="#TCM_learningMode">learningMode</a>.<br> Set Fhem in learning mode for RBS, 1BS, 4BS, GP, STE and UTE teach-in / teach-out, see <a href="#TCM_learningMode">learningMode</a>.<br>

View File

@ -1,7 +1,7 @@
############################################## ##############################################
# $Id$ # $Id$
# 2016-04-07 # 2016-04-16
# PID V1.0.0.9 # PID V1.0.0.9
# EnOcean Security in Perl, teach-in, VAES, MAC and message handling # EnOcean Security in Perl, teach-in, VAES, MAC and message handling
@ -318,14 +318,14 @@ my %EnO_eepConfig = (
"D2.10.00" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.00" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.10.01" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.01" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.10.02" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.02" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.01" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.01" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.02" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.02" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.03" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.03" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.04" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.04" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.05" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.05" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.06" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.06" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.07" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.07" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.11.08" => {attr => {subType => "roomCtrlPanel.01", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.11.08" => {attr => {subType => "roomCtrlPanel.01", comMode => "biDir", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.20.00" => {attr => {subType => "fanCtrl.00", webCmd => "fanSpeed"}, GPLOT => "EnO_fanSpeed4humi4:FanSpeed/Humi,"}, "D2.20.00" => {attr => {subType => "fanCtrl.00", webCmd => "fanSpeed"}, GPLOT => "EnO_fanSpeed4humi4:FanSpeed/Humi,"},
"D2.32.00" => {attr => {subType => "currentClamp.00"}, GPLOT => "EnO_D2-32-xx:Current,"}, "D2.32.00" => {attr => {subType => "currentClamp.00"}, GPLOT => "EnO_D2-32-xx:Current,"},
"D2.32.01" => {attr => {subType => "currentClamp.01"}, GPLOT => "EnO_D2-32-xx:Current,"}, "D2.32.01" => {attr => {subType => "currentClamp.01"}, GPLOT => "EnO_D2-32-xx:Current,"},
@ -852,6 +852,8 @@ sub EnOcean_Define($$) {
readingsSingleUpdate($hash, "teach", "GP teach-in is missing", 1); readingsSingleUpdate($hash, "teach", "GP teach-in is missing", 1);
Log3 $name, 2, "EnOcean $name GP teach-in is missing"; Log3 $name, 2, "EnOcean $name GP teach-in is missing";
} }
} elsif ($packetType == 4) {
$hash->{helper}{smartAckLearnWait} = $name;
} }
EnOcean_Parse($hash, $a[3]); EnOcean_Parse($hash, $a[3]);
if (exists $attr{$name}{eep}) { if (exists $attr{$name}{eep}) {
@ -4712,6 +4714,7 @@ sub EnOcean_Set($@)
my $setpointShiftMax = ReadingsVal($name, "setpointShiftMax", 10); my $setpointShiftMax = ReadingsVal($name, "setpointShiftMax", 10);
my $setpointType = ReadingsVal($name, "setpointType", 'setpointShift'); my $setpointType = ReadingsVal($name, "setpointType", 'setpointShift');
my $temperature = ReadingsVal($name, "temperature", 20); my $temperature = ReadingsVal($name, "temperature", 20);
my $waitingCmds = ReadingsVal($name, "waitingCmds", 0);
my $window = ReadingsVal($name, "window", 'closed'); my $window = ReadingsVal($name, "window", 'closed');
if ($cmd eq "desired-temp"|| $cmd eq "setpointTemp") { if ($cmd eq "desired-temp"|| $cmd eq "setpointTemp") {
if (defined $a[1]) { if (defined $a[1]) {
@ -4736,7 +4739,9 @@ sub EnOcean_Set($@)
$setpointTemp = $a[1]; $setpointTemp = $a[1];
readingsBulkUpdate($hash, "setpointTemp", $a[1]); readingsBulkUpdate($hash, "setpointTemp", $a[1]);
readingsBulkUpdate($hash, "state", "T: $temperature H: $humidity SPT: $setpointTemp F: $fanSpeed"); readingsBulkUpdate($hash, "state", "T: $temperature H: $humidity SPT: $setpointTemp F: $fanSpeed");
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 1);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name setpointTemp $a[1]"; Log3 $name, 3, "EnOcean set $name setpointTemp $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4758,7 +4763,9 @@ sub EnOcean_Set($@)
$setpointShiftMax = $a[1]; $setpointShiftMax = $a[1];
} }
readingsBulkUpdate($hash, "setpointShiftMax", $setpointShiftMax); readingsBulkUpdate($hash, "setpointShiftMax", $setpointShiftMax);
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 2);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name setpointShiftMax $a[1]"; Log3 $name, 3, "EnOcean set $name setpointShiftMax $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4774,7 +4781,9 @@ sub EnOcean_Set($@)
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
$setpointType = $a[1]; $setpointType = $a[1];
readingsBulkUpdate($hash, "setpointType", $setpointType); readingsBulkUpdate($hash, "setpointType", $setpointType);
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 0x80);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name setpointType $a[1]"; Log3 $name, 3, "EnOcean set $name setpointType $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4791,7 +4800,9 @@ sub EnOcean_Set($@)
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "fanSpeed", $a[1]); readingsBulkUpdate($hash, "fanSpeed", $a[1]);
readingsBulkUpdate($hash, "state", "T: $temperature H: $humidity SPT: $setpointTemp F: $fanSpeed"); readingsBulkUpdate($hash, "state", "T: $temperature H: $humidity SPT: $setpointTemp F: $fanSpeed");
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 4);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name fanSpeed $a[1]"; Log3 $name, 3, "EnOcean set $name fanSpeed $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4811,7 +4822,9 @@ sub EnOcean_Set($@)
$heating = 'off'; $heating = 'off';
readingsBulkUpdate($hash, "heating", 'off'); readingsBulkUpdate($hash, "heating", 'off');
} }
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 0x20);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name cooling $a[1]"; Log3 $name, 3, "EnOcean set $name cooling $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4831,7 +4844,9 @@ sub EnOcean_Set($@)
$cooling = 'off'; $cooling = 'off';
readingsBulkUpdate($hash, "cooling", 'off'); readingsBulkUpdate($hash, "cooling", 'off');
} }
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 0x40);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name heating $a[1]"; Log3 $name, 3, "EnOcean set $name heating $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4847,7 +4862,9 @@ sub EnOcean_Set($@)
$occupancy = $a[1]; $occupancy = $a[1];
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "occupancy", $a[1]); readingsBulkUpdate($hash, "occupancy", $a[1]);
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 8);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name occupancy $a[1]"; Log3 $name, 3, "EnOcean set $name occupancy $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4863,7 +4880,9 @@ sub EnOcean_Set($@)
$window = $a[1]; $window = $a[1];
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "window", $a[1]); readingsBulkUpdate($hash, "window", $a[1]);
readingsBulkUpdate($hash, "waitingCmds", $waitingCmds |= 0x10);
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
CommandDeleteReading(undef, "$name smartAckMailbox");
Log3 $name, 3, "EnOcean set $name window $a[1]"; Log3 $name, 3, "EnOcean set $name window $a[1]";
shift(@a); shift(@a);
} else { } else {
@ -4883,7 +4902,8 @@ sub EnOcean_Set($@)
$heating = $heating eq 'on' ? 0x40 : 0; $heating = $heating eq 'on' ? 0x40 : 0;
$cooling = $cooling eq 'on' ? 0x20 : 0; $cooling = $cooling eq 'on' ? 0x20 : 0;
$window = $window eq 'open' ? 0x10 : 0; $window = $window eq 'open' ? 0x10 : 0;
$setpointShift = unpack('C', pack('c', $setpointShift)); $setpointShift = int(($setpointShift + $setpointShiftMax) * 255 / ($setpointShiftMax * 2));
#$setpointShift = unpack('C', pack('c', $setpointShift));
my %fanSpeed = ('auto' => 0, 'off' =>1, 1 => 2, 2 => 3, 3 => 4); my %fanSpeed = ('auto' => 0, 'off' =>1, 1 => 2, 2 => 3, 3 => 4);
$occupancy = $occupancy eq 'occupied' ? 1 : 0; $occupancy = $occupancy eq 'occupied' ? 1 : 0;
$data = sprintf "%02X%02X%02X%02X", $setpointType |$heating | $cooling | $window | 1, $data = sprintf "%02X%02X%02X%02X", $setpointType |$heating | $cooling | $window | 1,
@ -5652,10 +5672,10 @@ sub EnOcean_Set($@)
readingsSingleUpdate($hash, "state", $cmd, 1); readingsSingleUpdate($hash, "state", $cmd, 1);
} elsif ($updateState == 0 && $updateStateAttr eq "yes") { } elsif ($updateState == 0 && $updateStateAttr eq "yes") {
readingsSingleUpdate($hash, "state", $cmd, 1); readingsSingleUpdate($hash, "state", $cmd, 1);
} elsif ($updateState == 3) { #} elsif ($updateState == 3) {
#internal command #internal command
} else { #} else {
readingsSingleUpdate($hash, ".info", "await_confirm", 0); # readingsSingleUpdate($hash, ".info", "await_confirm", 0);
} }
# send commands # send commands
@ -5837,10 +5857,10 @@ sub EnOcean_Parse($$)
return $ret; return $ret;
} }
} elsif ($learningMode eq "demand" && ($iohash->{Teach} || $iohash->{SmartAckLearn})) { } elsif ($learningMode eq "demand" && $iohash->{Teach}) {
Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and $rorgname telegram, please define it."; Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and $rorgname telegram, please define it.";
return $ret; return $ret;
} elsif ($learningMode eq "nearfield" && ($iohash->{Teach}|| $iohash->{SmartAckLearn}) && $RSSI <= 60) { } elsif ($learningMode eq "nearfield" && $iohash->{Teach} && $RSSI <= 60) {
Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and $rorgname telegram, please define it."; Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and $rorgname telegram, please define it.";
return $ret; return $ret;
} elsif ($learningMode eq "always") { } elsif ($learningMode eq "always") {
@ -5900,15 +5920,21 @@ sub EnOcean_Parse($$)
# packet type EVENT # packet type EVENT
#EnOcean:PacketType:eventCode:MessageData #EnOcean:PacketType:eventCode:MessageData
(undef, undef, $funcNumber, $data) = @msg; (undef, undef, $funcNumber, $data) = @msg;
Log3 undef, 2, "EnOcean EVENTCODE: $funcNumber DATA: $data";
$funcNumber = hex($funcNumber); $funcNumber = hex($funcNumber);
if ($funcNumber == 2) { if ($funcNumber == 2) {
# smart Ack confirm learn # smart Ack confirm learn
my ($priority, $rorg, $func, $type, $postmasterID, $hopCount); my ($priority, $rorg, $func, $type, $postmasterID, $hopCount);
my $responseTime = 150; my $responseTime = 150;
my $sendData = ''; my $sendData = '';
if ($iohash->{SmartAckLearn}) { my $sendHash = defined($hash) ? $hash : $iohash;
$data =~ m/^(..)(....)(..)(..)(..)(..)(........)(........)(..)$/; my $sendName = $sendHash->{NAME};
($priority, $manufID, $rorg, $func, $type, $RSSI, $postmasterID, $senderID, $hopCount) = ($1, $2, $3, $4, $5, $6, $7, $8, $9); $data =~ m/^(..)(....)(..)(..)(..)(..)(........)(........)(..)$/;
($priority, $manufID, $rorg, $func, $type, $RSSI, $postmasterID, $senderID, $hopCount) = (hex($1), $2, $3, $4, $5, hex($6), $7, $8, $9);
Log3 undef, 2, "EnOcean IOHASH: $iohash PRIORITY: $priority SmartAckLearn: " . (exists($iohash->{SmartAckLearn}) ? 1 : 0) .
" SmartAckLearnWait: " . (exists($iohash->{helper}{smartAckLearnWait}) ? $iohash->{helper}{smartAckLearnWait} : '');
if ($iohash->{SmartAckLearn} ||
exists($iohash->{helper}{smartAckLearnWait}) && $iohash->{helper}{smartAckLearnWait} eq $sendName) {
my $subType = "$rorg.$func.$type"; my $subType = "$rorg.$func.$type";
if (exists $EnO_eepConfig{$subType}) { if (exists $EnO_eepConfig{$subType}) {
# EEP supported # EEP supported
@ -5917,9 +5943,10 @@ sub EnOcean_Parse($$)
} }
$rorgname = $EnO_rorgname{$rorg}; $rorgname = $EnO_rorgname{$rorg};
if($hash) { if($hash) {
delete $iohash->{helper}{smartAckLearnWait};
$name = $hash->{NAME}; $name = $hash->{NAME};
$subDef = uc(AttrVal($name, "subDef", $hash->{DEF})); $subDef = uc(AttrVal($name, "subDef", $hash->{DEF}));
if (AttrVal($name, "teachMethod", undef) eq 'smartAck') { if (($priority & 15) == 15) {
# device exists, learn OUT # device exists, learn OUT
# send response, to delete mailbox # send response, to delete mailbox
$rorg = substr(AttrVal($name, "eep", ' '), 0, 2); $rorg = substr(AttrVal($name, "eep", ' '), 0, 2);
@ -5940,7 +5967,7 @@ sub EnOcean_Parse($$)
$attr{$name}{manufID} = $manufID; $attr{$name}{manufID} = $manufID;
$manufID = $EnO_manuf{$manufID} if(exists $EnO_manuf{$manufID}); $manufID = $EnO_manuf{$manufID} if(exists $EnO_manuf{$manufID});
$attr{$name}{postmasterID} = $postmasterID; $attr{$name}{postmasterID} = $postmasterID;
$hash->{SmartAckRSSI} = - hex($RSSI); $hash->{SmartAckRSSI} = $RSSI;
$attr{$name}{teachMethod} = 'smartAck'; $attr{$name}{teachMethod} = 'smartAck';
foreach my $attrCntr (keys %{$EnO_eepConfig{$subType}{attr}}) { foreach my $attrCntr (keys %{$EnO_eepConfig{$subType}{attr}}) {
if ($attrCntr ne "subDef") { if ($attrCntr ne "subDef") {
@ -5963,15 +5990,21 @@ sub EnOcean_Parse($$)
} }
} else { } else {
# device unknown # device unknown
if ($priority & 7 == 7) { if (($priority & 5) == 5) {
# Smart Ack priority ok (place for mailbox, good RSSI, Local) # Smart Ack priority ok (place for mailbox, good RSSI, Local)
Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and Smart Ack Teach-In message, please define it."; Log3 undef, 1, "EnOcean Unknown device with SenderID $senderID and Smart Ack learn In message, please define it.";
return "UNDEFINED EnO_$senderID EnOcean $senderID $msg"; return "UNDEFINED EnO_$senderID EnOcean $senderID $msg";
} elsif (($priority & 4) == 0) {
# Smart Ack no place for mailbox
$sendData = sprintf "00%04X12", $responseTime;
EnOcean_SndRadio(undef, $sendHash, 2, $rorg, $sendData, $postmasterID, '00', $senderID);
Log3 $sendName, 2, "EnOcean $sendName Smart Ack learn in from SenderID $senderID Discard learn in, postmaster has no place for further mailbox";
return '';
} else { } else {
# Smart Ack priority to low # Smart Ack priority to low
$sendData = sprintf "00%04X13", $responseTime; $sendData = sprintf "00%04X13", $responseTime;
EnOcean_SndRadio(undef, $hash, 2, $rorg, $sendData, $postmasterID, '00', $senderID); EnOcean_SndRadio(undef, $sendHash, 2, $rorg, $sendData, $postmasterID, '00', $senderID);
Log3 undef, 2, "EnOcean Smart Ack teach-in from SenderID $senderID priority to low"; Log3 $sendName, 2, "EnOcean $sendName Smart Ack learn in from SenderID $senderID Discard learn in, priority to low";
return ''; return '';
} }
} }
@ -5979,15 +6012,15 @@ sub EnOcean_Parse($$)
# EEP not supported # EEP not supported
# sent response # sent response
$sendData = sprintf "00%04X11", $responseTime; $sendData = sprintf "00%04X11", $responseTime;
EnOcean_SndRadio(undef, $hash, 2, $rorg, $sendData, $postmasterID, '00', $senderID); EnOcean_SndRadio(undef, $sendHash, 2, $rorg, $sendData, $postmasterID, '00', $senderID);
Log3 undef, 2, "EnOcean Smart Ack teach-in from SenderID $senderID with EEP $rorg-$func-$type not supported"; Log3 $sendName, 2, "EnOcean $sendName Smart Ack learn in from SenderID $senderID with EEP $rorg-$func-$type not supported";
return ''; return '';
} }
} else { } else {
# smart ack learn not activated # smart ack learn not activated
$sendData = sprintf "00%04XFF", $responseTime; $sendData = sprintf "00%04XFF", $responseTime;
EnOcean_SndRadio(undef, $hash, 2, $rorg, $sendData, $postmasterID, '00', $senderID); EnOcean_SndRadio(undef, $sendHash, 2, $rorg, $sendData, $postmasterID, '00', $senderID);
Log3 undef, 2, "EnOcean Smart Ack teach-in from SenderID $senderID received, activate learning"; Log3 $sendName, 2, "EnOcean $sendName Smart Ack learn in from SenderID $senderID received, activate learning";
return ''; return '';
} }
} }
@ -9561,35 +9594,33 @@ sub EnOcean_Parse($$)
# Room Control Panel # Room Control Panel
# (D2-11-01 - D2-11-08) # (D2-11-01 - D2-11-08)
my $msgType = hex(substr($data, 1, 1)); my $msgType = hex(substr($data, 1, 1));
my $setpointType = hex(substr($data, 0, 1) & 8 ? 'setpointTemp' : 'setpointShift'); my $setpointType = ReadingsVal($name, "setpointType", 'setpointShift');
push @event, "3:setpointType:$setpointType"; my $waitingCmds = ReadingsVal($name, "waitingCmds", 0);
if (! $waitingCmds & 0x80) {
$setpointType = hex(substr($data, 0, 1)) & 8 ? 'setpointTemp' : 'setpointShift';
push @event, "3:setpointType:$setpointType";
}
if ($msgType == 2) { if ($msgType == 2) {
my $trigger = ($db[5] & 0x60) >> 5; my $trigger = ($db[5] & 0x60) >> 5;
my %trigger = (0 => 'heartbeat', 1 => 'sensor', 2 => 'input'); my %trigger = (0 => 'heartbeat', 1 => 'sensor', 2 => 'input');
push @event, "3:trigger:" . $trigger{$trigger}; push @event, "3:trigger:" . $trigger{$trigger};
my $temperature = $db[4] / 255 * 40; my $temperature = sprintf "%0.1f", $db[4] / 255 * 40;
push @event, "3:temperature:$temperature"; push @event, "3:temperature:$temperature";
my $humidity = $db[3] / 2.5; my $humidity = sprintf "%d", $db[3] / 2.5;
push @event, "3:humidity:$humidity"; push @event, "3:humidity:$humidity";
my $setpointShift = unpack('c', pack('C', $db[2])); my $setpointShiftMax = ($db[0] & 0xF0) >> 4;
push @event, "3:setpointShift:$setpointShift"; push @event, "3:setpointShiftMax:$setpointShiftMax";
my $setpointShift = int(0.5 + $db[2] * $setpointShiftMax / 128 * 10) / 10 - $setpointShiftMax;
push @event, "3:setpointShift:" . sprintf "%0.1f", $setpointShift;
push @event, "3:setpointBase:$db[1]"; push @event, "3:setpointBase:$db[1]";
push @event, "3:setpointTemp:" . $db[1] * $setpointShift; push @event, "3:setpointTemp:" . sprintf "%0.1f", ($db[1] + $setpointShift);
push @event, "3:setpointShiftMax:" . (($db[0] & 0xF0) >> 4);
my %fanSpeed = (0 => 'auto', 1 => 'off', 2 => 1, 3 => 2, 4 => 3); my %fanSpeed = (0 => 'auto', 1 => 'off', 2 => 1, 3 => 2, 4 => 3);
my $fanSpeed = ($db[0] & 0xE) >> 1; my $fanSpeed = ($db[0] & 0xE) >> 1;
push @event, "3:fanSpeed:" . $fanSpeed{$fanSpeed}; push @event, "3:fanSpeed:" . $fanSpeed{$fanSpeed};
push @event, "3:occupancy:" . $db[0] & 1 ? 'occupied' : 'unoccupied'; push @event, "3:occupancy:" . ($db[0] & 1 ? 'occupied' : 'unoccupied');
push @event, "3:state:T: $temperature H: $humidity SPT: " . $db[1] + $setpointShift . " F: " . $fanSpeed{$fanSpeed}; push @event, "3:state:T: $temperature H: $humidity SPT: " . ($db[1] + $setpointShift) . " F: " . $fanSpeed{$fanSpeed};
if ($trigger == 2) {
# parameters changed on device
$db[3] = $db[5] & 0x80 | (ReadingsVal($name, "heating", 'off') eq 'on' ? 0x40 : 0) |
(ReadingsVal($name, "cooling", 'off') eq 'on' ? 0x20 : 0) |
(ReadingsVal($name, "window", 'closed') eq 'open' ? 0x10 : 0) | 1;
$data = sprintf "%02X%02X%02X%02X", $db[3], $db[2], $db[1], $db[0];
EnOcean_SndRadio(undef, $hash, $packetType, "D2", $data, AttrVal($name, "subDef", "00000000"), "00", $hash->{DEF});
}
} }
CommandDeleteReading(undef, "$name waitingCmds");
} elsif ($st eq "fanCtrl.00") { } elsif ($st eq "fanCtrl.00") {
# Fan Control # Fan Control
@ -9990,6 +10021,10 @@ sub EnOcean_Parse($$)
} }
} }
} elsif ($rorg eq "D0") {
my %smartAckMailbox = (0 => 'empty', 1 => 'not_exits', 2 => 'reset');
push @event, "3:smartAckMailbox:" . $smartAckMailbox{$db[0]};
} elsif ($rorg eq "B2") { } elsif ($rorg eq "B2") {
# GP complete data (GPCD) # GP complete data (GPCD)
my ($channel, $channelName, $value, $gpDef, $resolution) = (0, undef, undef, AttrVal($name, 'gpDef', undef), undef); my ($channel, $channelName, $value, $gpDef, $resolution) = (0, undef, undef, AttrVal($name, 'gpDef', undef), undef);
@ -14481,7 +14516,7 @@ EnOcean_Delete($$)
<br><br> <br><br>
Fhem and the EnOcean devices must be trained with each other. To this, Fhem Fhem and the EnOcean devices must be trained with each other. To this, Fhem
must be in the learning mode, see <a href="#EnOcean_teach-in">Teach-In / Teach-Out</a>, must be in the learning mode, see <a href="#EnOcean_teach-in">Teach-In / Teach-Out</a>,
<a href="#EnOcean_smartAck">SmartAck Learning</a> and <a href="#TCM_learningMode">learningMode</a>. <a href="#EnOcean_smartAck">Smart Ack Learning</a> and <a href="#TCM_learningMode">learningMode</a>.
The teach-in procedure depends on the type of the devices. The teach-in procedure depends on the type of the devices.
<br><br> <br><br>
Switches (EEP RPS) and contacts (EEP 1BS) are recognized when receiving the first message. Switches (EEP RPS) and contacts (EEP 1BS) are recognized when receiving the first message.
@ -14502,7 +14537,7 @@ EnOcean_Delete($$)
<br><br> <br><br>
Smart Ack Learning is a futher process where devices exchange information about each Smart Ack Learning is a futher process where devices exchange information about each
other in order to create the logical links in the EnOcean network and a Post Master Mail Box. other in order to create the logical links in the EnOcean network and a Post Master Mail Box.
It can result in Learn In or Learn Out, see <a href="#EnOcean_smartAck">SmartAck Learning</a>. It can result in Learn In or Learn Out, see <a href="#EnOcean_smartAck">Smart Ack Learning</a>.
<br><br> <br><br>
Fhem supports many of most common EnOcean profiles and manufacturer-specific Fhem supports many of most common EnOcean profiles and manufacturer-specific
devices. Additional profiles and devices can be added if required. devices. Additional profiles and devices can be added if required.
@ -14797,15 +14832,17 @@ EnOcean_Delete($$)
</ul> </ul>
</li> </li>
<li><a name="EnOcean_smartAck">SmartAck Learning</a> <li><a name="EnOcean_smartAck">Smart Ack Learning</a>
<ul> <ul>
<li>Teach-in remote Smart Ack devices</li> <li>Teach-in remote Smart Ack devices</li>
<br> <br>
<code>set &lt;IODev&gt; smartAckLearn &lt;t/s&gt;</code> <code>set &lt;IODev&gt; smartAckLearn &lt;t/s&gt;</code>
<br><br> <br><br>
Set Fhem in the Smart Ack learning mode.<br> Set Fhem in the Smart Ack learning mode.<br>
The post master fuctionality must be activated using the command <code>smartAckMailboxMax</code> in advance.<br>
The simple learnmode is supported, see <a href="#TCM_smartAckLearnMode">smartAckLearnMode</a><br>
A device, which is then also put in this state is to paired with A device, which is then also put in this state is to paired with
Fhem. Bidirectional Teach-In for 4BS, UTE and Generic Profiles are supported.<br> Fhem. Bidirectional learn in for 4BS, UTE and Generic Profiles are supported.<br>
<code>IODev</code> is the name of the TCM Module.<br> <code>IODev</code> is the name of the TCM Module.<br>
<code>t/s</code> is the time for the learning period. <code>t/s</code> is the time for the learning period.
<br><br> <br><br>