mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-21 07:56:03 +00:00
00_TCM: start routines optimized
git-svn-id: https://svn.fhem.de/fhem/trunk@6100 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
602e3696fc
commit
bf3b7baecd
@ -3,12 +3,12 @@
|
||||
|
||||
# by r.koenig at koeniglich.de
|
||||
#
|
||||
# This modules handles the communication with a TCM120 or TCM310 EnOcean
|
||||
# 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.
|
||||
# See also:
|
||||
# TCM_120_User_Manual_V1.53_02.pdf
|
||||
# EnOcean Serial Protocol 3 (ESP3) (for the TCM310)
|
||||
# EnOcean Serial Protocol 3 (ESP3) (for the TCM 310, TCM 400J)
|
||||
|
||||
# TODO:
|
||||
# Check BSC Temp
|
||||
@ -20,13 +20,12 @@ package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
use Time::HiRes qw(gettimeofday usleep);
|
||||
if( $^O =~ /Win/ ) {
|
||||
require Win32::SerialPort;
|
||||
} else {
|
||||
require Device::SerialPort;
|
||||
}
|
||||
|
||||
sub TCM_Read($);
|
||||
sub TCM_ReadAnswer($$);
|
||||
sub TCM_Ready($);
|
||||
@ -55,12 +54,14 @@ TCM_Initialize($)
|
||||
$hash->{MatchList} = \%matchList;
|
||||
|
||||
# Normal devices
|
||||
$hash->{DefFn} = "TCM_Define";
|
||||
$hash->{UndefFn} = "TCM_Undef";
|
||||
$hash->{GetFn} = "TCM_Get";
|
||||
$hash->{SetFn} = "TCM_Set";
|
||||
$hash->{AttrFn} = "TCM_Attr";
|
||||
$hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 blockSenderID:own,no learningMode:always,demand,nearfield";
|
||||
$hash->{DefFn} = "TCM_Define";
|
||||
$hash->{UndefFn} = "TCM_Undef";
|
||||
$hash->{GetFn} = "TCM_Get";
|
||||
$hash->{SetFn} = "TCM_Set";
|
||||
$hash->{NotifyFn} = "TCM_Notify";
|
||||
$hash->{AttrFn} = "TCM_Attr";
|
||||
$hash->{AttrList} = "do_not_notify:1,0 dummy:1,0 blockSenderID:own,no learningMode:always,demand,nearfield " .
|
||||
"sendInterval:0,25,40,50,100,150,200,250";
|
||||
}
|
||||
|
||||
# Define
|
||||
@ -71,37 +72,29 @@ TCM_Define($$)
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
my $name = $a[0];
|
||||
my $model = $a[2];
|
||||
my $baseID;
|
||||
|
||||
return "TCM: wrong syntax, correct is: define <name> TCM [120|310] ".
|
||||
return "TCM: wrong syntax, correct is: define <name> TCM [ESP2|ESP3] ".
|
||||
"{devicename[\@baudrate]|ip:port|none}"
|
||||
if(@a != 4 || $model !~ m/^(120|310)$/);
|
||||
if(@a != 4 || $model !~ m/^(ESP2|ESP3|120|310)$/);
|
||||
|
||||
DevIo_CloseDev($hash);
|
||||
my $dev = $a[3];
|
||||
$hash->{DeviceName} = $dev;
|
||||
# old model names replaced
|
||||
$model = "ESP2" if ($model eq "120");
|
||||
$model = "ESP3" if ($model eq "310");
|
||||
$hash->{MODEL} = $model;
|
||||
|
||||
$hash->{BaseID} = "00000000";
|
||||
$hash->{LastID} = "00000000";
|
||||
if($dev eq "none") {
|
||||
#Log 1, "TCM: $name device is none, commands will be echoed only";
|
||||
Log3 undef, 1, "TCM $name device is none, commands will be echoed only";
|
||||
$attr{$name}{dummy} = 1;
|
||||
return undef;
|
||||
}
|
||||
|
||||
my $ret = DevIo_OpenDev($hash, 0, undef);
|
||||
my @getBaseID = ("get", "baseID");
|
||||
if (TCM_Get($hash, @getBaseID) =~ /[Ff]{2}[\dA-Fa-f]{6}/ ) {
|
||||
$hash->{BaseID} = sprintf "%08X", hex $&;
|
||||
$hash->{LastID} = sprintf "%08X", (hex $&) + 127;
|
||||
} else {
|
||||
$hash->{BaseID} = "00000000";
|
||||
$hash->{LastID} = "00000000";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
# Write
|
||||
# Input is header and data (HEX), without CRC
|
||||
sub
|
||||
@ -113,7 +106,7 @@ TCM_Write($$$)
|
||||
return if(!defined($fn));
|
||||
|
||||
my $bstring;
|
||||
if($hash->{MODEL} eq "120") {
|
||||
if($hash->{MODEL} eq "ESP2") {
|
||||
# TCM 120 (ESP2)
|
||||
if (!$fn) {
|
||||
# command with ESP2 format
|
||||
@ -122,12 +115,12 @@ TCM_Write($$$)
|
||||
# command with ESP3 format
|
||||
my $packetType = hex(substr($fn, 6, 2));
|
||||
if ($packetType != 1) {
|
||||
Log3 $name, 1, "TCM $name: Packet Type not supported.";
|
||||
Log3 $name, 1, "TCM $name Packet Type not supported.";
|
||||
return;
|
||||
}
|
||||
my $odataLen = hex(substr($fn, 4, 2));
|
||||
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;
|
||||
}
|
||||
#my $mdataLen = hex(substr($fn, 0, 4));
|
||||
@ -140,7 +133,7 @@ TCM_Write($$$)
|
||||
if($rorgmap{$rorg}) {
|
||||
$rorg = $rorgmap{$rorg};
|
||||
} else {
|
||||
Log3 $name, 1, "TCM $name: unknown RORG mapping for $rorg";
|
||||
Log3 $name, 1, "TCM $name unknown RORG mapping for $rorg";
|
||||
}
|
||||
if ($rorg eq "05" || $rorg eq "06") {
|
||||
$bstring = "6B" . $rorg . substr ($msg, 2, 2) . "000000" . substr ($msg, 4);
|
||||
@ -155,6 +148,8 @@ TCM_Write($$$)
|
||||
}
|
||||
Log3 $name, 5, "TCM $name sending $bstring";
|
||||
DevIo_SimpleWrite($hash, $bstring, 1);
|
||||
# next commands will be sent with a delay
|
||||
usleep(int(AttrVal($name, "sendInterval", 100)));
|
||||
}
|
||||
|
||||
# ESP2 CRC
|
||||
@ -232,7 +227,7 @@ TCM_Read($)
|
||||
my $data = $hash->{PARTIAL} . uc(unpack('H*', $buf));
|
||||
Log3 $name, 5, "TCM $name RAW: $data";
|
||||
|
||||
if($hash->{MODEL} == 120) {
|
||||
if($hash->{MODEL} eq "ESP2") {
|
||||
# TCM 120
|
||||
|
||||
while($data =~ m/^A55A(.B.{20})(..)/) {
|
||||
@ -255,7 +250,6 @@ TCM_Read($)
|
||||
if($orgmap{$org}) {
|
||||
$org = $orgmap{$org};
|
||||
} else {
|
||||
#Log 1, "TCM120: unknown ORG mapping for $org";
|
||||
Log3 undef, 1, "TCM unknown ORG mapping for $org";
|
||||
}
|
||||
if ($org ne "A5") {
|
||||
@ -279,7 +273,6 @@ TCM_Read($)
|
||||
if($orgmap{$org}) {
|
||||
$org = $orgmap{$org};
|
||||
} else {
|
||||
#Log 1, "TCM120: unknown ORG mapping for $org";
|
||||
Log3 undef, 1, "TCM unknown ORG mapping for $org";
|
||||
}
|
||||
if ($org ne "A5") {
|
||||
@ -350,7 +343,6 @@ TCM_Read($)
|
||||
RSSI => -$RSSI,
|
||||
ReceivingQuality => $receivingQuality,
|
||||
RepeatingCounter => $repeatingCounter,
|
||||
SecurityLevel => hex($4),
|
||||
);
|
||||
$hash->{RSSI} = -$RSSI;
|
||||
|
||||
@ -374,7 +366,6 @@ TCM_Read($)
|
||||
"91" => "BASEID_MAX_REACHED",
|
||||
);
|
||||
$rc = $codes{$rc} if($codes{$rc});
|
||||
#Log (($rc eq "OK") ? $ll5 : $ll2, "TCM $name RESPONSE: $rc");
|
||||
Log3 ($name, ($rc eq "OK") ? 5 : 2, "TCM $name RESPONSE: $rc");
|
||||
|
||||
} elsif($packetType == 3) {
|
||||
@ -397,6 +388,14 @@ TCM_Read($)
|
||||
# packet type REMOTE_MAN_COMMAND
|
||||
Log3 $name, 1, "TCM: $name packet type REMOTE_MAN_COMMAND not supported: $data";
|
||||
|
||||
} elsif($packetType == 9) {
|
||||
# packet type RADIO_MESSAGE
|
||||
Log3 $name, 1, "TCM: $name packet type RADIO_MESSAGE not supported: $data";
|
||||
|
||||
} elsif($packetType == 10) {
|
||||
# packet type RADIO_ADVANCED
|
||||
Log3 $name, 1, "TCM: $name packet type RADIO_ADVANCED not supported: $data";
|
||||
|
||||
} else {
|
||||
Log3 $name, 1, "TCM $name unknown packet type $packetType: $data";
|
||||
|
||||
@ -445,15 +444,11 @@ TCM_Parse120($$$)
|
||||
{
|
||||
my ($hash,$rawmsg,$ret) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 5, "TCM Parse $rawmsg";
|
||||
|
||||
Log3 $name, 5, "TCM $name Parse $rawmsg";
|
||||
my $msg = "";
|
||||
my $cmd = $parsetbl120{substr($rawmsg, 0, 4)};
|
||||
|
||||
if(!$cmd) {
|
||||
$msg ="Unknown command: $rawmsg";
|
||||
|
||||
} else {
|
||||
if($cmd->{expr}) {
|
||||
$msg = $cmd->{msg}." " if(!$ret);
|
||||
@ -461,16 +456,12 @@ TCM_Parse120($$$)
|
||||
$rawstr =~ s/[\r\n]//g;
|
||||
my @a = map { ord($_) } split("", $rawstr);
|
||||
$msg .= eval $cmd->{expr};
|
||||
|
||||
} else {
|
||||
return "" if($cmd ->{msg} eq "OK" && !$ret); # SKIP Ok
|
||||
$msg = $cmd->{msg};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Log3 $name, 2, "TCM $name $msg" if(!$ret);
|
||||
Log3 $name, 2, "TCM $name RESPONSE: $msg" if(!$ret);
|
||||
return $msg;
|
||||
}
|
||||
|
||||
@ -495,7 +486,6 @@ TCM_Parse310($$$)
|
||||
Log3 $name, 5, "TCM Parse $rawmsg";
|
||||
my $rc = substr($rawmsg, 0, 2);
|
||||
my $msg = "";
|
||||
|
||||
if($rc ne "00") {
|
||||
$msg = $rc310{$rc};
|
||||
$msg = "Unknown return code $rc" if(!$msg);
|
||||
@ -506,16 +496,20 @@ TCM_Parse310($$$)
|
||||
my ($off, $len, $type) = split(",", $ptr->{$k});
|
||||
my $data = substr($rawmsg, $off*2, $len*2);
|
||||
$data = pack('H*', $data) if($type && $type eq "STR");
|
||||
push @ans, "$k=$data";
|
||||
#push @ans, "$k=$data";
|
||||
push @ans, "$k: $data";
|
||||
}
|
||||
$msg = join(",", @ans);
|
||||
$msg = join(" ", @ans);
|
||||
#$msg = join(",", @ans);
|
||||
}
|
||||
if ($msg eq "") {
|
||||
Log3 $name, 2, "TCM $name RESPONSE: OK";
|
||||
} else {
|
||||
Log3 $name, 2, "TCM $name RESPONSE: $msg";
|
||||
}
|
||||
|
||||
Log3 $name, 2, "TCM $name $msg";
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
||||
# Ready
|
||||
sub
|
||||
TCM_Ready($)
|
||||
@ -534,40 +528,30 @@ TCM_Ready($)
|
||||
# Get commands TCM 120
|
||||
my %gets120 = (
|
||||
"sensitivity" => "AB48",
|
||||
"idbase" => "AB58",
|
||||
"baseID" => "AB58",
|
||||
"modem_status" => "AB68",
|
||||
"sw_ver" => "AB4B",
|
||||
"version" => "AB4B",
|
||||
);
|
||||
|
||||
# Get commands TCM 310
|
||||
my %gets310 = (
|
||||
"sw_ver" => {cmd => "03",
|
||||
APPVersion => "1,4",
|
||||
APIVersion => "5,4",
|
||||
ChipID => "9,4",
|
||||
ChipVersion => "13,4",
|
||||
Desc => "17,16,STR",},
|
||||
"version" => {cmd => "03",
|
||||
APPVersion => "1,4",
|
||||
APIVersion => "5,4",
|
||||
ChipID => "9,4",
|
||||
ChipVersion => "13,4",
|
||||
Desc => "17,16,STR",},
|
||||
"idbase" => {cmd => "08",
|
||||
BaseID => "1,4",
|
||||
RemainingWriteCycles => "5,1",},
|
||||
"baseID" => {cmd => "08",
|
||||
BaseID => "1,4",
|
||||
RemainingWriteCycles => "5,1",},
|
||||
"repeater" => {cmd => "0A",
|
||||
repEnable => "1,1",
|
||||
repLevel => "2,1",},
|
||||
RepEnable => "1,1",
|
||||
RepLevel => "2,1",},
|
||||
# "secureDev" => {cmd => "1B01",
|
||||
# SLF => "1,1",
|
||||
# devID => "2,4",},
|
||||
"numSecureDev" => {cmd => "1D",
|
||||
number => "1,1",},
|
||||
Number => "1,1",},
|
||||
);
|
||||
|
||||
# Get
|
||||
@ -581,40 +565,33 @@ TCM_Get($@)
|
||||
my $cmd = $a[1];
|
||||
my ($err, $msg);
|
||||
|
||||
if($hash->{MODEL} eq "120") {
|
||||
if($hash->{MODEL} eq "ESP2") {
|
||||
# TCM 120
|
||||
my $rawcmd = $gets120{$cmd};
|
||||
return "Unknown argument $cmd, choose one of " .
|
||||
join(" ", sort keys %gets120) if(!defined($rawcmd));
|
||||
|
||||
Log3 $name, 2, "TCM get $name $cmd";
|
||||
$rawcmd .= "000000000000000000";
|
||||
TCM_Write($hash, "", $rawcmd);
|
||||
|
||||
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
|
||||
$msg = TCM_Parse120($hash, $msg, 1) if(!$err);
|
||||
|
||||
} else {
|
||||
# TCM 310
|
||||
my $cmdhash = $gets310{$cmd};
|
||||
return "Unknown argument $cmd, choose one of " .
|
||||
join(" ", sort keys %gets310) if(!defined($cmdhash));
|
||||
|
||||
Log3 $name, 2, "TCM get $name $cmd";
|
||||
my $cmdHex = $cmdhash->{cmd};
|
||||
TCM_Write($hash, sprintf("%04X0005", length($cmdHex)/2), $cmdHex);
|
||||
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
|
||||
$msg = TCM_Parse310($hash, $msg, $cmdhash) if(!$err);
|
||||
|
||||
}
|
||||
|
||||
if($err) {
|
||||
#Log 1, $err;
|
||||
Log3 undef, 1, $err;
|
||||
Log3 undef, 1, TCM $name $err;
|
||||
return $err;
|
||||
}
|
||||
$hash->{READINGS}{$cmd}{VAL} = $msg;
|
||||
$hash->{READINGS}{$cmd}{TIME} = TimeNow();
|
||||
readingsSingleUpdate($hash, $cmd, $msg, 1);
|
||||
return $msg;
|
||||
|
||||
}
|
||||
|
||||
# RemovePair
|
||||
@ -627,9 +604,7 @@ TCM_RemovePair($)
|
||||
|
||||
# Set commands TCM 120
|
||||
my %sets120 = ( # Name, Data to send to the CUL, Regexp for the answer
|
||||
"pairForSec" => { cmd => "AB18", arg => "\\d+" },
|
||||
"teach" => { cmd => "AB18", arg => "\\d+" },
|
||||
"idbase" => { cmd => "AB18", arg => "FF[8-9A-F][0-9A-F]{5}" },
|
||||
"baseID" => { cmd => "AB18", arg => "FF[8-9A-F][0-9A-F]{5}" },
|
||||
"sensitivity" => { cmd => "AB08", arg => "0[01]" },
|
||||
"sleep" => { cmd => "AB09" },
|
||||
@ -641,16 +616,15 @@ my %sets120 = ( # Name, Data to send to the CUL, Regexp for the answer
|
||||
|
||||
# Set commands TCM 310
|
||||
my %sets310 = (
|
||||
"pairForSec" => { cmd => "AB18", arg=> "\\d+" },
|
||||
"teach" => { cmd => "AB18", arg=> "\\d+" },
|
||||
"sleep" => { cmd => "01", arg => "00[0-9A-F]{6}" },
|
||||
"reset" => { cmd => "02" },
|
||||
"bist" => { cmd => "06", BIST_Result => "1,1", },
|
||||
"idbase" => { cmd => "07", arg => "FF[8-9A-F][0-9A-F]{5}" },
|
||||
"baseID" => { cmd => "07", arg => "FF[8-9A-F][0-9A-F]{5}" },
|
||||
"repeater" => { cmd => "09", arg => "0[0-1]0[0-2]" },
|
||||
"maturity" => { cmd => "10", arg => "0[0-1]" },
|
||||
"subtel" => { cmd => "11", arg => "0[0-1]" },
|
||||
"mode" => { cmd => "1C", arg => "0[0-1]" },
|
||||
);
|
||||
|
||||
# Set
|
||||
@ -665,7 +639,7 @@ TCM_Set($@)
|
||||
my $arg = $a[2];
|
||||
my ($err, $msg);
|
||||
|
||||
my $chash = ($hash->{MODEL} eq "120" ? \%sets120 : \%sets310);
|
||||
my $chash = ($hash->{MODEL} eq "ESP2" ? \%sets120 : \%sets310);
|
||||
my $cmdhash = $chash->{$cmd};
|
||||
return "Unknown argument $cmd, choose one of ".join(" ",sort keys %{$chash})
|
||||
if(!defined($cmdhash));
|
||||
@ -678,14 +652,15 @@ TCM_Set($@)
|
||||
if($arg !~ m/$argre/i);
|
||||
$cmdHex .= $arg;
|
||||
}
|
||||
Log3 $name, 2, "TCM set $name $cmd $arg";
|
||||
|
||||
if($cmd eq "pairForSec" || $cmd eq "teach") {
|
||||
if($cmd eq "teach") {
|
||||
$hash->{Teach} = 1;
|
||||
InternalTimer(gettimeofday()+$arg, "TCM_RemovePair", $hash, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if($hash->{MODEL} eq "120") {
|
||||
if($hash->{MODEL} eq "ESP2") {
|
||||
# TCM 120
|
||||
if($cmdHex eq "") { # wake is very special
|
||||
DevIo_SimpleWrite($hash, "AA", 1);
|
||||
@ -695,23 +670,29 @@ TCM_Set($@)
|
||||
$cmdHex .= "0"x(22-length($cmdHex)); # Padding with 0
|
||||
TCM_Write($hash, "", $cmdHex);
|
||||
($err, $msg) = TCM_ReadAnswer($hash, "get $cmd");
|
||||
$msg = TCM_Parse120($hash, $msg, 1)
|
||||
if(!$err);
|
||||
$msg = TCM_Parse120($hash, $msg, 1) if(!$err);
|
||||
|
||||
} else {
|
||||
# TCM310
|
||||
TCM_Write($hash, sprintf("%04X0005", length($cmdHex)/2), $cmdHex);
|
||||
($err, $msg) = TCM_ReadAnswer($hash, "set $cmd");
|
||||
$msg = TCM_Parse310($hash, $msg, $cmdhash)
|
||||
if(!$err);
|
||||
$msg = TCM_Parse310($hash, $msg, $cmdhash) if(!$err);
|
||||
|
||||
}
|
||||
|
||||
if($err) {
|
||||
#Log 1, $err;
|
||||
Log3 undef, 1, $err;
|
||||
Log3 undef, 1, "TCM $name $err";
|
||||
return $err;
|
||||
}
|
||||
|
||||
my @setCmdReadingsUpdate = ("repeater", "maturity", "mode");
|
||||
foreach(@setCmdReadingsUpdate) {
|
||||
if ($_ eq $cmd && $msg eq "") {
|
||||
if ($_ eq "repeater") {
|
||||
$arg = "RepEnable: " . substr($arg, 0, 2) . " RepLevel: " . substr($arg, 2, 2);
|
||||
}
|
||||
readingsSingleUpdate($hash, $cmd, $arg, 1);
|
||||
}
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
@ -757,9 +738,9 @@ TCM_ReadAnswer($$)
|
||||
|
||||
if(defined($buf)) {
|
||||
$data .= uc(unpack('H*', $buf));
|
||||
Log3 $name, 5, "TCM RAW ReadAnswer: $data";
|
||||
Log3 $name, 5, "TCM $name RAW ReadAnswer: $data";
|
||||
|
||||
if($hash->{MODEL} eq "120") {
|
||||
if($hash->{MODEL} eq "ESP2") {
|
||||
# TCM 120
|
||||
if(length($data) >= 28) {
|
||||
return ("$arg: Bogus answer received: $data", undef)
|
||||
@ -806,6 +787,7 @@ TCM_Attr(@) {
|
||||
|
||||
if ($attrName eq "blockSenderID") {
|
||||
if (!defined $attrVal) {
|
||||
|
||||
} elsif ($attrVal !~ m/^(own|no)$/) {
|
||||
Log3 $name, 2, "EnOcean $name attribute-value [$attrName] = $attrVal wrong";
|
||||
CommandDeleteAttr(undef, "$name $attrName");
|
||||
@ -819,6 +801,82 @@ TCM_Attr(@) {
|
||||
CommandDeleteAttr(undef, "$name $attrName");
|
||||
}
|
||||
|
||||
} elsif ($attrName eq "sendInterval") {
|
||||
if (!defined $attrVal){
|
||||
|
||||
} elsif (($attrVal + 0) < 0 || ($attrVal + 0) > 250) {
|
||||
Log3 $name, 2, "EnOcean $name attribute-value [$attrName] = $attrVal wrong or out of range";
|
||||
CommandDeleteAttr(undef, "$name $attrName");
|
||||
}
|
||||
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub TCM_Notify(@) {
|
||||
my ($hash, $dev) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
if ($dev->{NAME} eq "global" && grep (m/^INITIALIZED$/,@{$dev->{CHANGED}})){
|
||||
my $attrVal;
|
||||
my $setCmdVal = "";
|
||||
my @setCmd = ("set", "reset", $setCmdVal);
|
||||
# read and discard receive buffer, modem reset
|
||||
if ($hash->{MODEL} eq "ESP2") {
|
||||
} else {
|
||||
TCM_ReadAnswer($hash, "set reset");
|
||||
TCM_Set($hash, @setCmd);
|
||||
#usleep(200);
|
||||
}
|
||||
# default attributes
|
||||
my %setAttrInit = ("sendInterval" => {ESP2 => 100, ESP3 => 0});
|
||||
foreach(keys %setAttrInit) {
|
||||
$attrVal = AttrVal($name, $_, undef);
|
||||
if(!defined $attrVal && defined $setAttrInit{$_}{$hash->{MODEL}}) {
|
||||
$attr{$name}{$_} = $setAttrInit{$_}{$hash->{MODEL}};
|
||||
Log3 $name, 2, "TCM $name Attribute $_ $setAttrInit{$_}{$hash->{MODEL}} initialized";
|
||||
}
|
||||
}
|
||||
# default transceiver parameter
|
||||
my %setCmdRestore = ("mode" => "00",
|
||||
"maturity" => "01",
|
||||
"repeater" => "RepEnable: 00 RepLevel: 00"
|
||||
);
|
||||
foreach(keys %setCmdRestore) {
|
||||
$setCmdVal = ReadingsVal($name, $_, undef);
|
||||
if (defined $setCmdVal) {
|
||||
if ($_ eq "repeater") {
|
||||
$setCmdVal = substr($setCmdVal, 11, 2) . substr($setCmdVal, 24, 2);
|
||||
$setCmdVal = "0000" if ($setCmdVal eq "0001");
|
||||
}
|
||||
@setCmd = ("set", $_, $setCmdVal);
|
||||
TCM_Set($hash, @setCmd);
|
||||
Log3 $name, 2, "TCM $name $_ $setCmdVal restored";
|
||||
} else {
|
||||
if ($hash->{MODEL} eq "ESP2") {
|
||||
|
||||
} else {
|
||||
if ($_ eq "repeater") {
|
||||
$setCmdVal = substr($setCmdRestore{$_}, 11, 2) . substr($setCmdRestore{$_}, 24, 2);
|
||||
} else {
|
||||
$setCmdVal = $setCmdRestore{$_};
|
||||
}
|
||||
@setCmd = ("set", $_, $setCmdVal);
|
||||
my $msg = TCM_Set($hash, @setCmd);
|
||||
Log3 $name, 2, "TCM $name $_ $setCmdVal initialized" if ($msg eq "");
|
||||
}
|
||||
}
|
||||
}
|
||||
my @getBaseID = ("get", "baseID");
|
||||
if (TCM_Get($hash, @getBaseID) =~ /[Ff]{2}[\dA-Fa-f]{6}/ ) {
|
||||
$hash->{BaseID} = sprintf "%08X", hex $&;
|
||||
$hash->{LastID} = sprintf "%08X", (hex $&) + 127;
|
||||
} else {
|
||||
$hash->{BaseID} = "00000000";
|
||||
$hash->{LastID} = "00000000";
|
||||
}
|
||||
CommandSave(undef, undef);
|
||||
readingsSingleUpdate($hash, "state", "initialized", 1);
|
||||
Log3 $name, 2, "TCM $name initialized";
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@ -836,7 +894,6 @@ TCM_Undef($$)
|
||||
$defs{$d}{IODev} == $hash)
|
||||
{
|
||||
my $lev = ($reread_active ? 4 : 2);
|
||||
#Log GetLogLevel($name,$lev), "deleting port for $d";
|
||||
Log3 $name, $lev, "TCM deleting port for $d";
|
||||
delete $defs{$d}{IODev};
|
||||
}
|
||||
@ -853,14 +910,14 @@ TCM_Undef($$)
|
||||
<a name="TCM"></a>
|
||||
<h3>TCM</h3>
|
||||
<ul>
|
||||
The TCM module serves an USB or TCP/IP connected TCM120 or TCM310 EnOcean
|
||||
Transceiver module. These are mostly packaged together with a serial to USB
|
||||
chip and an antenna, e.g. the BSC BOR contains the TCM120, the <a
|
||||
The TCM module serves an USB or TCP/IP connected TCM 120 or TCM 310x, TCM 410J
|
||||
EnOcean Transceiver module. These are mostly packaged together with a serial to USB
|
||||
chip and an antenna, e.g. the BSC BOR contains the TCM 120, the <a
|
||||
href="http://www.enocean.com/de/enocean_module/usb-300-oem/">USB 300</a> from
|
||||
EnOcean and the EUL from busware contains a TCM310. See also the datasheet
|
||||
EnOcean and the EUL from busware contains a TCM 310. See also the datasheet
|
||||
available from <a href="http://www.enocean.com">www.enocean.com</a>.
|
||||
<br>
|
||||
As the TCM120 and the TCM310 speak completely different protocols, this
|
||||
As the TCM 120 and the TCM 310, TCM 410J speak completely different protocols, this
|
||||
module implements 2 drivers in one. It is the "physical" part for the <a
|
||||
href="#EnOcean">EnOcean</a> module.<br><br>
|
||||
Please note that EnOcean repeaters also send Fhem data telegrams again. Use
|
||||
@ -884,38 +941,37 @@ TCM_Undef($$)
|
||||
use event-on-update-reading. Use instead either event-on-change-reading or
|
||||
event-min-interval.
|
||||
The Eltako bus uses the EnOcean Serial Protocol version 2 (ESP2) protocol, which is
|
||||
the same serial protocol used by TCM120 modules. For this reason, a FGW14 can be
|
||||
configured as a TCM120.<br><br>
|
||||
the same serial protocol used by TCM 120 modules. For this reason, a FGW14 can be
|
||||
configured as a TCM 120.<br><br>
|
||||
|
||||
<a name="TCMdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> TCM [120|310] <device></code> <br>
|
||||
<code>define <name> TCM [ESP2|ESP3] <device></code> <br>
|
||||
<br>
|
||||
First you have to specify the type of the EnOcean Transceiver Chip, i.e
|
||||
either 120 for the TCM120 or 310 for the TCM310.<br><br>
|
||||
either ESP2 for the TCM 120 or ESP3 for the TCM 310x, TCM 410J, USB 300, USB400J.<br><br>
|
||||
<code>device</code> can take the same parameters (@baudrate, @directio,
|
||||
TCP/IP, none) like the <a href="#CULdefine">CUL</a>, but you probably have
|
||||
to specify the baudrate: the TCM120 should be opened with 9600 Baud, the
|
||||
TCM310 with 57600 baud. For Eltako FGW14 devices, type has to be set to 120 and
|
||||
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
|
||||
the baudrate has to be set to 57600 baud if the FGW14 operating mode
|
||||
rotary switch is on position 6.<br><br>
|
||||
|
||||
Example:
|
||||
<ul><code>
|
||||
define BscBor TCM 120 /dev/ttyACM0@9600<br>
|
||||
define FGW14 TCM 120 /dev/ttyS3@57600<br>
|
||||
define TCM310 TCM 310 /dev/ttyACM0@57600<br>
|
||||
define TCM310 TCM 310 COM1@57600 (Windows)<br>
|
||||
define BscBor TCM ESP2 /dev/ttyACM0@9600<br>
|
||||
define FGW14 TCM ESP2 /dev/ttyS3@57600<br>
|
||||
define TCM310 TCM ESP3 /dev/ttyACM0@57600<br>
|
||||
define TCM310 TCM ESP3 COM1@57600 (Windows)<br>
|
||||
</code></ul>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<a name="TCMset"></a>
|
||||
<b>Set</b><br>
|
||||
<ul><b>TCM 120</b><br>
|
||||
<li>idbase [FF800000 ... FFFFFF80]<br>
|
||||
<ul><b>ESP2 (TCM 120)</b><br>
|
||||
<li>baseID [FF800000 ... FFFFFF80]<br>
|
||||
Set the BaseID.<br>
|
||||
Note: The firmware executes this command only up to then times to prevent misuse.</li>
|
||||
<li>modem_off<br>
|
||||
@ -935,11 +991,11 @@ TCM_Undef($$)
|
||||
Enter the energy saving mode</li>
|
||||
<li>wake<br>
|
||||
Wakes up from sleep mode</li>
|
||||
<br><br>
|
||||
<br>
|
||||
For details see the TCM 120 User Manual available from <a href="http://www.enocean.com">www.enocean.com</a>.
|
||||
<br><br>
|
||||
</ul>
|
||||
<ul><b>TCM 310</b><br>
|
||||
<ul><b>ESP3 (TCM 310x, TCM 410J, USB 300, USB400J)</b><br>
|
||||
<li>baseID [FF800000 ... FFFFFF80]<br>
|
||||
Set the BaseID.<br>
|
||||
Note: The firmware executes this command only up to then times to prevent misuse.</li>
|
||||
@ -948,12 +1004,15 @@ TCM_Undef($$)
|
||||
<li>maturity [00|01]<br>
|
||||
Waiting till end of maturity time before received radio telegrams will transmit:
|
||||
radio telegrams are send immediately = 00, after the maturity time is elapsed = 01</li>
|
||||
<li>mode [00|01]<br>
|
||||
mode = 00: Compatible mode - ERP1 - gateway uses Packet Type 1 to transmit and receive radio telegrams<br>
|
||||
mode = 01: Advanced mode – ERP2 - gateway uses Packet Type 10 to transmit and receive radio telegrams
|
||||
(for FSK products with advanced protocol)</li>
|
||||
<li>teach <t/s><br>
|
||||
Set Fhem in learning mode, see <a href="#TCM_learningMode">learningMode</a>.<br>
|
||||
The command is always required for UTE and to teach-in bidirectional actuators
|
||||
e. g. EEP 4BS (RORG A5-20-XX),
|
||||
see <a href="#EnOcean_teach-in">Teach-In / Teach-Out</a>.</li>
|
||||
<li>reset<br>
|
||||
<li>reset<br>
|
||||
Reset the device</li>
|
||||
<li>repeater [0000|0101|0102]<br>
|
||||
Set Repeater Level: off = 0000, 1 = 0101, 2 = 0102.</li>
|
||||
@ -961,16 +1020,16 @@ TCM_Undef($$)
|
||||
Enter the energy saving mode</li>
|
||||
<li>subtel [00|01]<br>
|
||||
Transmitting additional subtelegram info: Enable = 01, Disable = 00</li>
|
||||
<br><br>
|
||||
<br>
|
||||
For details see the EnOcean Serial Protocol 3 (ESP3) available from
|
||||
<a href="http://www.enocean.com">www.enocean.com</a>.
|
||||
<br><br>
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
<a name="TCMget"></a>
|
||||
<b>Get</b><br>
|
||||
<ul><b>TCM 120</b><br>
|
||||
<li>idbase<br>
|
||||
<li>baseID<br>
|
||||
Get the BaseID. You need this command in order to control EnOcean devices,
|
||||
see the <a href="#EnOceandefine">EnOcean</a> paragraph.
|
||||
</li>
|
||||
@ -978,9 +1037,9 @@ TCM_Undef($$)
|
||||
Requests the current modem status.</li>
|
||||
<li>sensitivity<br>
|
||||
Get the TCM radio sensitivity, low = 00, high = 01</li>
|
||||
<li>sw_ver<br>
|
||||
<li>version<br>
|
||||
Read the device SW version / HW version, chip-ID, etc.</li>
|
||||
<br><br>
|
||||
<br>
|
||||
For details see the TCM 120 User Manual available from <a href="http://www.enocean.com">www.enocean.com</a>.
|
||||
<br><br>
|
||||
</ul>
|
||||
@ -994,7 +1053,7 @@ TCM_Undef($$)
|
||||
Read Repeater Level: off = 0000, 1 = 0101, 2 = 0102.</li>
|
||||
<li>version<br>
|
||||
Read the device SW version / HW version, chip-ID, etc.</li>
|
||||
<br><br>
|
||||
<br>
|
||||
For details see the EnOcean Serial Protocol 3 (ESP3) available from
|
||||
<a href="http://www.enocean.com">www.enocean.com</a>.
|
||||
<br><br>
|
||||
@ -1016,10 +1075,29 @@ TCM_Undef($$)
|
||||
[learningMode] = demand: Teach-In/Teach-Out telegrams accepted if Fhem is in learning mode, see also <code>set <IODev> teach <t/s></code><br>
|
||||
[learningMode] = nearfield: Teach-In/Teach-Out telegrams accepted if Fhem is in learning mode and the signal strength RSSI >= -60 dBm.<be>
|
||||
</li>
|
||||
<li><a name="TCM_sendInterval">sendInterval</a> <0 ... 250>,
|
||||
sendInterval = 100 ms is default.<br>
|
||||
Smallest interval between two sending telegrams
|
||||
</li>
|
||||
<li><a href="#verbose">verbose</a></li>
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
<a name="TCMevents"></a>
|
||||
<b>Generated events</b>
|
||||
<ul>
|
||||
<li>baseID <transceiver response></li>
|
||||
<li>maturity 00|01</li>
|
||||
<li>modem_status <transceiver response></li>
|
||||
<li>numSecureDev <transceiver response></li>
|
||||
<li>repeater 0000|0101|0102</li>
|
||||
<li>sensitivity 00|01</li>
|
||||
<li>version <transceiver response></li>
|
||||
<li>state: opend|initialized</li>
|
||||
<br><br>
|
||||
</ul>
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
=cut
|
||||
|