CUL_HM: pairing enhancement
git-svn-id: https://svn.fhem.de/fhem/trunk@11954 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -153,6 +153,10 @@ sub CUL_HM_Initialize($) {
|
||||
."autoReadReg:0_off,1_restart,2_pon-restart,3_onChange,4_reqStatus,5_readMissing,8_stateOnly "
|
||||
."burstAccess:0_off,1_auto "
|
||||
."msgRepeat "
|
||||
#General ."hmDstDly:slider,104,4,136 " # CUL destination answer delay
|
||||
#General ."hmPairAddDly:slider,-16,8,440 " # CUL additional destination delay for pair request
|
||||
#General ."SndThrRep:0,1 " # CUL force expectation of send through repeater
|
||||
#General ."RepBstAddDly:slider,0,8,600 " # CUL additional first answer delay for burst devices using repeater to device, 552 is a good value for HM-LC-SW1-BA-PCB
|
||||
."hmProtocolEvents:0_off,1_dump,2_dumpFull,3_dumpTrigger "
|
||||
."aesKey:5,4,3,2,1,0 "
|
||||
;
|
||||
@@ -222,12 +226,12 @@ sub CUL_HM_updateConfig($){
|
||||
foreach my $name (@{$modules{CUL_HM}{helper}{updtCfgLst}}){
|
||||
my $hash = $defs{$name};
|
||||
next if (!$hash->{DEF}); # likely renamed
|
||||
foreach my $read (grep/(RegL_0.:|_chn:\d\d)/,keys%{$defs{$name}{READINGS}}){
|
||||
foreach my $read (grep/(RegL_0.:|_chn:\d\d)/,keys%{$hash->{READINGS}}){
|
||||
my $readN = $read;
|
||||
$readN =~ s/(RegL_0.):/$1\./;
|
||||
$readN =~ s/_chn:(\d\d)/_chn-$1/;
|
||||
$defs{$name}{READINGS}{$readN} = $defs{$name}{READINGS}{$read};
|
||||
delete $defs{$name}{READINGS}{$read};
|
||||
$hash->{READINGS}{$readN} = $hash->{READINGS}{$read};
|
||||
delete $hash->{READINGS}{$read};
|
||||
}
|
||||
|
||||
my $id = $hash->{DEF};
|
||||
@@ -525,6 +529,7 @@ sub CUL_HM_Define($$) {##############################
|
||||
CUL_HM_assignIO($hash)if (!$init_done && $HMid ne "000000");
|
||||
}
|
||||
$modules{CUL_HM}{defptr}{$HMid} = $hash;
|
||||
$hash->{NOTIFYDEV} = "global";
|
||||
|
||||
#- - - - create auto-update - - - - - -
|
||||
CUL_HM_ActGetCreateHash() if($HMid eq '000000');#startTimer
|
||||
@@ -1060,7 +1065,7 @@ sub CUL_HM_Parse($$) {#########################################################
|
||||
DoTrigger("global","UNDEFINED $sname CUL_HM $mh{src}");
|
||||
$mh{devH} = CUL_HM_id2Hash($mh{src}); #sourcehash - changed to channel entity
|
||||
$mh{devH}->{IODev} = $iohash;
|
||||
$mh{devH}->{helper}{io}{nextSend} = gettimeofday()+0.09;# io couldn't set
|
||||
$mh{devH}->{helper}{io}{nextSend} = gettimeofday()+0.09 if(!defined($mh{devH}->{helper}{io}{nextSend}));# io couldn't set
|
||||
}
|
||||
|
||||
my @entities = ("global"); #additional entities with events to be notifies
|
||||
@@ -1111,7 +1116,7 @@ sub CUL_HM_Parse($$) {#########################################################
|
||||
}
|
||||
$respRemoved = 0; #set to 'no response in this message' at start
|
||||
$mh{devN} = $mh{devH}->{NAME}; #sourcehash - will be modified to channel entity
|
||||
$mh{shash} = $mh{devH}; # source device hash
|
||||
$mh{shash} = $mh{devH}; # source hash - will be redirected to channel if applicable
|
||||
my $ioId = CUL_HM_h2IoId($mh{devH}->{IODev});
|
||||
$ioId = $mh{id} if(!$ioId);
|
||||
if (CUL_HM_getAttrInt($mh{devN},"ignore")){
|
||||
@@ -1192,7 +1197,6 @@ sub CUL_HM_Parse($$) {#########################################################
|
||||
elsif ($mh{mTp} =~ m/^0[23]/) {
|
||||
$doAES = 0;
|
||||
}
|
||||
#FIXME: Extract channel from more messages
|
||||
|
||||
if ($doAES && $chn && defined(CUL_HM_id2Hash($mh{src}.sprintf("%02X",$chn)))) {
|
||||
CUL_HM_m_setCh(\%mh,$mI[0]);
|
||||
@@ -1333,10 +1337,11 @@ sub CUL_HM_Parse($$) {#########################################################
|
||||
|
||||
#----------start valid messages parsing ---------
|
||||
my $parse = CUL_HM_parseCommon($iohash,\%mh);
|
||||
|
||||
push @evtEt,[$mh{devH},1,"powerOn:$tn"] if($parse eq "powerOn");
|
||||
push @evtEt,[$mh{devH},1,""] if($parse eq "parsed"); # msg is parsed but may
|
||||
# be processed further
|
||||
$mh{devH}->{helper}{HM_CMDNR} = hex($mh{mNo});
|
||||
# be processed further
|
||||
|
||||
if ($parse eq "ACK" ||
|
||||
$parse eq "done" ){# remember - ACKinfo will be passed on
|
||||
push @evtEt,[$mh{devH},1,""];
|
||||
@@ -2803,11 +2808,12 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
# parsing commands that are device independent
|
||||
my ($ioHash,$mhp) = @_;
|
||||
|
||||
my ($p) =$mhp->{p};
|
||||
|
||||
return "" if(!$mhp->{shash}{DEF});# this should be from ourself
|
||||
return "" if(!$mhp->{devH}{DEF});# this should be from ourself
|
||||
|
||||
my ($p) = $mhp->{p};
|
||||
my $devHlpr = $mhp->{devH}{helper};
|
||||
my $ret = "";
|
||||
my $rspWait = $mhp->{shash}{helper}{prt}{rspWait};
|
||||
my $rspWait = $devHlpr->{prt}{rspWait};
|
||||
my $pendType = $rspWait->{Pending} ? $rspWait->{Pending} : "";
|
||||
#------------ parse message flag for start processing command Stack
|
||||
# TC wakes up with 8270, not with A258
|
||||
@@ -2822,62 +2828,63 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
CUL_HM_ProcessCmdStack($mhp->{devH});
|
||||
}
|
||||
}
|
||||
elsif($mhp->{devH}{helper}{prt}{sProc} != 1){ # no wakeup signal,
|
||||
elsif($devHlpr->{prt}{sProc} != 1){ # no wakeup signal,
|
||||
# this is an autonom message send ACK but dont process further
|
||||
$mhp->{devH}{helper}{prt}{sleeping} = 1 if($mhp->{mFlgH} & 0x20) ;
|
||||
$devHlpr->{prt}{sleeping} = 1 if($mhp->{mFlgH} & 0x20) ;
|
||||
}
|
||||
}
|
||||
if($rxt & 0x10 && $mhp->{devH}{helper}{prt}{sleeping}){ # lazy config
|
||||
if($rxt & 0x10 && $devHlpr->{prt}{sleeping}){ # lazy config
|
||||
if($mhp->{mFlgH} & 0x02 #wakeup device
|
||||
&& $defs{$mhp->{devH}{IODev}{NAME}}{TYPE} =~ m/^(HMLAN|HMUARTLGW)$/){
|
||||
$mhp->{devH}{helper}{io}{newCh} = 1 if ($mhp->{devH}{helper}{prt}{sProc} == 2);
|
||||
$devHlpr->{io}{newCh} = 1 if ($devHlpr->{prt}{sProc} == 2);
|
||||
CUL_HM_appFromQ($mhp->{devN},"cf");# stack cmds if waiting
|
||||
$mhp->{devH}{helper}{prt}{sleeping} = 0;
|
||||
$devHlpr->{prt}{sleeping} = 0;
|
||||
CUL_HM_ProcessCmdStack($mhp->{devH});
|
||||
}
|
||||
else{
|
||||
$mhp->{devH}{helper}{prt}{sleeping} = 1;
|
||||
$devHlpr->{prt}{sleeping} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$mhp->{devH}{helper}{PONtest} = 1 if($mhp->{mNo} eq "00" &&
|
||||
$mhp->{devH}{helper}{HM_CMDNR} < 250);# this is power on
|
||||
$devHlpr->{PONtest} = 1 if($mhp->{mNo} eq "00" &&
|
||||
$devHlpr->{HM_CMDNR} < 250);# this is power on
|
||||
$devHlpr->{HM_CMDNR} = hex($mhp->{mNo});# sync msgNo
|
||||
my $repeat;
|
||||
if ($mhp->{mTp} eq "02"){# Ack/Nack/aesReq ####################
|
||||
my $reply;
|
||||
my $success;
|
||||
|
||||
if ($mhp->{devH}{helper}{prt}{rspWait}{brstWu}){
|
||||
if ($mhp->{devH}{helper}{prt}{rspWait}{mNo} eq $mhp->{mNo} &&
|
||||
if ($devHlpr->{prt}{rspWait}{brstWu}){
|
||||
if ($devHlpr->{prt}{rspWait}{mNo} eq $mhp->{mNo} &&
|
||||
$mhp->{mStp} eq "00"){
|
||||
if ($mhp->{devH}{helper}{prt}{awake} && $mhp->{devH}{helper}{prt}{awake}==4){#re-burstWakeup
|
||||
delete $mhp->{devH}{helper}{prt}{rspWait};#clear burst-wakeup values
|
||||
$mhp->{devH}{helper}{prt}{rspWait}{$_} = $mhp->{devH}{helper}{prt}{rspWaitSec}{$_}
|
||||
foreach (keys%{$mhp->{devH}{helper}{prt}{rspWaitSec}}); #back to original message
|
||||
delete $mhp->{devH}{helper}{prt}{rspWaitSec};
|
||||
IOWrite($mhp->{devH}, "", $mhp->{devH}{helper}{prt}{rspWait}{cmd}); # and send
|
||||
if ($devHlpr->{prt}{awake} && $devHlpr->{prt}{awake}==4){#re-burstWakeup
|
||||
delete $devHlpr->{prt}{rspWait};#clear burst-wakeup values
|
||||
$devHlpr->{prt}{rspWait}{$_} = $devHlpr->{prt}{rspWaitSec}{$_}
|
||||
foreach (keys%{$devHlpr->{prt}{rspWaitSec}}); #back to original message
|
||||
delete $devHlpr->{prt}{rspWaitSec};
|
||||
IOWrite($mhp->{devH}, "", $devHlpr->{prt}{rspWait}{cmd}); # and send
|
||||
CUL_HM_statCnt($mhp->{devH}{IODev}{NAME},"s");
|
||||
return "done";
|
||||
}
|
||||
$mhp->{devH}{protCondBurst} = "on" if ( $mhp->{devH}{protCondBurst}
|
||||
&& $mhp->{devH}{protCondBurst} !~ m/forced/);
|
||||
$mhp->{devH}{helper}{prt}{awake}=2;#awake
|
||||
$devHlpr->{prt}{awake}=2;#awake
|
||||
}
|
||||
else{
|
||||
$mhp->{devH}{protCondBurst} = "off" if ( !$mhp->{devH}{protCondBurst}
|
||||
|| $mhp->{devH}{protCondBurst} !~ m/forced/);
|
||||
$mhp->{devH}{helper}{prt}{awake}=3;#reject
|
||||
$devHlpr->{prt}{awake}=3;#reject
|
||||
return "done";
|
||||
}
|
||||
}
|
||||
if (defined($mhp->{devH}{helper}{AESreqAck})) {
|
||||
if ($mhp->{devH}{helper}{AESreqAck} eq substr($mhp->{p}, -1 * length($mhp->{devH}{helper}{AESreqAck}))) {
|
||||
if (defined($devHlpr->{AESreqAck})) {
|
||||
if ($devHlpr->{AESreqAck} eq substr($mhp->{p}, -1 * length($devHlpr->{AESreqAck}))) {
|
||||
push @evtEt,[$mhp->{devH},1,"aesCommToDev:ok"];
|
||||
}
|
||||
else {
|
||||
push @evtEt,[$mhp->{devH},1,"aesCommToDev:fail"];
|
||||
}
|
||||
delete $mhp->{devH}{helper}{AESreqAck};
|
||||
delete $devHlpr->{AESreqAck};
|
||||
}
|
||||
|
||||
if ($mhp->{mStp} =~ m/^8/){#NACK
|
||||
@@ -2901,11 +2908,11 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
if ($rssi && $rssi ne '00' && $rssi ne'80');
|
||||
}
|
||||
$reply = "ACKStatus";
|
||||
if ($mhp->{devH}{helper}{tmdOn}){
|
||||
if ($devHlpr->{tmdOn}){
|
||||
if ((not hex(substr($mhp->{p},6,2))&0x40) && # not timedOn, we have to repeat
|
||||
$mhp->{devH}{helper}{tmdOn} eq substr($mhp->{p},2,2) ){# virtual channels for dimmer may be incorrect
|
||||
my ($pre,$nbr,$msg) = unpack 'A4A2A*',$mhp->{devH}{helper}{prt}{rspWait}{cmd};
|
||||
$mhp->{devH}{helper}{prt}{rspWait}{cmd} = sprintf("%s%02X%s",
|
||||
$devHlpr->{tmdOn} eq substr($mhp->{p},2,2) ){# virtual channels for dimmer may be incorrect
|
||||
my ($pre,$nbr,$msg) = unpack 'A4A2A*',$devHlpr->{prt}{rspWait}{cmd};
|
||||
$devHlpr->{prt}{rspWait}{cmd} = sprintf("%s%02X%s",
|
||||
$pre,hex($nbr)+1,$msg);
|
||||
CUL_HM_eventP($mhp->{devH},"TimedOn");
|
||||
$success = "no";
|
||||
@@ -2921,11 +2928,11 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
if (AttrVal($mhp->{devH}{IODev}{NAME},"rfmode","") eq "HomeMatic" &&
|
||||
defined($aesKeyNbr)) {
|
||||
if ($cryptFunc == 1 && #AES is available
|
||||
$mhp->{devH}{helper}{prt}{rspWait}{cmd}){ #There is a previously executed command
|
||||
$devHlpr->{prt}{rspWait}{cmd}){ #There is a previously executed command
|
||||
my (undef, %keys) = CUL_HM_getKeys($mhp->{devH});
|
||||
|
||||
my $kNo = hex($aesKeyNbr) / 2;
|
||||
Log3 $mhp->{devH},5,"CUL_HM $mhp->{devN} signing request for $mhp->{devH}{helper}{prt}{rspWait}{cmd} challenge: "
|
||||
Log3 $mhp->{devH},5,"CUL_HM $mhp->{devN} signing request for $devHlpr->{prt}{rspWait}{cmd} challenge: "
|
||||
.$challenge." kNo: ".$kNo;
|
||||
|
||||
if (!defined($keys{$kNo})) {
|
||||
@@ -2936,12 +2943,12 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
my $key = $keys{$kNo} ^ pack("H12", $challenge);
|
||||
my $cipher = Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_ECB());
|
||||
my($s,$us) = gettimeofday();
|
||||
my $respRaw = pack("NnH20", $s, $us, substr($mhp->{devH}{helper}{prt}{rspWait}{cmd}, 4, 20));
|
||||
my $respRaw = pack("NnH20", $s, $us, substr($devHlpr->{prt}{rspWait}{cmd}, 4, 20));
|
||||
my $response = $cipher->encrypt($respRaw);
|
||||
$mhp->{devH}{helper}{AESreqAck} = uc(unpack("H*", substr($response,0,4)));
|
||||
$devHlpr->{AESreqAck} = uc(unpack("H*", substr($response,0,4)));
|
||||
Log3 $mhp->{devH},5,"CUL_HM $mhp->{devN} signing response: ".unpack("H*", $respRaw)
|
||||
." should send $mhp->{devH}{helper}{AESreqAck} to authenticate";
|
||||
$response = $response ^ pack("H*", substr($mhp->{devH}{helper}{prt}{rspWait}{cmd}, 24));
|
||||
." should send $devHlpr->{AESreqAck} to authenticate";
|
||||
$response = $response ^ pack("H*", substr($devHlpr->{prt}{rspWait}{cmd}, 24));
|
||||
$response = $cipher->encrypt(substr($response, 0, 16));
|
||||
|
||||
CUL_HM_SndCmd($mhp->{devH}, $mhp->{mNo}.$mhp->{mFlg}.'03'.CUL_HM_IoId($mhp->{devH}).$mhp->{src}.unpack("H*", $response));
|
||||
@@ -2973,15 +2980,15 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
}
|
||||
}
|
||||
|
||||
if ( $mhp->{devH}{helper}{prt}{mmcS}
|
||||
&& $mhp->{devH}{helper}{prt}{mmcS} == 3){
|
||||
if ( $devHlpr->{prt}{mmcS}
|
||||
&& $devHlpr->{prt}{mmcS} == 3){
|
||||
# after write device might need a break
|
||||
# allow for wake types only - and if commands are pending
|
||||
$mhp->{devH}{helper}{prt}{try} = 1 if(CUL_HM_getRxType($mhp->{devH}) & 0x08 #wakeup
|
||||
$devHlpr->{prt}{try} = 1 if(CUL_HM_getRxType($mhp->{devH}) & 0x08 #wakeup
|
||||
&& $mhp->{devH}{cmdStack});
|
||||
if ($success eq 'yes'){
|
||||
delete $mhp->{devH}{helper}{prt}{mmcA};
|
||||
delete $mhp->{devH}{helper}{prt}{mmcS};
|
||||
delete $devHlpr->{prt}{mmcA};
|
||||
delete $devHlpr->{prt}{mmcS};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2992,8 +2999,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
$chnhash = $mhp->{devH} if(!$chnhash);
|
||||
push @evtEt,[$chnhash,0,"CommandAccepted:$success"];
|
||||
CUL_HM_ProcessCmdStack($mhp->{devH}) if(CUL_HM_IoId($mhp->{devH}) eq $mhp->{dst});
|
||||
delete $mhp->{devH}{helper}{prt}{wuReSent}
|
||||
if (!$mhp->{devH}{helper}{prt}{mmcS});
|
||||
delete $devHlpr->{prt}{wuReSent}
|
||||
if (!$devHlpr->{prt}{mmcS});
|
||||
}
|
||||
$ret = $reply;
|
||||
}
|
||||
@@ -3006,6 +3013,9 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
}
|
||||
|
||||
elsif($mhp->{mTp} eq "00"){######################################
|
||||
if (InternalVal($mhp->{devN},"lastMsg",undef) =~ m/t:00/){# repeated
|
||||
return "done"; # suppress handling of a repeated pair request
|
||||
}
|
||||
my $paired = 0; #internal flag
|
||||
CUL_HM_infoUpdtDevData($mhp->{devN}, $mhp->{devH},$mhp->{p})
|
||||
if (!$modules{CUL_HM}{helper}{hmManualOper});
|
||||
@@ -3029,8 +3039,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
delete $ioHash->{hmPairSerial};
|
||||
CUL_HM_respPendRm($mhp->{devH}); # remove all pending messages
|
||||
delete $mhp->{devH}{cmdStack};
|
||||
delete $mhp->{devH}{helper}{prt}{rspWait};
|
||||
delete $mhp->{devH}{helper}{prt}{rspWaitSec};
|
||||
delete $devHlpr->{prt}{rspWait};
|
||||
delete $devHlpr->{prt}{rspWaitSec};
|
||||
delete $mhp->{devH}{READINGS}{"RegL_00."};
|
||||
delete $mhp->{devH}{READINGS}{".RegL_00."};
|
||||
|
||||
@@ -3061,6 +3071,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
my $ioId = CUL_HM_h2IoId($mhp->{devH}{IODev});
|
||||
$respRemoved = 1;#force command stack processing
|
||||
}
|
||||
|
||||
$devHlpr->{HM_CMDNR} += 20; # force new setting. Send will take care of module 255
|
||||
$ret = "done";
|
||||
}
|
||||
elsif($mhp->{mTp} eq "10"){######################################
|
||||
@@ -3078,7 +3090,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
($rspWait->{mNo} == $mNoInt || $rspWait->{mNo} == $mNoInt-1)){
|
||||
$rspWait->{mNo} = $mNoInt;
|
||||
|
||||
my $chn = $mhp->{devH}{helper}{prt}{rspWait}{forChn};
|
||||
my $chn = $devHlpr->{prt}{rspWait}{forChn};
|
||||
my $chnhash = $modules{CUL_HM}{defptr}{$mhp->{src}.$chn};
|
||||
$chnhash = $mhp->{devH} if (!$chnhash);
|
||||
my $chnName = $chnhash->{NAME};
|
||||
@@ -3234,11 +3246,11 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
else{
|
||||
if ($mhp->{chn} == 0
|
||||
|| ( $mhp->{chn} == 1
|
||||
&& $mhp->{devH}{helper}{PONtest})){# this is power on
|
||||
&& $devHlpr->{PONtest})){# this is power on
|
||||
CUL_HM_qStateUpdatIfEnab($mhp->{devN});
|
||||
CUL_HM_qAutoRead($mhp->{devN},2);
|
||||
$ret = "powerOn" ;# check dst eq "000000" as well?
|
||||
$mhp->{devH}{helper}{PONtest} = 0;
|
||||
$devHlpr->{PONtest} = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3276,7 +3288,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
||||
&& $mhp->{dst} ne "000000"
|
||||
&& $mhp->{dst} ne $mhp->{id}){
|
||||
push @evtEt,[$mhp->{cHash},1,"triggerTo_$mhp->{dstN}:".(ucfirst($long))."_$cnt"];
|
||||
$mhp->{devH}{helper}{ack}{$mhp->{dstN}} = "$mhp->{cName}:$mhp->{mNo}";
|
||||
$devHlpr->{ack}{$mhp->{dstN}} = "$mhp->{cName}:$mhp->{mNo}";
|
||||
}
|
||||
}
|
||||
push @evtEt,[$mhp->{cHash},1,"trigger_cnt:$cnt"];
|
||||
@@ -3499,7 +3511,7 @@ sub CUL_HM_pushEvnts(){########################################################
|
||||
Log 2,"CUL_HM set reading invalid:".join(",",@{$e});
|
||||
next;
|
||||
}
|
||||
if ($h ne ${$e}[0] || $x ne ${$e}[1]){
|
||||
if ($h ne ${$e}[0] || $x ne ${$e}[1]){
|
||||
push @ent,CUL_HM_UpdtReadBulk($h,$x,@evts);
|
||||
@evts = ();
|
||||
($h,$x) = (${$e}[0],${$e}[1]);
|
||||
|
||||
Reference in New Issue
Block a user