2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 03:06:37 +00:00

00_TCM / 10_EnOcean: Communication between modules optimized. Both modules need to be updated at the same time because the exchange format has changed.

git-svn-id: https://svn.fhem.de/fhem/trunk@19607 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klaus.schauer 2019-06-13 08:06:53 +00:00
parent 676ecaedf8
commit 011e1844ba
2 changed files with 45 additions and 64 deletions

View File

@ -8,13 +8,7 @@
# TCM_120_User_Manual_V1.53_02.pdf # TCM_120_User_Manual_V1.53_02.pdf
# EnOcean Serial Protocol 3 (ESP3) (for the TCM 310, TCM 400J, TCM 515) # EnOcean Serial Protocol 3 (ESP3) (for the TCM 310, TCM 400J, TCM 515)
# TODO:
# Check BSC Temp
# Check Stick Temp
# Check Stick WriteRadio
package main; package main;
use strict; use strict;
use warnings; use warnings;
use Time::HiRes qw(gettimeofday usleep); use Time::HiRes qw(gettimeofday usleep);
@ -26,7 +20,7 @@ if( $^O =~ /Win/ ) {
sub TCM_Read($); sub TCM_Read($);
sub TCM_ReadAnswer($$); sub TCM_ReadAnswer($$);
sub TCM_Ready($); sub TCM_Ready($);
sub TCM_Write($$$); sub TCM_Write($$$$);
sub TCM_Parse120($$$); sub TCM_Parse120($$$);
sub TCM_Parse310($$$); sub TCM_Parse310($$$);
sub TCM_CRC8($); sub TCM_CRC8($);
@ -95,6 +89,7 @@ sub TCM_Define($$){
sub TCM_InitSerialCom($) { sub TCM_InitSerialCom($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
delete $hash->{helper}{init_done};
if ($hash->{STATE} eq "disconnected") { if ($hash->{STATE} eq "disconnected") {
Log3 $name, 2, "TCM $name not initialized"; Log3 $name, 2, "TCM $name not initialized";
return undef; return undef;
@ -142,7 +137,6 @@ sub TCM_InitSerialCom($) {
$hash->{BaseID} = $baseID; $hash->{BaseID} = $baseID;
$hash->{LastID} = sprintf "%08X", (hex $baseID) + 127; $hash->{LastID} = sprintf "%08X", (hex $baseID) + 127;
} elsif ($comType ne "RS485" && $hash->{DeviceName} ne "none") { } elsif ($comType ne "RS485" && $hash->{DeviceName} ne "none") {
#$hash->{PARTIAL} = '';
my @getBaseID = ("get", "baseID"); my @getBaseID = ("get", "baseID");
if (TCM_Get($hash, @getBaseID) =~ /[Ff]{2}[\dA-Fa-f]{6}/) { if (TCM_Get($hash, @getBaseID) =~ /[Ff]{2}[\dA-Fa-f]{6}/) {
$hash->{BaseID} = sprintf "%08X", hex $&; $hash->{BaseID} = sprintf "%08X", hex $&;
@ -154,7 +148,6 @@ sub TCM_InitSerialCom($) {
} }
if ($hash->{MODEL} eq "ESP3" && $comType ne "RS485" && $hash->{DeviceName} ne "none") { if ($hash->{MODEL} eq "ESP3" && $comType ne "RS485" && $hash->{DeviceName} ne "none") {
# get chipID # get chipID
#$hash->{PARTIAL} = '';
my @getChipID = ('get', 'version'); my @getChipID = ('get', 'version');
if (TCM_Get($hash, @getChipID) =~ m/ChipID:.([\dA-Fa-f]{8})/) { if (TCM_Get($hash, @getChipID) =~ m/ChipID:.([\dA-Fa-f]{8})/) {
$hash->{ChipID} = sprintf "%08X", hex $1; $hash->{ChipID} = sprintf "%08X", hex $1;
@ -194,16 +187,15 @@ sub TCM_InitSerialCom($) {
} }
} }
#CommandSave(undef, undef); #CommandSave(undef, undef);
$hash->{helper}{init_done} = 1;
readingsSingleUpdate($hash, "state", "initialized", 1); readingsSingleUpdate($hash, "state", "initialized", 1);
Log3 $name, 2, "TCM $name initialized"; Log3 $name, 2, "TCM $name initialized";
return undef; return undef;
} }
sub sub TCM_Fingerprint($$) {
TCM_Fingerprint($$)
{
my ($IODev, $msg) = @_; my ($IODev, $msg) = @_;
return ($IODev, $msg) if (AttrVal($IODev, "fingerprint", 'off') eq 'off'); return ($IODev, $msg) if (AttrVal($IODev, "fingerprint", 'off') eq 'off');
my @msg = split(":", $msg); my @msg = split(":", $msg);
if ($msg[1] == 1) { if ($msg[1] == 1) {
@ -242,34 +234,31 @@ TCM_Fingerprint($$)
} }
# Write # Write
# Input is header and data (HEX), without CRC sub TCM_Write($$$$) {
sub # Input is header and data (HEX), without CRC
TCM_Write($$$) my ($hash, $shash, $header, $msg) = @_;
{ return if (!exists($hash->{helper}{init_done}) && $hash != $shash);
my ($hash,$fn,$msg) = @_; # return if (!defined($header));
my $name = $hash->{NAME}; my $name = $hash->{NAME};
return if (!defined($fn));
my $bstring; my $bstring;
if ($hash->{MODEL} eq "ESP2") { if ($hash->{MODEL} eq "ESP2") {
# TCM 120 (ESP2) # TCM 120 (ESP2)
if (!$fn) { if (!$header) {
# command with ESP2 format # command with ESP2 format
$bstring = $msg; $bstring = $msg;
} else { } else {
# command with ESP3 format # command with ESP3 format
my $packetType = hex(substr($fn, 6, 2)); my $packetType = hex(substr($header, 6, 2));
if ($packetType != 1) { if ($packetType != 1) {
Log3 $name, 1, "TCM $name Packet Type not supported."; Log3 $name, 1, "TCM $name Packet Type not supported.";
return; return;
} }
my $odataLen = hex(substr($fn, 4, 2)); my $odataLen = hex(substr($header, 4, 2));
if ($odataLen != 0) { if ($odataLen != 0) {
Log3 $name, 1, "TCM $name Radio Telegram with optional Data not supported."; Log3 $name, 1, "TCM $name Radio Telegram with optional Data not supported.";
return; return;
} }
#my $mdataLen = hex(substr($fn, 0, 4)); #my $mdataLen = hex(substr($header, 0, 4));
my $rorg = substr ($msg, 0, 2); my $rorg = substr ($msg, 0, 2);
# translate the RORG to ORG # translate the RORG to ORG
my %rorgmap = ("F6"=>"05", my %rorgmap = ("F6"=>"05",
@ -290,7 +279,7 @@ TCM_Write($$$)
$bstring = "A55A" . $bstring . TCM_CSUM($bstring); $bstring = "A55A" . $bstring . TCM_CSUM($bstring);
} else { } else {
# TCM 310 (ESP3) # TCM 310 (ESP3)
$bstring = "55" . $fn . TCM_CRC8($fn) . $msg . TCM_CRC8($msg); $bstring = "55" . $header . TCM_CRC8($header) . $msg . TCM_CRC8($msg);
if (exists($hash->{helper}{telegramSentTimeLast}) && $hash->{helper}{telegramSentTimeLast} < gettimeofday() - 6) { if (exists($hash->{helper}{telegramSentTimeLast}) && $hash->{helper}{telegramSentTimeLast} < gettimeofday() - 6) {
# clear outdated response control list # clear outdated response control list
delete $hash->{helper}{awaitCmdResp}; delete $hash->{helper}{awaitCmdResp};
@ -415,7 +404,7 @@ TCM_Read($)
if ($blockSenderID eq "own" && ((hex($id) >= $baseID && hex($id) <= $lastID) || $chipID == hex($id))) { if ($blockSenderID eq "own" && ((hex($id) >= $baseID && hex($id) <= $lastID) || $chipID == hex($id))) {
Log3 $name, 4, "TCM $name own telegram from $id blocked."; Log3 $name, 4, "TCM $name own telegram from $id blocked.";
} else { } else {
Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:01FFFFFFFF0000", undef); Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:01FFFFFFFF0000", undef) if (exists $hash->{helper}{init_done});
} }
} else { } else {
@ -438,7 +427,7 @@ TCM_Read($)
if ($blockSenderID eq "own" && ((hex($id) >= $baseID && hex($id) <= $lastID) || $chipID == hex($id))) { if ($blockSenderID eq "own" && ((hex($id) >= $baseID && hex($id) <= $lastID) || $chipID == hex($id))) {
Log3 $name, 4, "TCM $name own telegram from $id blocked."; Log3 $name, 4, "TCM $name own telegram from $id blocked.";
} else { } else {
Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:01FFFFFFFF0000", undef); Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:01FFFFFFFF0000", undef) if (exists $hash->{helper}{init_done});
} }
} }
} }
@ -503,7 +492,7 @@ TCM_Read($)
Log3 $name, 4, "TCM $name own telegram from $id blocked."; Log3 $name, 4, "TCM $name own telegram from $id blocked.";
} else { } else {
#EnOcean:PacketType:RORG:MessageData:SourceID:Status:OptionalData #EnOcean:PacketType:RORG:MessageData:SourceID:Status:OptionalData
Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:$odata", \%addvals); Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:$odata", \%addvals) if (exists $hash->{helper}{init_done});
} }
} elsif ($packetType == 2) { } elsif ($packetType == 2) {
@ -581,7 +570,7 @@ TCM_Read($)
$mdata =~ m/^(..)(.*)$/; $mdata =~ m/^(..)(.*)$/;
$packetType = sprintf "%01X", $packetType; $packetType = sprintf "%01X", $packetType;
#EnOcean:PacketType:smartAckCode:MessageData #EnOcean:PacketType:smartAckCode:MessageData
Dispatch($hash, "EnOcean:$packetType:$1:$2", undef); Dispatch($hash, "EnOcean:$packetType:$1:$2", undef) if (exists $hash->{helper}{init_done});
} elsif ($packetType == 7) { } elsif ($packetType == 7) {
# packet type REMOTE_MAN_COMMAND # packet type REMOTE_MAN_COMMAND
@ -607,7 +596,7 @@ TCM_Read($)
Log3 $name, 4, "TCM $name own telegram from $2 blocked."; Log3 $name, 4, "TCM $name own telegram from $2 blocked.";
} else { } else {
#EnOcean:PacketType:RORG:MessageData:SourceID:DestinationID:FunctionNumber:ManufacturerID:RSSI:Delay #EnOcean:PacketType:RORG:MessageData:SourceID:DestinationID:FunctionNumber:ManufacturerID:RSSI:Delay
Dispatch($hash, "EnOcean:$packetType:C5:$messageData:$2:$1:$function:$manufID:$RSSI:$4", \%addvals); Dispatch($hash, "EnOcean:$packetType:C5:$messageData:$2:$1:$function:$manufID:$RSSI:$4", \%addvals) if (exists $hash->{helper}{init_done});
} }
} elsif ($packetType == 9) { } elsif ($packetType == 9) {
@ -769,9 +758,7 @@ TCM_Parse310($$$)
} }
# Ready # Ready
sub sub TCM_Ready($) {
TCM_Ready($)
{
my ($hash) = @_; my ($hash) = @_;
return DevIo_OpenDev($hash, 1, undef) return DevIo_OpenDev($hash, 1, undef)
@ -827,7 +814,7 @@ TCM_Get($@)
return "Unknown argument $cmd, choose one of " . join(':noArg ', sort keys %gets120) . ':noArg' if(!defined($rawcmd)); return "Unknown argument $cmd, choose one of " . join(':noArg ', sort keys %gets120) . ':noArg' if(!defined($rawcmd));
Log3 $name, 3, "TCM $name get $cmd"; Log3 $name, 3, "TCM $name get $cmd";
$rawcmd .= "000000000000000000"; $rawcmd .= "000000000000000000";
TCM_Write($hash, "", $rawcmd); TCM_Write($hash, $hash, "", $rawcmd);
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd"); ($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
$msg = TCM_Parse120($hash, $msg, 1) if(!$err); $msg = TCM_Parse120($hash, $msg, 1) if(!$err);
@ -840,8 +827,8 @@ TCM_Get($@)
my $oCmdHex = ''; my $oCmdHex = '';
$oCmdHex = $cmdhash->{oCmd} if (exists $cmdhash->{oCmd}); $oCmdHex = $cmdhash->{oCmd} if (exists $cmdhash->{oCmd});
$hash->{helper}{SetAwaitCmdResp} = 1; $hash->{helper}{SetAwaitCmdResp} = 1;
#TCM_Write($hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex); #TCM_Write($hash, $hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex);
TCM_Write($hash, sprintf("%04X%02X%02X", length($cmdHex)/2, length($oCmdHex)/2, $cmdhash->{packetType}), $cmdHex . $oCmdHex); TCM_Write($hash, $hash, sprintf("%04X%02X%02X", length($cmdHex)/2, length($oCmdHex)/2, $cmdhash->{packetType}), $cmdHex . $oCmdHex);
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd"); ($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
$msg = TCM_Parse310($hash, $msg, $cmdhash) if(!$err); $msg = TCM_Parse310($hash, $msg, $cmdhash) if(!$err);
@ -975,7 +962,7 @@ sub TCM_Set($@)
return ""; return "";
} }
$cmdHex .= "0"x(22-length($cmdHex)); # Padding with 0 $cmdHex .= "0"x(22-length($cmdHex)); # Padding with 0
TCM_Write($hash, "", $cmdHex); TCM_Write($hash, $hash, "", $cmdHex);
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd"); ($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
$msg = TCM_Parse120($hash, $msg, 1) if(!$err); $msg = TCM_Parse120($hash, $msg, 1) if(!$err);
@ -993,7 +980,7 @@ sub TCM_Set($@)
return; return;
} }
$hash->{helper}{SetAwaitCmdResp} = 1; $hash->{helper}{SetAwaitCmdResp} = 1;
TCM_Write($hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex); TCM_Write($hash, $hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex);
($err, $msg) = TCM_ReadAnswer($hash, "set $cmd"); ($err, $msg) = TCM_ReadAnswer($hash, "set $cmd");
if(!$err) { if(!$err) {
$msg = TCM_Parse310($hash, $msg, $cmdhash); $msg = TCM_Parse310($hash, $msg, $cmdhash);
@ -1163,7 +1150,7 @@ sub TCM_ReadAnswer($$)
Log3 $name, 4, "TCM $name own telegram from $id blocked."; Log3 $name, 4, "TCM $name own telegram from $id blocked.";
} else { } else {
#EnOcean:PacketType:RORG:MessageData:SourceID:Status:OptionalData #EnOcean:PacketType:RORG:MessageData:SourceID:Status:OptionalData
Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:$odata", \%addvals); Dispatch($hash, "EnOcean:$packetType:$org:$d1:$id:$status:$odata", \%addvals) if (exists $hash->{helper}{init_done});
} }
$data = $rest; $data = $rest;
$hash->{PARTIAL} = $rest; $hash->{PARTIAL} = $rest;
@ -1343,9 +1330,7 @@ sub TCM_Notify(@) {
} }
# Undef # Undef
sub sub TCM_Undef($$) {
TCM_Undef($$)
{
my ($hash, $arg) = @_; my ($hash, $arg) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1360,6 +1345,7 @@ TCM_Undef($$)
} }
} }
DevIo_CloseDev($hash); DevIo_CloseDev($hash);
delete $hash->{helper}{init_done};
return undef; return undef;
} }

