mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
AES enhanvement HMLAN, preparation for condBurst r-wakeup
git-svn-id: https://svn.fhem.de/fhem/trunk@3968 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5fb3e461bd
commit
09ec5be2a6
@ -148,21 +148,34 @@ sub HMLAN_Attr(@) {#################################
|
|||||||
elsif($attrName =~ m /^hmKey/){
|
elsif($attrName =~ m /^hmKey/){
|
||||||
my $retVal= "";
|
my $retVal= "";
|
||||||
if ($cmd eq "set"){
|
if ($cmd eq "set"){
|
||||||
$attr{$name}{$attrName} = ($aVal =~ m /^[0-9A-Fa-f]{32}$/ )?
|
my $kno = ($attrName eq "hmKey")?1:substr($attrName,5,1);
|
||||||
$aVal:
|
my ($no,$val) = (sprintf("%02X",$kno),$aVal);
|
||||||
unpack('H*', md5($aVal));
|
if ($aVal =~ m/:/){#number given
|
||||||
|
($no,$val) = split ":",$aVal;
|
||||||
|
return "illegal number:$no" if (hex($no) < 1 || hex($no) > 255 || length($no) != 2);
|
||||||
|
}
|
||||||
|
$attr{$name}{$attrName} = "$no:".
|
||||||
|
(($val =~ m /^[0-9A-Fa-f]{32}$/ )?
|
||||||
|
$val:
|
||||||
|
unpack('H*', md5($val)));
|
||||||
$retVal = "$attrName set to $attr{$name}{$attrName}";
|
$retVal = "$attrName set to $attr{$name}{$attrName}";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
delete $attr{$name}{$attrName};
|
delete $attr{$name}{$attrName};
|
||||||
}
|
}
|
||||||
my ($k1,$k2,$k3) =( AttrVal($name,"hmKey","")
|
my ($k1no,$k1,$k2no,$k2,$k3no,$k3)
|
||||||
,AttrVal($name,"hmKey2","")
|
=( "01",AttrVal($name,"hmKey","")
|
||||||
,AttrVal($name,"hmKey3","")
|
,"02",AttrVal($name,"hmKey2","")
|
||||||
|
,"03",AttrVal($name,"hmKey3","")
|
||||||
);
|
);
|
||||||
HMLAN_SimpleWrite($defs{$name}, "Y01,".($k1?"01,$k1":"00,"));
|
|
||||||
HMLAN_SimpleWrite($defs{$name}, "Y02,".($k2?"02,$k2":"00,"));
|
if ($k1 =~ m/:/){($k1no,$k1) = split(":",$k1);}
|
||||||
HMLAN_SimpleWrite($defs{$name}, "Y03,".($k3?"03,$k3":"00,"));
|
if ($k2 =~ m/:/){($k2no,$k2) = split(":",$k2);}
|
||||||
|
if ($k3 =~ m/:/){($k3no,$k3) = split(":",$k3);}
|
||||||
|
|
||||||
|
HMLAN_SimpleWrite($defs{$name}, "Y01,".($k1?"$k1no,$k1":"00,"));
|
||||||
|
HMLAN_SimpleWrite($defs{$name}, "Y02,".($k2?"$k2no,$k2":"00,"));
|
||||||
|
HMLAN_SimpleWrite($defs{$name}, "Y03,".($k3?"$k3no,$k3":"00,"));
|
||||||
return $retVal;
|
return $retVal;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -567,17 +580,24 @@ sub HMLAN_DoInit($) {##########################################################
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
my $id = AttrVal($name, "hmId", undef);
|
my $id = AttrVal($name, "hmId", undef);
|
||||||
my $key = AttrVal($name, "hmKey", ""); # 36(!) hex digits
|
my ($k1no,$k1,$k2no,$k2,$k3no,$k3)
|
||||||
|
=( "01",AttrVal($name,"hmKey","")
|
||||||
|
,"02",AttrVal($name,"hmKey2","")
|
||||||
|
,"03",AttrVal($name,"hmKey3","")
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($k1 =~ m/:/){($k1no,$k1) = split(":",$k1);}
|
||||||
|
if ($k2 =~ m/:/){($k2no,$k2) = split(":",$k2);}
|
||||||
|
if ($k3 =~ m/:/){($k3no,$k3) = split(":",$k3);}
|
||||||
|
|
||||||
my $s2000 = sprintf("%02X", HMLAN_secSince2000());
|
my $s2000 = sprintf("%02X", HMLAN_secSince2000());
|
||||||
delete $hash->{READINGS}{state};
|
delete $hash->{READINGS}{state};
|
||||||
|
|
||||||
HMLAN_SimpleWrite($hash, "A$id") if($id);
|
HMLAN_SimpleWrite($hash, "A$id") if($id);
|
||||||
HMLAN_SimpleWrite($hash, "C");
|
HMLAN_SimpleWrite($hash, "C");
|
||||||
HMLAN_SimpleWrite($hash, "Y01,01,$key");
|
HMLAN_SimpleWrite($defs{$name}, "Y01,".($k1?"$k1no,$k1":"00,"));
|
||||||
HMLAN_SimpleWrite($hash, "Y02,00,");
|
HMLAN_SimpleWrite($defs{$name}, "Y02,".($k2?"$k2no,$k2":"00,"));
|
||||||
HMLAN_SimpleWrite($hash, "Y03,00,");
|
HMLAN_SimpleWrite($defs{$name}, "Y03,".($k3?"$k3no,$k3":"00,"));
|
||||||
HMLAN_SimpleWrite($hash, "Y03,00,");
|
|
||||||
HMLAN_SimpleWrite($hash, "T$s2000,04,00,00000000");
|
HMLAN_SimpleWrite($hash, "T$s2000,04,00,00000000");
|
||||||
delete $hash->{helper}{ref};
|
delete $hash->{helper}{ref};
|
||||||
|
|
||||||
|
@ -64,7 +64,6 @@ sub CUL_HM_respPendToutProlong($);
|
|||||||
sub CUL_HM_PushCmdStack($$);
|
sub CUL_HM_PushCmdStack($$);
|
||||||
sub CUL_HM_ProcessCmdStack($);
|
sub CUL_HM_ProcessCmdStack($);
|
||||||
sub CUL_HM_pushConfig($$$$$$$$@);
|
sub CUL_HM_pushConfig($$$$$$$$@);
|
||||||
sub CUL_HM_Resend($);
|
|
||||||
sub CUL_HM_ID2PeerList ($$$);
|
sub CUL_HM_ID2PeerList ($$$);
|
||||||
sub CUL_HM_peerChId($$$);
|
sub CUL_HM_peerChId($$$);
|
||||||
sub CUL_HM_peerChName($$$);
|
sub CUL_HM_peerChName($$$);
|
||||||
@ -328,6 +327,7 @@ sub CUL_HM_Define($$) {##############################
|
|||||||
else{# define a device
|
else{# define a device
|
||||||
$hash->{helper}{role}{dev}=1;
|
$hash->{helper}{role}{dev}=1;
|
||||||
$hash->{helper}{role}{chn}=1;# take role of chn 01 until it is defined
|
$hash->{helper}{role}{chn}=1;# take role of chn 01 until it is defined
|
||||||
|
CUL_HM_prtInit ($hash);
|
||||||
AssignIoPort($hash);
|
AssignIoPort($hash);
|
||||||
}
|
}
|
||||||
$modules{CUL_HM}{defptr}{$HMid} = $hash;
|
$modules{CUL_HM}{defptr}{$HMid} = $hash;
|
||||||
@ -851,6 +851,10 @@ sub CUL_HM_Parse($$) {##############################
|
|||||||
,3=>"adjustRangeTooSmall" , 4=>"communicationERR"
|
,3=>"adjustRangeTooSmall" , 4=>"communicationERR"
|
||||||
,5=>"unknown" , 6=>"lowBat" , 7=>"ValveErrorPosition" );
|
,5=>"unknown" , 6=>"lowBat" , 7=>"ValveErrorPosition" );
|
||||||
|
|
||||||
|
"measured-temp:$actTemp";
|
||||||
|
"desired-temp:$setTemp";
|
||||||
|
"ValvePosition:$vp %";
|
||||||
|
|
||||||
push @event, "motorErr:$errTbl{$err}";
|
push @event, "motorErr:$errTbl{$err}";
|
||||||
push @event, "measured-temp:$actTemp";
|
push @event, "measured-temp:$actTemp";
|
||||||
push @event, "desired-temp:$setTemp";
|
push @event, "desired-temp:$setTemp";
|
||||||
@ -862,6 +866,9 @@ sub CUL_HM_Parse($$) {##############################
|
|||||||
push @entities,CUL_HM_UpdtReadBulk($dHash,1
|
push @entities,CUL_HM_UpdtReadBulk($dHash,1
|
||||||
,"battery:".($err&0x80?"low":"ok")
|
,"battery:".($err&0x80?"low":"ok")
|
||||||
,"batteryLevel:$bat V"
|
,"batteryLevel:$bat V"
|
||||||
|
,"measured-temp:$actTemp" # values to please HCS
|
||||||
|
,"desired-temp:$setTemp"
|
||||||
|
,"actuator:$vp %"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elsif($mTp eq "59" && $p =~ m/^(..)/) {#inform team about new value
|
elsif($mTp eq "59" && $p =~ m/^(..)/) {#inform team about new value
|
||||||
@ -1319,7 +1326,7 @@ sub CUL_HM_Parse($$) {##############################
|
|||||||
#C7: tone off
|
#C7: tone off
|
||||||
#01: no alarm
|
#01: no alarm
|
||||||
my ($No,$state) = (substr($p,2,2),substr($p,4,2));
|
my ($No,$state) = (substr($p,2,2),substr($p,4,2));
|
||||||
if(($dhash && $dname ne $name) && # update source(ID is reported in $dst...)
|
if(($dhash && $dname ne $name) && # update source(ID reported in $dst)
|
||||||
(!$dhash->{helper}{alarmNo} || $dhash->{helper}{alarmNo} ne $No)){
|
(!$dhash->{helper}{alarmNo} || $dhash->{helper}{alarmNo} ne $No)){
|
||||||
$dhash->{helper}{alarmNo} = $No;
|
$dhash->{helper}{alarmNo} = $No;
|
||||||
push @entities,
|
push @entities,
|
||||||
@ -1518,8 +1525,8 @@ sub CUL_HM_Parse($$) {##############################
|
|||||||
sprintf("%02X",$vp*2)."0000";
|
sprintf("%02X",$vp*2)."0000";
|
||||||
}
|
}
|
||||||
elsif($mTp eq "02"){
|
elsif($mTp eq "02"){
|
||||||
if ($dhash->{helper}{respWait}{mNo} &&
|
if ($dhash->{helper}{prt}{rspWait}{mNo} &&
|
||||||
$dhash->{helper}{respWait}{mNo} eq $mNo ){
|
$dhash->{helper}{prt}{rspWait}{mNo} eq $mNo ){
|
||||||
#ack we waited for - stop Waiting
|
#ack we waited for - stop Waiting
|
||||||
CUL_HM_respPendRm($dhash);
|
CUL_HM_respPendRm($dhash);
|
||||||
}
|
}
|
||||||
@ -1575,8 +1582,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
my $dhash = $modules{CUL_HM}{defptr}{$dst};
|
my $dhash = $modules{CUL_HM}{defptr}{$dst};
|
||||||
return "" if(!$shash->{DEF});# this should be from ourself
|
return "" if(!$shash->{DEF});# this should be from ourself
|
||||||
my $ret = "";
|
my $ret = "";
|
||||||
my $pendType = $shash->{helper}{respWait}{Pending}?
|
my $pendType = $shash->{helper}{prt}{rspWait}{Pending}?
|
||||||
$shash->{helper}{respWait}{Pending}:"";
|
$shash->{helper}{prt}{rspWait}{Pending}:"";
|
||||||
#------------ parse message flag for start processing command Stack
|
#------------ parse message flag for start processing command Stack
|
||||||
# TC wakes up with 8270, not with A258
|
# TC wakes up with 8270, not with A258
|
||||||
# VD wakes up with 8202
|
# VD wakes up with 8202
|
||||||
@ -1596,13 +1603,16 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
my $reply;
|
my $reply;
|
||||||
my $success;
|
my $success;
|
||||||
|
|
||||||
if ($shash->{helper}{respWait}{wakeup}){
|
if ($shash->{helper}{prt}{rspWait}{wakeup}){
|
||||||
if ($shash->{helper}{respWait}{mNo} eq $mNo &&
|
if ($shash->{helper}{prt}{rspWait}{mNo} eq $mNo &&
|
||||||
$subType eq "00" ){
|
$subType eq "00" ){
|
||||||
$shash->{protCondBurst} = "on";
|
$shash->{protCondBurst} = "on";
|
||||||
|
$shash->{helper}{prt}{awake}=2;#awake
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
||||||
$shash->{protCondBurst} = "off";
|
$shash->{protCondBurst} = "off";
|
||||||
|
$shash->{helper}{prt}{awake}=3;#reject
|
||||||
return "done";
|
return "done";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1622,8 +1632,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
$reply = "ACKStatus";
|
$reply = "ACKStatus";
|
||||||
if ($shash->{helper}{tmdOn}){
|
if ($shash->{helper}{tmdOn}){
|
||||||
if (not hex(substr($p,6,2))&0x40){# not timedOn, we have to repeat
|
if (not hex(substr($p,6,2))&0x40){# not timedOn, we have to repeat
|
||||||
my ($pre,$nbr,$msg) = unpack 'A4A2A*',$shash->{helper}{respWait}{cmd};
|
my ($pre,$nbr,$msg) = unpack 'A4A2A*',$shash->{helper}{prt}{rspWait}{cmd};
|
||||||
$shash->{helper}{respWait}{cmd} = sprintf("%s%02X%s",
|
$shash->{helper}{prt}{rspWait}{cmd} = sprintf("%s%02X%s",
|
||||||
$pre,hex($nbr)+1,$msg);
|
$pre,hex($nbr)+1,$msg);
|
||||||
CUL_HM_eventP($shash,"TimedOn");
|
CUL_HM_eventP($shash,"TimedOn");
|
||||||
$success = "no";
|
$success = "no";
|
||||||
@ -1653,7 +1663,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
}
|
}
|
||||||
elsif($mTp eq "00"){######################################
|
elsif($mTp eq "00"){######################################
|
||||||
if ($pendType eq "PairSerial"){
|
if ($pendType eq "PairSerial"){
|
||||||
if($shash->{helper}{respWait}{forChn} = substr($p,6,20)){
|
if($shash->{helper}{prt}{rspWait}{forChn} = substr($p,6,20)){
|
||||||
CUL_HM_respPendRm($shash);
|
CUL_HM_respPendRm($shash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1673,7 +1683,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
}
|
}
|
||||||
elsif($subType eq "01"){ #storePeerList#################
|
elsif($subType eq "01"){ #storePeerList#################
|
||||||
if ($pendType eq "PeerList"){
|
if ($pendType eq "PeerList"){
|
||||||
my $chn = $shash->{helper}{respWait}{forChn};
|
my $chn = $shash->{helper}{prt}{rspWait}{forChn};
|
||||||
my $chnhash = $modules{CUL_HM}{defptr}{$src.$chn};
|
my $chnhash = $modules{CUL_HM}{defptr}{$src.$chn};
|
||||||
$chnhash = $shash if (!$chnhash);
|
$chnhash = $shash if (!$chnhash);
|
||||||
my $chnNname = $chnhash->{NAME};
|
my $chnNname = $chnhash->{NAME};
|
||||||
@ -1711,12 +1721,12 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
}
|
}
|
||||||
elsif($subType eq "02" ||$subType eq "03"){ #ParamResp==================
|
elsif($subType eq "02" ||$subType eq "03"){ #ParamResp==================
|
||||||
if ($pendType eq "RegisterRead"){
|
if ($pendType eq "RegisterRead"){
|
||||||
my $chnSrc = $src.$shash->{helper}{respWait}{forChn};
|
my $chnSrc = $src.$shash->{helper}{prt}{rspWait}{forChn};
|
||||||
my $chnHash = $modules{CUL_HM}{defptr}{$chnSrc};
|
my $chnHash = $modules{CUL_HM}{defptr}{$chnSrc};
|
||||||
$chnHash = $shash if (!$chnHash);
|
$chnHash = $shash if (!$chnHash);
|
||||||
my $chnName = $chnHash->{NAME};
|
my $chnName = $chnHash->{NAME};
|
||||||
my ($format,$data) = ($1,$2) if ($p =~ m/^(..)(.*)/);
|
my ($format,$data) = ($1,$2) if ($p =~ m/^(..)(.*)/);
|
||||||
my $list = $shash->{helper}{respWait}{forList};
|
my $list = $shash->{helper}{prt}{rspWait}{forList};
|
||||||
$list = "00" if (!$list); #use the default
|
$list = "00" if (!$list); #use the default
|
||||||
if ($format eq "02"){ # list 2: format aa:dd aa:dd ...
|
if ($format eq "02"){ # list 2: format aa:dd aa:dd ...
|
||||||
$data =~ s/(..)(..)/ $1:$2/g;
|
$data =~ s/(..)(..)/ $1:$2/g;
|
||||||
@ -1737,7 +1747,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $peer = $shash->{helper}{respWait}{forPeer};
|
my $peer = $shash->{helper}{prt}{rspWait}{forPeer};
|
||||||
my $regLNp = "RegL_$list:$peer";# pure, no expert
|
my $regLNp = "RegL_$list:$peer";# pure, no expert
|
||||||
my $regLN = ((CUL_HM_getAttrInt($chnName,"expert") == 2)?"":".").$regLNp;
|
my $regLN = ((CUL_HM_getAttrInt($chnName,"expert") == 2)?"":".").$regLNp;
|
||||||
readingsSingleUpdate($chnHash,$regLN,
|
readingsSingleUpdate($chnHash,$regLN,
|
||||||
@ -1801,7 +1811,7 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
@{$modules{CUL_HM}{helper}{reqStatus}} = grep { $_ ne $shash->{NAME} }
|
@{$modules{CUL_HM}{helper}{reqStatus}} = grep { $_ ne $shash->{NAME} }
|
||||||
@{$modules{CUL_HM}{helper}{reqStatus}};
|
@{$modules{CUL_HM}{helper}{reqStatus}};
|
||||||
if ($pendType eq "StatusReq"){#it is the answer to our request
|
if ($pendType eq "StatusReq"){#it is the answer to our request
|
||||||
my $chnSrc = $src.$shash->{helper}{respWait}{forChn};
|
my $chnSrc = $src.$shash->{helper}{prt}{rspWait}{forChn};
|
||||||
my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc};
|
my $chnhash = $modules{CUL_HM}{defptr}{$chnSrc};
|
||||||
$chnhash = $shash if (!$chnhash);
|
$chnhash = $shash if (!$chnhash);
|
||||||
CUL_HM_respPendRm($shash);
|
CUL_HM_respPendRm($shash);
|
||||||
@ -1848,8 +1858,8 @@ sub CUL_HM_parseCommon(@){#####################################################
|
|||||||
# CUL_HM_ProcessCmdStack($shash);
|
# CUL_HM_ProcessCmdStack($shash);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($shash->{helper}{respWait}{mNo} &&
|
if ($shash->{helper}{prt}{rspWait}{mNo} &&
|
||||||
$shash->{helper}{respWait}{mNo} eq $mNo &&
|
$shash->{helper}{prt}{rspWait}{mNo} eq $mNo &&
|
||||||
!$repeat){
|
!$repeat){
|
||||||
#response we waited for - stop Waiting
|
#response we waited for - stop Waiting
|
||||||
CUL_HM_respPendRm($shash);
|
CUL_HM_respPendRm($shash);
|
||||||
@ -3122,9 +3132,10 @@ sub CUL_HM_Set($@) {
|
|||||||
}
|
}
|
||||||
elsif(($rxType & 0x80) && #burstConditional - have a try
|
elsif(($rxType & 0x80) && #burstConditional - have a try
|
||||||
$devHash->{cmdStack} &&
|
$devHash->{cmdStack} &&
|
||||||
!$devHash->{helper}{respWait}{cmd} &&
|
!$devHash->{helper}{prt}{rspWait}{cmd}
|
||||||
!$devHash->{helper}{respWait}{Pending}
|
|
||||||
){
|
){
|
||||||
|
# Log 1,"General !!!!!! wakeup but stack processing $name" if($devHash->{helper}{prt}{sProc});
|
||||||
|
$hash->{helper}{prt}{awake}=1;# start wakeup
|
||||||
CUL_HM_SndCmd($devHash,"++B112$id$dst");
|
CUL_HM_SndCmd($devHash,"++B112$id$dst");
|
||||||
}
|
}
|
||||||
return ("",1);# no not generate trigger outof command
|
return ("",1);# no not generate trigger outof command
|
||||||
@ -3288,6 +3299,208 @@ sub CUL_HM_getConfig($$$$$){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#+++++++++++++++++ Protocol stack, sending, repeat+++++++++++++++++++++++++++++
|
#+++++++++++++++++ Protocol stack, sending, repeat+++++++++++++++++++++++++++++
|
||||||
|
sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
|
||||||
|
my ($hash,$src,$dst,$chn,$peerAddr,$peerChn,$list,$content,$prep) = @_;
|
||||||
|
my $flag = CUL_HM_getFlag($hash);
|
||||||
|
my $tl = length($content);
|
||||||
|
|
||||||
|
$chn = sprintf("%02X",$chn);
|
||||||
|
$peerChn = sprintf("%02X",$peerChn);
|
||||||
|
$list = sprintf("%02X",$list);
|
||||||
|
|
||||||
|
# --store pending changes in shadow to handle bit manipulations cululativ--
|
||||||
|
$peerAddr = "000000" if(!$peerAddr);
|
||||||
|
my $peerN = ($peerAddr ne "000000")?CUL_HM_peerChName($peerAddr.$peerChn,$dst,""):"";
|
||||||
|
$peerN =~ s/broadcast//;
|
||||||
|
$peerN =~ s/ /_/g;#remote blanks
|
||||||
|
my $regLN = ((CUL_HM_getAttrInt($hash->{NAME},"expert") == 2)?"":".").
|
||||||
|
"RegL_".$list.":".$peerN;
|
||||||
|
#--- copy data from readings to shadow
|
||||||
|
my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn};
|
||||||
|
$chnhash = $hash if (!$chnhash);
|
||||||
|
if (!$chnhash->{helper}{shadowReg} ||
|
||||||
|
!$chnhash->{helper}{shadowReg}{$regLN}){
|
||||||
|
$chnhash->{helper}{shadowReg}{$regLN} =
|
||||||
|
ReadingsVal($chnhash->{NAME},$regLN,"");
|
||||||
|
}
|
||||||
|
#--- update with ne value
|
||||||
|
my $regs = $chnhash->{helper}{shadowReg}{$regLN};
|
||||||
|
for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow
|
||||||
|
my $addr = substr($content,$l,2);
|
||||||
|
my $data = substr($content,$l+2,2);
|
||||||
|
if(!$regs || !($regs =~ s/$addr:../$addr:$data/)){
|
||||||
|
$regs .= " ".$addr.":".$data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$chnhash->{helper}{shadowReg}{$regLN} = $regs;
|
||||||
|
return if ($prep);#prepare shadowReg only. More data to come.
|
||||||
|
#Application takes care about execution
|
||||||
|
CUL_HM_updtRegDisp($hash,$list,$peerAddr.$peerChn);
|
||||||
|
CUL_HM_PushCmdStack($hash, "++".$flag.'01'.$src.$dst.$chn.'05'.
|
||||||
|
$peerAddr.$peerChn.$list);
|
||||||
|
for(my $l = 0; $l < $tl; $l+=28) {
|
||||||
|
my $ml = $tl-$l < 28 ? $tl-$l : 28;
|
||||||
|
CUL_HM_PushCmdStack($hash, "++A001".$src.$dst.$chn."08".
|
||||||
|
substr($content,$l,$ml));
|
||||||
|
}
|
||||||
|
CUL_HM_PushCmdStack($hash,"++A001".$src.$dst.$chn."06");
|
||||||
|
CUL_HM_queueAutoRead($hash->{NAME})
|
||||||
|
if (2 < CUL_HM_getAttrInt($hash->{NAME},"autoReadReg"));
|
||||||
|
}
|
||||||
|
sub CUL_HM_PushCmdStack($$) {
|
||||||
|
my ($chnhash, $cmd) = @_;
|
||||||
|
my @arr = ();
|
||||||
|
my $hash = CUL_HM_getDeviceHash($chnhash);
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
if(!$hash->{cmdStack}){
|
||||||
|
$hash->{cmdStack} = \@arr;
|
||||||
|
delete ($hash->{helper}{burstEvtCnt}) if (!$hash->{helper}{prt}{rspWait});
|
||||||
|
}
|
||||||
|
push(@{$hash->{cmdStack}}, $cmd);
|
||||||
|
my $entries = scalar @{$hash->{cmdStack}};
|
||||||
|
$hash->{protCmdPend} = $entries." CMDs_pending";
|
||||||
|
CUL_HM_protState($hash,"CMDs_pending") if(!$hash->{helper}{prt}{rspWait}{cmd});
|
||||||
|
}
|
||||||
|
sub CUL_HM_ProcessCmdStack($) {
|
||||||
|
my ($chnhash) = @_;
|
||||||
|
my $hash = CUL_HM_getDeviceHash($chnhash);
|
||||||
|
# Log 1,"General proc starting $hash->{NAME}" if($hash->{cmdStack} && !$hash->{helper}{prt}{sProc});
|
||||||
|
# Log 1,"General proc ERROR $hash->{NAME}" if($hash->{helper}{prt}{rspWait}{cmd} && !$hash->{helper}{prt}{sProc});
|
||||||
|
# General need to add wakeup here. Only one wakeup per stack processing!
|
||||||
|
|
||||||
|
if($hash->{cmdStack} && !$hash->{helper}{prt}{rspWait}{cmd}){
|
||||||
|
if(@{$hash->{cmdStack}}) {
|
||||||
|
# Log 1,"General proc send $hash->{NAME}";
|
||||||
|
CUL_HM_SndCmd($hash, shift @{$hash->{cmdStack}});
|
||||||
|
}
|
||||||
|
elsif(!@{$hash->{cmdStack}}) {
|
||||||
|
delete($hash->{cmdStack});
|
||||||
|
delete($hash->{protCmdPend});
|
||||||
|
#-- update info ---
|
||||||
|
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{burstEvtCnt}?
|
||||||
|
("_events:".$hash->{helper}{burstEvtCnt}):""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub CUL_HM_prtInit ($){ #setup protocol variables after define
|
||||||
|
my ($hash)=@_;
|
||||||
|
$hash->{helper}{prt}{sProc} = 0; # stack not being processed by now
|
||||||
|
}
|
||||||
|
sub CUL_HM_respWaitSu ($@){ #setup response for multi-message response
|
||||||
|
# single commands
|
||||||
|
# cmd: single msg that needs to be ACKed
|
||||||
|
# mNo: number of message (needs to be in ACK)
|
||||||
|
# mNoWu: number of message if wakeup
|
||||||
|
# reSent: number of resends already done - usually init with 1
|
||||||
|
# wakeup: was wakeup message (burst devices)
|
||||||
|
#
|
||||||
|
# commands with multi-message answer
|
||||||
|
# PendCmd: command message
|
||||||
|
# Pending: type of answer we are awaiting
|
||||||
|
# forChn: which channel are we working on?
|
||||||
|
# forList: which list are we waiting for? (optional)
|
||||||
|
# forPeer: which peer are we waiting for? (optional)
|
||||||
|
my ($hash,@a)=@_;
|
||||||
|
my $mHsh = $hash->{helper}{prt};
|
||||||
|
$modules{CUL_HM}{prot}{rspPend}++ if(!$mHsh->{rspWait}{cmd});
|
||||||
|
foreach (@a){
|
||||||
|
my ($f,$d)=split ":",$_;
|
||||||
|
$mHsh->{rspWait}{$f}=$d;
|
||||||
|
}
|
||||||
|
my $to = gettimeofday() + (($mHsh->{rspWait}{Pending})?rand(20)/10+4:
|
||||||
|
rand(40)/10+1);
|
||||||
|
InternalTimer($to,"CUL_HM_respPendTout","respPend:$hash->{DEF}", 0);
|
||||||
|
}
|
||||||
|
sub CUL_HM_responseSetup($$) {#store all we need to handle the response
|
||||||
|
#setup repeatTimer and cmdStackControll
|
||||||
|
my ($hash,$cmd) = @_;
|
||||||
|
my ($mNo,$mFlg,$mTp,$dst,$p) = ($2,hex($3),$4,$6,$7)
|
||||||
|
if ($cmd =~ m/As(..)(..)(..)(..)(......)(......)(.*)/);
|
||||||
|
my ($chn,$subType) = ($1,$2) if($p =~ m/^(..)(..)/);
|
||||||
|
# my $rTo = rand(20)/10+4; #default response timeout
|
||||||
|
if (($mFlg & 0x20) && ($dst ne '000000')){
|
||||||
|
if ($mTp eq "01" && $subType){
|
||||||
|
if ($subType eq "03"){ #PeerList-----------
|
||||||
|
#--- remember request params in device level
|
||||||
|
CUL_HM_respWaitSu ($hash,"Pending:PeerList"
|
||||||
|
,"cmd:$cmd" ,"forChn:".substr($p,0,2)
|
||||||
|
,"reSent:1");
|
||||||
|
|
||||||
|
#--- remove readings in channel
|
||||||
|
my $chnhash = $modules{CUL_HM}{defptr}{"$dst$chn"};
|
||||||
|
$chnhash = $hash if (!$chnhash);
|
||||||
|
delete $chnhash->{READINGS}{peerList};#empty old list
|
||||||
|
delete $chnhash->{peerList};#empty old list
|
||||||
|
delete $chnhash->{helper}{peerIDsRaw};
|
||||||
|
$attr{$chnhash->{NAME}}{peerIDs} = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elsif($subType eq "04"){ #RegisterRead-------
|
||||||
|
my ($peer, $list) = ($1,$2) if ($p =~ m/..04(........)(..)/);
|
||||||
|
$peer = ($peer ne "00000000")?CUL_HM_peerChName($peer,$dst,""):"";
|
||||||
|
#--- set messaging items
|
||||||
|
CUL_HM_respWaitSu ($hash,"Pending:RegisterRead"
|
||||||
|
,"cmd:$cmd" ,"forChn:$chn"
|
||||||
|
,"forList:$list","forPeer:$peer"
|
||||||
|
,"reSent:1");
|
||||||
|
#--- remove channel entries that will be replaced
|
||||||
|
my $chnhash = $modules{CUL_HM}{defptr}{"$dst$chn"};
|
||||||
|
$chnhash = $hash if(!$chnhash);
|
||||||
|
|
||||||
|
$peer ="" if($list !~ m/^0[34]$/);
|
||||||
|
#empty val since reading will be cumulative
|
||||||
|
my $rlName = ((CUL_HM_getAttrInt($chnhash->{NAME},"expert") == 2)?"":".")."RegL_".$list.":".$peer;
|
||||||
|
$chnhash->{READINGS}{$rlName}{VAL}="";
|
||||||
|
delete ($chnhash->{READINGS}{$rlName}{TIME});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
# elsif($subType eq "0A"){ #Pair Serial----------
|
||||||
|
# #--- set messaging items
|
||||||
|
# $hash->{helper}{prt}{rspWait}{Pending} = "PairSerial";
|
||||||
|
# $hash->{helper}{prt}{rspWait}{cmd} = $cmd;
|
||||||
|
# $hash->{helper}{prt}{rspWait}{forChn} = substr($p,4,20);
|
||||||
|
#
|
||||||
|
# # define timeout - holdup cmdStack until response complete or timeout
|
||||||
|
# InternalTimer(gettimeofday()+$rTo, "CUL_HM_respPendTout", "respPend:$dst", 0);
|
||||||
|
# return;
|
||||||
|
# }
|
||||||
|
}
|
||||||
|
elsif($mTp eq '11' && $chn =~ m/^(02|81)$/){#!!! chn is subtype!!!
|
||||||
|
CUL_HM_qStateUpdatIfEnab($dst);
|
||||||
|
}
|
||||||
|
elsif($mTp eq '12' && $mFlg & 0x10){#wakeup with burst
|
||||||
|
# response setup - do not repeat, set counter to 250
|
||||||
|
CUL_HM_respWaitSu ($hash,"cmd:$cmd","mNo:$mNo","reSent:250","wakeup:1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mTp eq "11" && $p =~ m/02..(..)....(....)/){#lvl ne 0 and timer on
|
||||||
|
$hash->{helper}{tmdOn} = $2 if ($1 ne "00" && $2 !~ m/(0000|FFFF)/);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUL_HM_respWaitSu ($hash,"cmd:$cmd","mNo:$mNo","reSent:1");
|
||||||
|
CUL_HM_protState($hash,"CMDs_processing...");
|
||||||
|
}
|
||||||
|
else{# no answer expected
|
||||||
|
if($hash->{cmdStack} && scalar @{$hash->{cmdStack}}){
|
||||||
|
CUL_HM_protState($hash,"CMDs_processing...");
|
||||||
|
InternalTimer(gettimeofday()+.5, "CUL_HM_ProcessCmdStack", $hash, 0);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{burstEvtCnt}?
|
||||||
|
("_events:".$hash->{helper}{burstEvtCnt}):""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($hash->{cmdStack} && scalar @{$hash->{cmdStack}}){
|
||||||
|
$hash->{protCmdPend} = scalar @{$hash->{cmdStack}}." CMDs pending";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
delete($hash->{protCmdPend});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub CUL_HM_sndIfOpen($) {
|
sub CUL_HM_sndIfOpen($) {
|
||||||
my(undef,$io) = split(':',$_[0]);
|
my(undef,$io) = split(':',$_[0]);
|
||||||
RemoveInternalTimer("sndIfOpen:$io");# should not be necessary, but
|
RemoveInternalTimer("sndIfOpen:$io");# should not be necessary, but
|
||||||
@ -3383,103 +3596,58 @@ sub CUL_HM_SndCmd($$) {
|
|||||||
$cmd =~ m/As(..)(..)(..)(..)(......)(......)(.*)/;
|
$cmd =~ m/As(..)(..)(..)(..)(......)(......)(.*)/;
|
||||||
CUL_HM_DumpProtocol("SND", $io, ($1,$2,$3,$4,$5,$6,$7));
|
CUL_HM_DumpProtocol("SND", $io, ($1,$2,$3,$4,$5,$6,$7));
|
||||||
}
|
}
|
||||||
sub CUL_HM_respWaitSu ($@){ #setup response for multi-message response
|
|
||||||
my ($hash,@a)=@_;
|
|
||||||
# my $hashW = $hash->{helper}{respWait};
|
|
||||||
$modules{CUL_HM}{prot}{rspPend}++ if(!$hash->{helper}{respWait}{PendCmd} &&
|
|
||||||
!$hash->{helper}{respWait}{cmd});
|
|
||||||
foreach (@a){
|
|
||||||
my ($f,$d)=split ":",$_;
|
|
||||||
$hash->{helper}{respWait}{$f}=$d;
|
|
||||||
}
|
|
||||||
if ($hash->{helper}{respWait}{cmd}){InternalTimer(gettimeofday()+rand(40)/10+1,"CUL_HM_Resend" , $hash, 0);}
|
|
||||||
else{ InternalTimer(gettimeofday()+rand(20)/10+4,"CUL_HM_respPendTout","respPend:$hash->{DEF}", 0);}
|
|
||||||
}
|
|
||||||
sub CUL_HM_responseSetup($$) {#store all we need to handle the response
|
|
||||||
#setup repeatTimer and cmdStackControll
|
|
||||||
my ($hash,$cmd) = @_;
|
|
||||||
my ($mNo,$mFlg,$mTp,$dst,$p) = ($2,hex($3),$4,$6,$7)
|
|
||||||
if ($cmd =~ m/As(..)(..)(..)(..)(......)(......)(.*)/);
|
|
||||||
my ($chn,$subType) = ($1,$2) if($p =~ m/^(..)(..)/);
|
|
||||||
# my $rTo = rand(20)/10+4; #default response timeout
|
|
||||||
if (($mFlg & 0x20) && ($dst ne '000000')){
|
|
||||||
if ($mTp eq "01" && $subType){
|
|
||||||
if ($subType eq "03"){ #PeerList-----------
|
|
||||||
#--- remember request params in device level
|
|
||||||
CUL_HM_respWaitSu ($hash,"Pending:PeerList"
|
|
||||||
,"PendCmd:$cmd" ,"forChn:".substr($p,0,2));
|
|
||||||
|
|
||||||
#--- remove readings in channel
|
sub CUL_HM_respPendRm($) {#del response related entries in messageing entity
|
||||||
my $chnhash = $modules{CUL_HM}{defptr}{"$dst$chn"};
|
my ($hash) = @_;
|
||||||
$chnhash = $hash if (!$chnhash);
|
$modules{CUL_HM}{prot}{rspPend}-- if($hash->{helper}{prt}{rspWait}{cmd});
|
||||||
delete $chnhash->{READINGS}{peerList};#empty old list
|
delete ($hash->{helper}{prt}{rspWait});
|
||||||
delete $chnhash->{peerList};#empty old list
|
delete $hash->{helper}{tmdOn};
|
||||||
delete $chnhash->{helper}{peerIDsRaw};
|
RemoveInternalTimer($hash); # remove resend-timer
|
||||||
$attr{$chnhash->{NAME}}{peerIDs} = '';
|
RemoveInternalTimer("respPend:$hash->{DEF}");# remove responsePending timer
|
||||||
return;
|
$respRemoved = 1;
|
||||||
}
|
}
|
||||||
elsif($subType eq "04"){ #RegisterRead-------
|
sub CUL_HM_respPendTout($) {
|
||||||
my ($peer, $list) = ($1,$2) if ($p =~ m/..04(........)(..)/);
|
my ($HMid) = @_;
|
||||||
$peer = ($peer ne "00000000")?CUL_HM_peerChName($peer,$dst,""):"";
|
(undef,$HMid) = split(":",$HMid,2);
|
||||||
#--- set messaging items
|
my $hash = $modules{CUL_HM}{defptr}{$HMid};
|
||||||
CUL_HM_respWaitSu ($hash,"Pending:RegisterRead"
|
my $pHash = $hash->{helper}{prt};#shortcut
|
||||||
,"PendCmd:$cmd" ,"forChn:$chn"
|
|
||||||
,"forList:$list","forPeer:$peer");
|
|
||||||
#--- remove channel entries that will be replaced
|
|
||||||
my $chnhash = $modules{CUL_HM}{defptr}{"$dst$chn"};
|
|
||||||
$chnhash = $hash if(!$chnhash);
|
|
||||||
|
|
||||||
$peer ="" if($list !~ m/^0[34]$/);
|
if ($hash && $hash->{DEF} ne '000000'){
|
||||||
#empty val since reading will be cumulative
|
my $name = $hash->{NAME};
|
||||||
my $rlName = ((CUL_HM_getAttrInt($chnhash->{NAME},"expert") == 2)?"":".")."RegL_".$list.":".$peer;
|
$pHash->{awake} = 0 if (defined $pHash->{awake});# set to asleep
|
||||||
$chnhash->{READINGS}{$rlName}{VAL}="";
|
return if(!$pHash->{rspWait}{reSent}); # Double timer?
|
||||||
delete ($chnhash->{READINGS}{$rlName}{TIME});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
# elsif($subType eq "0A"){ #Pair Serial----------
|
|
||||||
# #--- set messaging items
|
|
||||||
# $hash->{helper}{respWait}{Pending} = "PairSerial";
|
|
||||||
# $hash->{helper}{respWait}{PendCmd} = $cmd;
|
|
||||||
# $hash->{helper}{respWait}{forChn} = substr($p,4,20);
|
|
||||||
#
|
|
||||||
# # define timeout - holdup cmdStack until response complete or timeout
|
|
||||||
# InternalTimer(gettimeofday()+$rTo, "CUL_HM_respPendTout", "respPend:$dst", 0);
|
|
||||||
# return;
|
|
||||||
# }
|
|
||||||
}
|
|
||||||
elsif($mTp eq '11' && $chn =~ m/^(02|81)$/){#!!! chn is subtype!!!
|
|
||||||
CUL_HM_qStateUpdatIfEnab($dst);
|
|
||||||
}
|
|
||||||
elsif($mTp eq '12' && $mFlg & 0x10){#wakeup with burst
|
|
||||||
# response setup - do not repeat, set counter to 250
|
|
||||||
CUL_HM_respWaitSu ($hash,"cmd:$cmd","mNo:$mNo","reSent:250","wakeup:1");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($mTp eq "11" && $p =~ m/02..(..)....(....)/){#lvl ne 0 and timer on
|
if ($pHash->{rspWait}{reSent} > AttrVal($hash->{NAME},"msgRepeat",3)
|
||||||
$hash->{helper}{tmdOn} = $2 if ($1 ne "00" && $2 !~ m/(0000|FFFF)/);
|
&&( ((CUL_HM_getRxType($hash) & 0x03) != 0)#to slow for wakeup/config
|
||||||
}
|
||($hash->{protCondBurst}&&$hash->{protCondBurst} eq "on" ))){
|
||||||
|
if ($pHash->{rspWait}{wakeup}){
|
||||||
CUL_HM_respWaitSu ($hash,"cmd:$cmd","mNo:$mNo","reSent:1");
|
CUL_HM_respPendRm($hash);# do not count problems with wakeup try, just wait
|
||||||
CUL_HM_protState($hash,"CMDs_processing...");
|
$hash->{protCondBurst} = "off";
|
||||||
}
|
|
||||||
else{# no answer expected
|
|
||||||
if($hash->{cmdStack} && scalar @{$hash->{cmdStack}}){
|
|
||||||
CUL_HM_protState($hash,"CMDs_processing...");
|
|
||||||
InternalTimer(gettimeofday()+.5, "CUL_HM_ProcessCmdStack", $hash, 0);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{burstEvtCnt}?
|
my $pendCmd = ($pHash->{rspWait}{Pending}
|
||||||
("_events:".$hash->{helper}{burstEvtCnt}):""));
|
?"RESPONSE TIMEOUT:".$pHash->{rspWait}{Pending}
|
||||||
|
:"MISSING ACK");# save before remove
|
||||||
|
CUL_HM_eventP($hash,"ResndFail");
|
||||||
|
readingsSingleUpdate($hash,"state",$pendCmd,1);
|
||||||
|
CUL_HM_ProcessCmdStack($hash); # continue processing commands if any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($hash->{cmdStack} && scalar @{$hash->{cmdStack}}){
|
|
||||||
$hash->{protCmdPend} = scalar @{$hash->{cmdStack}}." CMDs pending";
|
|
||||||
}
|
|
||||||
else{
|
else{
|
||||||
delete($hash->{protCmdPend});
|
CUL_HM_eventP($hash,"Resnd");
|
||||||
|
IOWrite($hash, "", $pHash->{rspWait}{cmd});
|
||||||
|
$pHash->{rspWait}{reSent}++;
|
||||||
|
Log GetLogLevel($name,4),"CUL_HM_Resend: ".$name. " nr ".$pHash->{rspWait}{reSent};
|
||||||
|
InternalTimer(gettimeofday()+rand(20)/10+4,"CUL_HM_respPendTout","respPend:$hash->{DEF}", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
sub CUL_HM_respPendToutProlong($) {#used when device sends part responses
|
||||||
|
my ($hash) = @_;
|
||||||
|
RemoveInternalTimer("respPend:$hash->{DEF}");
|
||||||
|
InternalTimer(gettimeofday()+1, "CUL_HM_respPendTout", "respPend:$hash->{DEF}", 0);
|
||||||
|
}
|
||||||
|
|
||||||
sub CUL_HM_eventP($$) {#handle protocol events
|
sub CUL_HM_eventP($$) {#handle protocol events
|
||||||
# Current Events are Rcv,NACK,IOerr,Resend,ResendFail,Snd
|
# Current Events are Rcv,NACK,IOerr,Resend,ResendFail,Snd
|
||||||
# additional variables are protCmdDel,protCmdPend,protState,protLastRcv
|
# additional variables are protCmdDel,protCmdPend,protState,protLastRcv
|
||||||
@ -3519,152 +3687,16 @@ sub CUL_HM_protState($$){
|
|||||||
Log GetLogLevel($name,6),"CUL_HM $name protEvent:$state".
|
Log GetLogLevel($name,6),"CUL_HM $name protEvent:$state".
|
||||||
($hash->{cmdStack}?" pending:".scalar @{$hash->{cmdStack}}:"");
|
($hash->{cmdStack}?" pending:".scalar @{$hash->{cmdStack}}:"");
|
||||||
|
|
||||||
DoTrigger($name, undef) if ($state =~ m/^CMDs_done/);
|
if ($state =~ m/^CMDs_done/){ DoTrigger($name, undef);
|
||||||
|
$hash->{helper}{prt}{sProc} = 0;
|
||||||
|
$hash->{helper}{prt}{awake} = 0 if (defined$hash->{helper}{prt}{awake}); # asleep
|
||||||
|
# Log 1,"General StackFinished $hash->{NAME}";
|
||||||
}
|
}
|
||||||
sub CUL_HM_respPendRm($) {#del response related entries in messageing entity
|
elsif($state =~ m/processing/){ $hash->{helper}{prt}{sProc} = 1;
|
||||||
my ($hash) = @_;
|
# Log 1,"General StackProces $hash->{NAME}";
|
||||||
$modules{CUL_HM}{prot}{rspPend}-- if( $hash->{helper}{respWait}{cmd}
|
|
||||||
||$hash->{helper}{respWait}{PendCmd});
|
|
||||||
delete ($hash->{helper}{respWait});
|
|
||||||
delete $hash->{helper}{tmdOn};
|
|
||||||
RemoveInternalTimer($hash); # remove resend-timer
|
|
||||||
RemoveInternalTimer("respPend:$hash->{DEF}");# remove responsePending timer
|
|
||||||
$respRemoved = 1;
|
|
||||||
}
|
}
|
||||||
sub CUL_HM_respPendTout($) {
|
elsif($state eq "Info_Cleared"){$hash->{helper}{prt}{sProc} = 0;
|
||||||
my ($HMid) = @_;
|
# Log 1,"General StackCleared $hash->{NAME}";
|
||||||
$HMid =~ s/.*://; #remove timer identifier
|
|
||||||
my $hash = $modules{CUL_HM}{defptr}{$HMid};
|
|
||||||
if ($hash && $hash->{DEF} ne '000000'){
|
|
||||||
my $pendCmd = $hash->{helper}{respWait}{Pending};# secure before remove
|
|
||||||
|
|
||||||
my $pendRsndCnt = $hash->{helper}{respWait}{PendingRsend};
|
|
||||||
$pendRsndCnt = 1 if (!$pendRsndCnt); #already one send done
|
|
||||||
if ($pendRsndCnt < 5 && # some retries
|
|
||||||
((CUL_HM_getRxType($hash) & 0x03) != 0 || # to slow for wakeup/config
|
|
||||||
($hash->{protCondBurst}&&$hash->{protCondBurst} eq "on" ))){
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
Log GetLogLevel($name,4),"CUL_HM_Resend: ".$name. " nr ".$pendRsndCnt;
|
|
||||||
$hash->{helper}{respWait}{PendingRsend} = $pendRsndCnt + 1;
|
|
||||||
CUL_HM_SndCmd($hash,substr($hash->{helper}{respWait}{PendCmd},4));
|
|
||||||
CUL_HM_eventP($hash,"Resnd");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
CUL_HM_eventP($hash,"ResndFail");
|
|
||||||
CUL_HM_ProcessCmdStack($hash); # continue processing commands
|
|
||||||
readingsSingleUpdate($hash,"state","RESPONSE TIMEOUT:".$pendCmd,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sub CUL_HM_respPendToutProlong($) {#used when device sends part responses
|
|
||||||
my ($hash) = @_;
|
|
||||||
RemoveInternalTimer("respPend:$hash->{DEF}");
|
|
||||||
InternalTimer(gettimeofday()+1, "CUL_HM_respPendTout", "respPend:$hash->{DEF}", 0);
|
|
||||||
}
|
|
||||||
sub CUL_HM_PushCmdStack($$) {
|
|
||||||
my ($chnhash, $cmd) = @_;
|
|
||||||
my @arr = ();
|
|
||||||
my $hash = CUL_HM_getDeviceHash($chnhash);
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
if(!$hash->{cmdStack}){
|
|
||||||
$hash->{cmdStack} = \@arr;
|
|
||||||
delete ($hash->{helper}{burstEvtCnt}) if (!$hash->{helper}{respWait});
|
|
||||||
}
|
|
||||||
push(@{$hash->{cmdStack}}, $cmd);
|
|
||||||
my $entries = scalar @{$hash->{cmdStack}};
|
|
||||||
$hash->{protCmdPend} = $entries." CMDs_pending";
|
|
||||||
CUL_HM_protState($hash,"CMDs_pending")
|
|
||||||
if (!$hash->{helper}{respWait}{cmd} &&
|
|
||||||
!$hash->{helper}{respWait}{Pending});
|
|
||||||
}
|
|
||||||
sub CUL_HM_ProcessCmdStack($) {
|
|
||||||
my ($chnhash) = @_;
|
|
||||||
my $hash = CUL_HM_getDeviceHash($chnhash);
|
|
||||||
if($hash->{cmdStack} && !$hash->{helper}{respWait}{cmd} &&
|
|
||||||
!$hash->{helper}{respWait}{Pending}){
|
|
||||||
if(@{$hash->{cmdStack}}) {
|
|
||||||
CUL_HM_SndCmd($hash, shift @{$hash->{cmdStack}});
|
|
||||||
}
|
|
||||||
elsif(!@{$hash->{cmdStack}}) {
|
|
||||||
delete($hash->{cmdStack});
|
|
||||||
delete($hash->{protCmdPend});
|
|
||||||
#-- update info ---
|
|
||||||
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{burstEvtCnt}?
|
|
||||||
("_events:".$hash->{helper}{burstEvtCnt}):""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
|
|
||||||
my ($hash,$src,$dst,$chn,$peerAddr,$peerChn,$list,$content,$prep) = @_;
|
|
||||||
my $flag = CUL_HM_getFlag($hash);
|
|
||||||
my $tl = length($content);
|
|
||||||
|
|
||||||
$chn = sprintf("%02X",$chn);
|
|
||||||
$peerChn = sprintf("%02X",$peerChn);
|
|
||||||
$list = sprintf("%02X",$list);
|
|
||||||
|
|
||||||
# --store pending changes in shadow to handle bit manipulations cululativ--
|
|
||||||
$peerAddr = "000000" if(!$peerAddr);
|
|
||||||
my $peerN = ($peerAddr ne "000000")?CUL_HM_peerChName($peerAddr.$peerChn,$dst,""):"";
|
|
||||||
$peerN =~ s/broadcast//;
|
|
||||||
$peerN =~ s/ /_/g;#remote blanks
|
|
||||||
my $regLN = ((CUL_HM_getAttrInt($hash->{NAME},"expert") == 2)?"":".").
|
|
||||||
"RegL_".$list.":".$peerN;
|
|
||||||
#--- copy data from readings to shadow
|
|
||||||
my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn};
|
|
||||||
$chnhash = $hash if (!$chnhash);
|
|
||||||
if (!$chnhash->{helper}{shadowReg} ||
|
|
||||||
!$chnhash->{helper}{shadowReg}{$regLN}){
|
|
||||||
$chnhash->{helper}{shadowReg}{$regLN} =
|
|
||||||
ReadingsVal($chnhash->{NAME},$regLN,"");
|
|
||||||
}
|
|
||||||
#--- update with ne value
|
|
||||||
my $regs = $chnhash->{helper}{shadowReg}{$regLN};
|
|
||||||
for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow
|
|
||||||
my $addr = substr($content,$l,2);
|
|
||||||
my $data = substr($content,$l+2,2);
|
|
||||||
if(!$regs || !($regs =~ s/$addr:../$addr:$data/)){
|
|
||||||
$regs .= " ".$addr.":".$data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$chnhash->{helper}{shadowReg}{$regLN} = $regs;
|
|
||||||
return if ($prep);#prepare shadowReg only. More data to come.
|
|
||||||
#Application takes care about execution
|
|
||||||
CUL_HM_updtRegDisp($hash,$list,$peerAddr.$peerChn);
|
|
||||||
CUL_HM_PushCmdStack($hash, "++".$flag.'01'.$src.$dst.$chn.'05'.
|
|
||||||
$peerAddr.$peerChn.$list);
|
|
||||||
for(my $l = 0; $l < $tl; $l+=28) {
|
|
||||||
my $ml = $tl-$l < 28 ? $tl-$l : 28;
|
|
||||||
CUL_HM_PushCmdStack($hash, "++A001".$src.$dst.$chn."08".
|
|
||||||
substr($content,$l,$ml));
|
|
||||||
}
|
|
||||||
CUL_HM_PushCmdStack($hash,"++A001".$src.$dst.$chn."06");
|
|
||||||
CUL_HM_queueAutoRead($hash->{NAME})
|
|
||||||
if (2 < CUL_HM_getAttrInt($hash->{NAME},"autoReadReg"));
|
|
||||||
}
|
|
||||||
sub CUL_HM_Resend($) {#resend a message if there is no answer
|
|
||||||
my $hash = shift;
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
return if(!$hash->{helper}{respWait}{reSent}); # Double timer?
|
|
||||||
my $rep = AttrVal($name,"msgRepeat",3);
|
|
||||||
if($hash->{helper}{respWait}{reSent} > $rep) {
|
|
||||||
if (!$hash->{helper}{respWait}{wakeup}){
|
|
||||||
CUL_HM_eventP($hash,"ResndFail");
|
|
||||||
readingsSingleUpdate($hash,"state","MISSING ACK",1);
|
|
||||||
CUL_HM_ProcessCmdStack($hash); # continue processing commands if any
|
|
||||||
}
|
|
||||||
else{# do not count problems with wakeup try, just wait
|
|
||||||
CUL_HM_respPendRm($hash);
|
|
||||||
$hash->{protCondBurst} = "off";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CUL_HM_eventP($hash,"Resnd");
|
|
||||||
IOWrite($hash, "", $hash->{helper}{respWait}{cmd});
|
|
||||||
$hash->{helper}{respWait}{reSent}++;
|
|
||||||
Log GetLogLevel($name,4),"CUL_HM_Resend: ".$name. " nr ".$hash->{helper}{respWait}{reSent};
|
|
||||||
InternalTimer(gettimeofday()+rand(40)/10+1, "CUL_HM_Resend", $hash, 0);#2fast?HMLAN wants 2 sec
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3693,6 +3725,7 @@ sub CUL_HM_ID2PeerList ($$$) {
|
|||||||
}
|
}
|
||||||
$attr{$name}{peerIDs} = $peerIDs; # make it public
|
$attr{$name}{peerIDs} = $peerIDs; # make it public
|
||||||
if ($peerNames){
|
if ($peerNames){
|
||||||
|
$peerNames =~ s/_chn:01//g; # channel 01 is part of device
|
||||||
readingsSingleUpdate($hash,"peerList",$peerNames,0) ;
|
readingsSingleUpdate($hash,"peerList",$peerNames,0) ;
|
||||||
$hash->{peerList} = $peerNames;
|
$hash->{peerList} = $peerNames;
|
||||||
}
|
}
|
||||||
|
@ -158,10 +158,15 @@ sub HMinfo_peerCheck(@) { #####################################################
|
|||||||
else{# work on a valid list:
|
else{# work on a valid list:
|
||||||
foreach (split",",$peerIDs){
|
foreach (split",",$peerIDs){
|
||||||
next if ($_ eq "00000000" ||$_ =~m /$devId/);
|
next if ($_ eq "00000000" ||$_ =~m /$devId/);
|
||||||
|
my $cId = $id;
|
||||||
|
if ($md eq "HM-CC-RT-DN" && $id =~ m/05$/){ # special RT climate
|
||||||
|
$_ =~ s/04$/05/; # have to compare with clima_team, not clima
|
||||||
|
$cId =~ s/05$/04/;# will find 04 in peerlist, not 05
|
||||||
|
}
|
||||||
my $pName = CUL_HM_id2Name($_);
|
my $pName = CUL_HM_id2Name($_);
|
||||||
$pName =~s/_chn:01//; #channel 01 could be covered by device
|
$pName =~s/_chn:01//; #channel 01 could be covered by device
|
||||||
my $pPlist = AttrVal($pName,"peerIDs","");
|
my $pPlist = AttrVal($pName,"peerIDs","");
|
||||||
push @peerIDsNoPeer,$eName." p:".$pName if ($pPlist !~ m/$id/);
|
push @peerIDsNoPeer,$eName." p:".$pName if ($pPlist !~ m/$cId/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ my %culHmModel=(
|
|||||||
"00A5" => {name=>"HM-RC-Sec4-2" ,st=>'remote' ,cyc=>'' ,rxt=>'c:l' ,lst=>'1,4' ,chn=>"Btn:1:2,BTN_T:3:1,BTN_A:4:1",},#only 1 and 2 canbe peered???
|
"00A5" => {name=>"HM-RC-Sec4-2" ,st=>'remote' ,cyc=>'' ,rxt=>'c:l' ,lst=>'1,4' ,chn=>"Btn:1:2,BTN_T:3:1,BTN_A:4:1",},#only 1 and 2 canbe peered???
|
||||||
"00A6" => {name=>"HM-RC-Key4-2" ,st=>'remote' ,cyc=>'' ,rxt=>'c:l' ,lst=>'1,4' ,chn=>"Btn:1:2,BTN_T:3:1,BTN_A:4:1",},#only 1 and 2 canbe peered???
|
"00A6" => {name=>"HM-RC-Key4-2" ,st=>'remote' ,cyc=>'' ,rxt=>'c:l' ,lst=>'1,4' ,chn=>"Btn:1:2,BTN_T:3:1,BTN_A:4:1",},#only 1 and 2 canbe peered???
|
||||||
"00A7" => {name=>"HM-Sen-RD-O" ,st=>'sensRain' ,cyc=>'' ,rxt=>'' ,lst=>'1:1,4:1p' ,chn=>"Rain:1:1,Heating:2:2",},#stc:70 THSensor
|
"00A7" => {name=>"HM-Sen-RD-O" ,st=>'sensRain' ,cyc=>'' ,rxt=>'' ,lst=>'1:1,4:1p' ,chn=>"Rain:1:1,Heating:2:2",},#stc:70 THSensor
|
||||||
"00A8" => {name=>"HM-WDS30-OT2-SM" ,st=>'THSensor' ,cyc=>'00:10' ,rxt=>'c:w:f' ,lst=>'p' ,chn=>"T1:1:1,T2:2:2,T1-T2:3:3,T2-T1:4:4,Event:5:5",},
|
"00A8" => {name=>"HM-WDS30-OT2-SM" ,st=>'THSensor' ,cyc=>'00:10' ,rxt=>'c:w:f' ,lst=>'p' ,chn=>"T1:1:1,T2:2:2,T1_T2:3:3,T2_T1:4:4,Event:5:5",},
|
||||||
"00A9" => {name=>"HM-PB-6-WM55" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"Btn:1:6",},
|
"00A9" => {name=>"HM-PB-6-WM55" ,st=>'remote' ,cyc=>'' ,rxt=>'c' ,lst=>'1,4' ,chn=>"Btn:1:6",},
|
||||||
"00AB" => {name=>"HM-LC-SW4-BA-PCB" ,st=>'switch' ,cyc=>'' ,rxt=>'b' ,lst=>'1,3' ,chn=>"Sw:1:4",},
|
"00AB" => {name=>"HM-LC-SW4-BA-PCB" ,st=>'switch' ,cyc=>'' ,rxt=>'b' ,lst=>'1,3' ,chn=>"Sw:1:4",},
|
||||||
"00AF" => {name=>"HM-OU-CM-PCB" ,st=>'outputUnit' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"",},
|
"00AF" => {name=>"HM-OU-CM-PCB" ,st=>'outputUnit' ,cyc=>'' ,rxt=>'' ,lst=>'3' ,chn=>"",},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user