diff --git a/fhem/FHEM/00_TCM.pm b/fhem/FHEM/00_TCM.pm index 7fab9ca87..e489fe0ab 100755 --- a/fhem/FHEM/00_TCM.pm +++ b/fhem/FHEM/00_TCM.pm @@ -1,22 +1,18 @@ ############################################## # $Id$ -# by r.koenig at koeniglich.de -# -# This modules handles the communication with a TCM 120 or TCM 310 / TCM 400J EnOcean -# transceiver chip. As the protocols are radically different, this is actually 2 -# drivers in one. +# This modules handles the communication with a TCM 120 or TCM 310 / TCM 400J / +# TCM 515 EnOcean transceiver chip. As the protocols are radically different, +# this is actually 2 drivers in one. # See also: # TCM_120_User_Manual_V1.53_02.pdf -# EnOcean Serial Protocol 3 (ESP3) (for the TCM 310, TCM 400J) +# EnOcean Serial Protocol 3 (ESP3) (for the TCM 310, TCM 400J, TCM 515) # TODO: # Check BSC Temp # Check Stick Temp # Check Stick WriteRadio -# Check Stick RSS - package main; use strict; @@ -548,8 +544,32 @@ TCM_Read($) # packet type EVENT $mdata =~ m/^(..)(.*)$/; $packetType = sprintf "%01X", $packetType; - #EnOcean:PacketType:eventCode:MessageData - Dispatch($hash, "EnOcean:$packetType:$1:$2", undef); + my $eventCode = $1; + my $messageData = $2; + if (hex($eventCode) <= 3) { + #EnOcean:PacketType:eventCode:messageData + Dispatch($hash, "EnOcean:$packetType:$eventCode:$messageData", undef); + } elsif (hex($eventCode) == 4) { + # CO_READY + my @resetCause = ('voltage_supply_drop', 'reset_pin', 'watchdog', 'flywheel', 'parity_error', 'hw_parity_error', 'memory_request_error', 'wake_up', 'wake_up', 'unknown'); + my @secureMode = ('standard', 'extended'); + $hash->{RESET_CAUSE} = $resetCause[hex($messageData)]; + $hash->{SECURE_MODE} = $secureMode[hex($odata)]; + Log3 $name, 2, "TCM $name EVENT RESET_CAUSE: $hash->{RESET_CAUSE} SECURE_MODE: $hash->{SECURE_MODE}"; + } elsif (hex($eventCode) == 5) { + # CO_EVENT_SECUREDEVICES + } elsif (hex($eventCode) == 6) { + # CO_DUTYCYCLE_LIMIT + my @dutycycleLimit = ('released', 'reached'); + $hash->{DUTYCYCLE_LIMIT} = $dutycycleLimit[hex($messageData)]; + Log3 $name, 2, "TCM $name EVENT DUTYCYCLE_LIMIT: $hash->{DUTYCYCLE_LIMIT}"; + } elsif (hex($eventCode) == 7) { + # CO_TRANSMIT_FAILED + my @transmitFailed = ('CSMA_failed', 'no_ack_received'); + $hash->{TRANSMIT_FAILED} = $transmitFailed[hex($messageData)]; + Log3 $name, 2, "TCM $name EVENT TRANSMIT_FAILED: $hash->{TRANSMIT_FAILED}"; + } else { + } } elsif ($packetType == 5) { # packet type COMMON_COMMAND @@ -776,10 +796,12 @@ my %gets120 = ( my %gets310 = ( "baseID" => {packetType => 5, cmd => "08", BaseID => "1,4", RemainingWriteCycles => "5,1"}, "filter" => {packetType => 5, cmd => "0F", "Type:Value" => "1,0,1:4"}, - "numSecureDevicesIn" => {packetType => 5, cmd => "1D00", Number => "1,1"}, - "numSecureDevicesOut" => {packetType => 5, cmd => "1D01", Number => "1,1"}, - "repeater" => {packetType => 5, cmd => "0A", RepEnable => "1,1", RepLevel => "2,1"}, "frequencyInfo" => {packetType => 5, cmd => "25", Frequency => "1,1", Protocol => "2,1"}, + "noiseThreshold" => {packetType => 5, cmd => "33", NoiseThreshold => "1,1"}, + #"numSecureDevicesIn" => {packetType => 5, cmd => "1D00", Number => "1,1"}, + #"numSecureDevicesOut" => {packetType => 5, cmd => "1D01", Number => "1,1"}, + "remanRepeating" => {packetType => 5, cmd => "31", Repeated => "1,1"}, + "repeater" => {packetType => 5, cmd => "0A", RepEnable => "1,1", RepLevel => "2,1"}, "stepCode" => {packetType => 5, cmd => "27", HWRevision => "1,1", Stepcode => "2,1"}, "smartAckLearnMode" => {packetType => 6, cmd => "02", Enable => "1,1", Extended => "2,1"}, "smartAckLearnedClients" => {packetType => 6, cmd => "06", "ClientID:CtrlID:Mailbox" => "1,0,4:4:1"}, @@ -801,7 +823,7 @@ TCM_Get($@) # TCM 120 my $rawcmd = $gets120{$cmd}; return "Unknown argument $cmd, choose one of " . join(':noArg ', sort keys %gets120) . ':noArg' if(!defined($rawcmd)); - Log3 $name, 3, "TCM get $name $cmd"; + Log3 $name, 3, "TCM $name get $cmd"; $rawcmd .= "000000000000000000"; TCM_Write($hash, "", $rawcmd); ($err, $msg) = TCM_ReadAnswer($hash, "get $cmd"); @@ -811,7 +833,7 @@ TCM_Get($@) # TCM 310 my $cmdhash = $gets310{$cmd}; return "Unknown argument $cmd, choose one of " . join(':noArg ', sort keys %gets310) . ':noArg' if(!defined($cmdhash)); - Log3 $name, 3, "TCM get $name $cmd"; + Log3 $name, 3, "TCM $name get $cmd"; my $cmdHex = $cmdhash->{cmd}; $hash->{helper}{SetAwaitCmdResp} = 1; TCM_Write($hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex); @@ -856,23 +878,28 @@ my %sets120 = ( # Name, Data to send to the CUL, Regexp for the answer # Set commands TCM 310 my %sets310 = ( - "init" => {}, - "teach" => {packetType => 5, arg=> "\\d+"}, - "sleep" => {packetType => 5, cmd => "01", arg => "00[0-9A-F]{6}"}, - "reset" => {packetType => 5, cmd => "02"}, - "bist" => {packetType => 5, cmd => "06", BIST_Result => "1,1"}, "baseID" => {packetType => 5, cmd => "07", arg => "FF[8-9A-F][0-9A-F]{5}"}, - "repeater" => {packetType => 5, cmd => "09", arg => "0[0-1]0[0-2]"}, + "baudrate" => {packetType => 5, cmd => "24", arg => "0[0-3]"}, + "bist" => {packetType => 5, cmd => "06", BIST_Result => "1,1"}, "filterAdd" => {packetType => 5, cmd => "0B", arg => "0[0-3][0-9A-F]{8}[048C]0"}, "filterDel" => {packetType => 5, cmd => "0C", arg => "0[0-3][0-9A-F]{8}"}, "filterDelAll" => {packetType => 5, cmd => "0D"}, "filterEnable" => {packetType => 5, cmd => "0E", arg => "0[01]0[0189]"}, + "init" => {}, "maturity" => {packetType => 5, cmd => "10", arg => "0[0-1]"}, - "subtel" => {packetType => 5, cmd => "11", arg => "0[0-1]"}, "mode" => {packetType => 5, cmd => "1C", arg => "0[0-1]"}, - "baudrate" => {packetType => 5, cmd => "24", arg => "0[0-3]"}, + "noiseThreshold" => {packetType => 5, cmd => "32", arg => "2E|2F|3[0-8]"}, + "remanCode" => {packetType => 5, cmd => "2E", arg => "[0-9A-F]{8}"}, + "remanRepeating" => {packetType => 5, cmd => "30", arg => "0[0-1]"}, + "reset" => {packetType => 5, cmd => "02"}, + "resetEvents" => {}, + "repeater" => {packetType => 5, cmd => "09", arg => "0[0-1]0[0-2]"}, + "sleep" => {packetType => 5, cmd => "01", arg => "00[0-9A-F]{6}"}, "smartAckLearn" => {packetType => 6, cmd => "01", arg => "\\d+"}, "smartAckMailboxMax" => {packetType => 6, cmd => "08", arg => "\\d+"}, + "startupDelay" => {packetType => 5, cmd => "2F", arg => "[0-9A-F]{2}"}, + "subtel" => {packetType => 5, cmd => "11", arg => "0[0-1]"}, + "teach" => {packetType => 5, arg=> "\\d+"}, ); # Set @@ -921,7 +948,7 @@ sub TCM_Set($@) $cmdHex .= $arg; } - Log3 $name, 3, "TCM set $name $cmd $logArg"; + Log3 $name, 3, "TCM $name set $cmd $logArg"; if($cmd eq "teach") { if ($arg == 0) { @@ -953,6 +980,13 @@ sub TCM_Set($@) TCM_InitSerialCom($hash); return; } + if($cmd eq "resetEvents") { + delete $hash->{RESET_CAUSE}; + delete $hash->{SECURE_MODE}; + delete $hash->{DUTYCYCLE_LIMIT}; + delete $hash->{TRANSMIT_FAILED}; + return; + } $hash->{helper}{SetAwaitCmdResp} = 1; TCM_Write($hash, sprintf("%04X00%02X", length($cmdHex)/2, $cmdhash->{packetType}), $cmdHex); ($err, $msg) = TCM_ReadAnswer($hash, "set $cmd"); @@ -1097,6 +1131,7 @@ sub TCM_ReadAnswer($$) shift(@{$hash->{helper}{awaitCmdResp}}); return ("wrong data checksum: got $crc, computed $mycrc", undef); } + if ($packetType == 1) { # packet type RADIO $mdata =~ m/^(..)(.*)(........)(..)$/; @@ -1157,8 +1192,41 @@ sub TCM_ReadAnswer($$) $data = $rest; next; } + } elsif ($packetType == 4) { + ##### + # packet type EVENT + $mdata =~ m/^(..)(.*)$/; + my $eventCode = $1; + my $messageData = $2; + if (hex($eventCode) <= 3) { + my $packetTypeHex = sprintf "%01X", $packetType; + #EnOcean:PacketType:eventCode:messageData + Dispatch($hash, "EnOcean:$packetTypeHex:$eventCode:$messageData", undef); + } elsif (hex($eventCode) == 4) { + # CO_READY + my @resetCause = ('voltage_supply_drop', 'reset_pin', 'watchdog', 'flywheel', 'parity_error', 'hw_parity_error', 'memory_request_error', 'wake_up', 'wake_up', 'unknown'); + my @secureMode = ('standard', 'extended'); + $hash->{RESET_CAUSE} = $resetCause[hex($messageData)]; + $hash->{SECURE_MODE} = $secureMode[hex($odata)]; + Log3 $name, 2, "TCM $name EVENT RESET_CAUSE: $hash->{RESET_CAUSE} SECURE_MODE: $hash->{SECURE_MODE}"; + } elsif (hex($eventCode) == 5) { + # CO_EVENT_SECUREDEVICES + } elsif (hex($eventCode) == 6) { + # CO_DUTYCYCLE_LIMIT + my @dutycycleLimit = ('released', 'reached'); + $hash->{DUTYCYCLE_LIMIT} = $dutycycleLimit[hex($messageData)]; + Log3 $name, 2, "TCM $name EVENT DUTYCYCLE_LIMIT: $hash->{DUTYCYCLE_LIMIT}"; + } elsif (hex($eventCode) == 7) { + # CO_TRANSMIT_FAILED + my @transmitFailed = ('CSMA_failed', 'no_ack_received'); + $hash->{TRANSMIT_FAILED} = $transmitFailed[hex($messageData)]; + Log3 $name, 2, "TCM $name EVENT TRANSMIT_FAILED: $hash->{TRANSMIT_FAILED}"; + } + $data = $rest; + $hash->{PARTIAL} = $rest; + next; } else { - return ("Evaluation of the command $arg aborted because the received data telegram is not supported.", undef) + return ("$arg ERROR: received data telegram PacketType: $packetType Data: $mdata not supported.", undef) } } } @@ -1292,14 +1360,14 @@ TCM_Undef($$)
define <name> TCM [ESP2|ESP3] <device>
device
can take the same parameters (@baudrate, @directio,
TCP/IP, none) like the CUL, but you probably have
to specify the baudrate: the TCM 120 should be opened with 9600 Baud, the
- TCM 310 with 57600 baud. For Eltako FGW14 devices, type has to be set to 120 and
+ TCM 310 and TCM 515 with 57600 baud. For Eltako FGW14 devices, type has to be set to 120 and
the baudrate has to be set to 57600 baud if the FGW14 operating mode
rotary switch is on position 6.smartAckMailboxMax
in advance.