View File

@ -1,7 +1,6 @@
# $Id$ # $Id$
package main; package main;
use strict; use strict;
use warnings; use warnings;
my $cryptFunc; my $cryptFunc;
@ -7837,7 +7836,7 @@ sub EnOcean_Parse($$)
# calc wakeup cycle # calc wakeup cycle
if ($summerMode eq 'off') { if ($summerMode eq 'off') {
$summerMode = 0; $summerMode = 0;
if ($timeDiff == 0 || $window eq 'open') { if ($timeDiff == 0 || $window eq 'open') {
$wakeUpCycle = 1200; $wakeUpCycle = 1200;
} elsif ($timeDiff < 120) { } elsif ($timeDiff < 120) {
$wakeUpCycle = 120; $wakeUpCycle = 120;
@ -14773,25 +14772,23 @@ sub EnOcean_calcPID($) {
$retStr = " with return-value:" . $ret if ( defined($ret) && ( $ret ne '' ) ); $retStr = " with return-value:" . $ret if ( defined($ret) && ( $ret ne '' ) );
#PID20_Log $hash, 3, "<$cmd> " . $retStr; #PID20_Log $hash, 3, "<$cmd> " . $retStr;
} }
my $updateAlive = ($actuation ne "") # my $updateAlive = ($actuation ne "")
&& EnOcean_TimeDiff(ReadingsTimestamp($name, 'setpointSet', undef)) >= $hash->{helper}{updateInterval}; # && EnOcean_TimeDiff(ReadingsTimestamp($name, 'setpointSet', ReadingsTimestamp($name, 'setpoint', undef))) >= $hash->{helper}{updateInterval};
#&& EnOcean_TimeDiff( ReadingsTimestamp( $name, 'setpointSet', gettimeofday() ) ) >= $hash->{helper}{updateInterval}; # && EnOcean_TimeDiff( ReadingsTimestamp( $name, 'setpointSet', gettimeofday() ) ) >= $hash->{helper}{updateInterval};
# my $updateReq = ( ( $actuationReq || $updateAlive ) && $actuation ne "" ); # my $updateReq = ( ( $actuationReq || $updateAlive ) && $actuation ne "" );
# PID20_Log $hash, 2, "U1 actReq:$actuationReq updateAlive:$updateAlive --> updateReq:$updateReq" if ($DEBUG_Update); # PID20_Log $hash, 2, "U1 actReq:$actuationReq updateAlive:$updateAlive --> updateReq:$updateReq" if ($DEBUG_Update);
# ---------------- update request # ---------------- update request
if ($readingUpdateReq) if ($readingUpdateReq) {
{
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
#readingsBulkUpdate( $hash, $hash->{helper}{desiredName}, $desired ) if ( $desired ne "" ); #readingsBulkUpdate( $hash, $hash->{helper}{desiredName}, $desired ) if ( $desired ne "" );
#readingsBulkUpdate( $hash, $hash->{helper}{measuredName}, $sensorValue ) if ( $sensorValue ne "" ); #readingsBulkUpdate( $hash, $hash->{helper}{measuredName}, $sensorValue ) if ( $sensorValue ne "" );
readingsBulkUpdate( $hash, 'p_p', $pPortion ) if ( $pPortion ne "" ); readingsBulkUpdate( $hash, 'p_p', $pPortion ) if ( $pPortion ne "" );
readingsBulkUpdate( $hash, 'p_d', $dPortion ) if ( $dPortion ne "" ); readingsBulkUpdate( $hash, 'p_d', $dPortion ) if ( $dPortion ne "" );
readingsBulkUpdate( $hash, 'p_i', $iPortion ) if ( $iPortion ne "" ); readingsBulkUpdate( $hash, 'p_i', $iPortion ) if ( $iPortion ne "" );
readingsBulkUpdate( $hash, 'setpointSet', $actuationDone) if ($actuationDone ne ""); readingsBulkUpdate( $hash, 'setpointSet', $actuationDone) if ($actuationDone ne "");
readingsBulkUpdate( $hash, 'setpointCalc', $actuationCalc ) if ( $actuationCalc ne "" ); readingsBulkUpdate( $hash, 'setpointCalc', $actuationCalc) if ( $actuationCalc ne "" );
readingsBulkUpdate( $hash, 'delta', $delta ) if ( $delta ne "" ); readingsBulkUpdate( $hash, 'delta', $delta ) if ( $delta ne "" );
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
#PID20_Log $hash, 5, "readings updated"; #PID20_Log $hash, 5, "readings updated";
} }
@ -15631,8 +15628,7 @@ sub EnOcean_SndCdm($$$$$$$$)
} }
# send ESP3 Packet Type Radio # send ESP3 Packet Type Radio
sub EnOcean_SndRadio($$$$$$$$) sub EnOcean_SndRadio($$$$$$$$) {
{
my ($ctrl, $hash, $packetType, $rorg, $data, $senderID, $status, $destinationID) = @_; my ($ctrl, $hash, $packetType, $rorg, $data, $senderID, $status, $destinationID) = @_;
if (!defined $data) { if (!defined $data) {
Log3 $hash->{NAME}, 5, "EnOcean $hash->{NAME} EnOcean_SndRadio SenderID: $senderID DestinationID: $destinationID " . Log3 $hash->{NAME}, 5, "EnOcean $hash->{NAME} EnOcean_SndRadio SenderID: $senderID DestinationID: $destinationID " .
@ -15685,20 +15681,19 @@ sub EnOcean_SndRadio($$$$$$$$)
} }
if (defined $ctrl) { if (defined $ctrl) {
# sent telegram delayed # sent telegram delayed
my @param = ($hash, $header, $data); my @param = ($hash, $hash, $header, $data);
InternalTimer(gettimeofday() + $ctrl, 'EnOcean_IOWriteTimer', \@param, 0); InternalTimer(gettimeofday() + $ctrl, 'EnOcean_IOWriteTimer', \@param, 0);
} else { } else {
IOWrite($hash, $header, $data); IOWrite($hash, $hash, $header, $data);
} }
return; return;
} }
# #
sub EnOcean_IOWriteTimer($) sub EnOcean_IOWriteTimer($) {
{
my ($ioParam) = @_; my ($ioParam) = @_;
my ($hash, $header, $data) = @$ioParam; my ($hash, $shash, $header, $data) = @$ioParam;
IOWrite($hash, $header, $data); IOWrite($hash, $shash, $header, $data);
return; return;
} }