2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-25 03:44:52 +00:00

CUL_HM:some bug files - thanks to Frank, noansi and beta-user

git-svn-id: https://svn.fhem.de/fhem/trunk@26934 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
martinp876 2022-12-31 16:24:33 +00:00
parent 78fe11f936
commit 68c76075dd

View File

@ -460,10 +460,18 @@ sub CUL_HM_updateConfig($){##########################
$attr{$name}{autoReadReg}= AttrVal($name,"autoReadReg","4_reqStatus");
CUL_HM_hmInitMsg($hash);
}
if (CUL_HM_getRxType($hash)&0x02){#burst dev must restrict retries!
# set rxType and mId
my $rxt = CUL_HM_getRxType($hash);# set rxType and mId
if($rxt & 0x02){#burst dev must restrict retries!
$attr{$name}{msgRepeat} = 1 if (!$attr{$name}{msgRepeat});
}
elsif($rxt & 0x80){# frank: init conditional burst dev
if($attr{$name}{burstAccess}){
CUL_HM_Attr('set',$name,'burstAccess',$attr{$name}{burstAccess});
}
else{
CUL_HM_Attr('del',$name,'burstAccess');
}
}
}
if ($attr{$name}{expert}){
CUL_HM_Attr("set",$name,"expert",$attr{$name}{expert});
@ -534,7 +542,7 @@ sub CUL_HM_updateConfig($){##########################
foreach(sort keys %{$attr{$name}}){
delete $attr{$name}{$_} if (CUL_HM_AttrCheck($name,'set',$_,$attr{$name}{$_}));
}
CUL_HM_qStateUpdatIfEnab($name) if($hash->{helper}{role}{dev});
#CUL_HM_qStateUpdatIfEnab($name) if($hash->{helper}{role}{dev});
next if (0 == (0x07 & CUL_HM_getAttrInt($name,"autoReadReg")));
if(CUL_HM_getPeers($name,"Config") == 2){
CUL_HM_qAutoRead($name,1);
@ -553,9 +561,10 @@ sub CUL_HM_updateConfig($){##########################
CUL_HM_setAssotiat($name);
}
delete $modules{CUL_HM}{helper}{updtCfgLst};
#delete $modules{CUL_HM}{helper}{updtCfgLst};
if(!$modules{CUL_HM}{helper}{initDone}){
Log 5,"CUL_HM finished initial cleanup";
InternalTimer(gettimeofday() + 66, 'CUL_HM_startQueues', 'CUL_HM_startQueues', 0); #frank, https://forum.fhem.de/index.php/topic,125378.msg1202273.html#msg1202273 ff
if (defined &HMinfo_init){# force reread
$modules{HMinfo}{helper}{initDone} = 0;
InternalTimer(gettimeofday() + 5,"HMinfo_init", "HMinfo_init", 0);
@ -565,6 +574,15 @@ sub CUL_HM_updateConfig($){##########################
## configCheck will be issues by HMInfo once
}
sub CUL_HM_startQueues() { #frank, https://forum.fhem.de/index.php/topic,125378.msg1202273.html#msg1202273
Log3('global',3,'CUL_HM start Queues'); #Beta-User: changed verbose level
for my $name (@{$modules{CUL_HM}{helper}{updtCfgLst}}){
CUL_HM_qStateUpdatIfEnab($name) if($defs{$name}->{helper}{role}{dev});
}
delete $modules{CUL_HM}{helper}{updtCfgLst};
return;
}
sub CUL_HM_initializeVirtuals {
my $hash = shift // return;
my $name = $hash->{NAME} // return;
@ -1294,7 +1312,11 @@ sub CUL_HM_Attr(@) {#################################
delete $attr{$chNm}{$attrName};
}
}
CUL_HM_assignIO($hash) if $attrName eq 'ignore' && !IsDummy($hash) || $attrName eq 'dummy' && !IsIgnored($hash);
if ( $attrName eq 'ignore' && !IsDummy($hash) || $attrName eq 'dummy' && !IsIgnored($hash) ) {
RemoveInternalTimer('ActionDetector'); #Beta-User: should solve https://forum.fhem.de/index.php/topic,125490.0.html
InternalTimer(gettimeofday()+5,'CUL_HM_ActCheck', 'ActionDetector', 0);
CUL_HM_assignIO($hash);
}
}
}
elsif($attrName eq "commStInCh"){
@ -1780,7 +1802,7 @@ sub CUL_HM_Parse($$) {#########################################################
}
else {
DoTrigger('global', "UNDEFINED $sname CUL_HM $mh{src}"); #Beta-User: procedure similar to ZWave
CommandAttr(undef,"$sname room CUL_HM");
CommandAttr(undef,"$sname room CUL_HM") if !AttrVal((devspec2array('TYPE=autocreate'))[0],'device_room',0); #Beta-User: see https://forum.fhem.de/index.php/topic,125507.msg1201540.html#msg1201540
}
$acdone = 1;
}
@ -2025,7 +2047,7 @@ sub CUL_HM_Parse($$) {#########################################################
$mh{devH}->{helper}{aesCommRq}{challenge} = $challenge;
$mh{devH}->{helper}{aesCommRq}{kNo} = $kNo;
my $cmd = $mh{mNo}.($mh{devH}->{helper}{io}{sendWu}?'A1':'A0')."02$mh{dst}$mh{src}04${challenge}".sprintf("%02X", $kNo*2);
my $cmd = $mh{mNo}.($mh{devH}->{helper}{io}{sendWu}?'A1':'A0')."02$mh{dst}$mh{src}04$challenge".sprintf("%02X", $kNo*2);
$cmd = sprintf("As%02X%s", length($cmd)/2, $cmd);
IOWrite($mh{devH}, "", $cmd);
$mh{msgStat}="AESpending";
@ -2140,7 +2162,6 @@ sub CUL_HM_Parse($$) {#########################################################
&& ( $mh{devH}->{IODev}->{helper}{VTS_LZYCFG} # for TSCUL VTS0.34 up, wakeup Ack automatically sent
|| $mh{devH}->{IODev}->{TYPE} =~ m/^(?:HMLAN|HMUARTLGW)$/s ) ); # also for HMLAN/HMUARTLGW?
$flr = sprintf("%02X", hex($flr)|0x01);
$m =~ s/^(..)../$1$flr/s; #noansi: wakeup replacement
}
CUL_HM_SndCmd($h, $m);
}
@ -2163,10 +2184,11 @@ sub CUL_HM_Parse($$) {#########################################################
CUL_HM_DumpProtocol("RCV",$iohash,$mh{len},$mh{mNo},$mh{mFlg},$mh{mTp},$mh{src},$mh{dst},$mh{p});
#----------start valid messages parsing ---------
my $oldTry = ($mh{devH}->{helper}{prt}{try})? 1: 0;# frank: save old setting
my $parse = CUL_HM_parseCommon($iohash,\%mh);
if(!defined $mh{md} or $mh{md} eq '' or $mh{md} eq "unknown"){
$mh{devN} = '' if (!defined($mh{devN}));
Log3 $mh{devH},5, "CUL_HM drop msg for $mh{devN} with unknown model";#actually level 1 - however there might be neighbors around
Log3 $mh{devH},5, "CUL_HM drop msg for $mh{devN} with unknown model";
$evtDly = 0;#noansi: switch delay trigger off
return;
}
@ -2180,6 +2202,7 @@ sub CUL_HM_Parse($$) {#########################################################
if ($parse eq "ACK" ||
$parse eq "done" ){# remember - ACKinfo will be passed on
delete $mh{devH}->{helper}{prt}{try} if($oldTry && $mh{devH}->{helper}{prt}{try});# frank: delete if the try cmd is successful
push @evtEt,[$mh{devH},1,""];
}
elsif($parse eq "NACK"){
@ -2995,7 +3018,7 @@ sub CUL_HM_Parse($$) {#########################################################
delete $mh{devH}->{cmdStack};
delete $mh{devH}->{cmdStacAESPend};
delete $mh{devH}->{helper}{prt}{rspWait};
delete $mh{devH}->{helper}{prt}{rspWaitSec};
#delete $mh{devH}->{helper}{prt}{rspWaitSec};
delete $mh{devH}->{helper}{prt}{mmcA};
delete $mh{devH}->{helper}{prt}{mmcS};
delete $mh{devH}->{lastMsg};
@ -3462,7 +3485,16 @@ sub CUL_HM_Parse($$) {#########################################################
}
if($ioId eq $mh{dst} && ($mh{mFlgH}&0x20)){ # Send Ack/Nack
push @ack,$mh{shash},$mh{mNo}."8002".$ioId.$mh{src}.($mh{mFlg}.$mh{mTp} eq "A001" ? "80":"00");
if ($mh{mFlg}.$mh{mTp} eq 'A001') {
push @ack,$mh{shash},$mh{mNo}.'8002'.$ioId.$mh{src}.'80';
}
else {
push @ack,$mh{shash},$mh{mNo}.'8002'.$ioId.$mh{src}.'00' #noansi: additional CUL ACK
if ( $ioId eq $mh{dst}
&& !$mh{wakupAck} #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983 not if wakeup is sent
&& !$mh{devH}->{IODev}->{helper}{VTS_ACK} # for TSCUL VTS0.17 up
&& $mh{devH}->{IODev}->{TYPE} !~ m/^(?:HMLAN|HMUARTLGW)$/s ); #noansi: additional CUL ACK
}
}
}
elsif($mh{st} eq "threeStateSensor") { ######################################
@ -3491,6 +3523,7 @@ sub CUL_HM_Parse($$) {#########################################################
push @evtEt,[$mh{devH},1,"battery:". ($err?"low" :"ok" )];
push @ack,$mh{shash},$mh{mNo}."8002".$mh{dst}.$mh{src}."00"
if ( $ioId eq $mh{dst}
&& !$mh{wakupAck} #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983 not if wakeup is sent
&& !$mh{devH}->{IODev}->{helper}{VTS_ACK}
&& $mh{devH}->{IODev}->{TYPE} !~ m/^(HMLAN|HMUARTLGW)$/); #noansi: additional CUL ACK
}
@ -3649,7 +3682,9 @@ sub CUL_HM_Parse($$) {#########################################################
elsif($ioId eq $mh{dst}){# if fhem is destination check if we need to react
if( $mh{mTp} =~ m/^4./ #Push Button event
&& !$mh{AckDone} #noansi: allready done device specific
&& ($mh{mFlgH} & 0x20)){ #response required Flag
&& ($mh{mFlgH} & 0x20) #response required Flag
&& !$mh{wakupAck} #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983 not if wakeup is sent
){
# fhem CUL shall ack a button press
if ($mh{md} =~ m/^(HM-SEC-SC.*|ROTO_ZEL-STG-RM-FFK)$/){# SCs - depending on FW version - do not accept ACK only. Especially if peered
push @ack,$mh{shash},$mh{mNo}."8002".$mh{dst}.$mh{src}."0101".((hex($mI[0])&1)?"C8":"00")."00";
@ -3667,6 +3702,7 @@ sub CUL_HM_Parse($$) {#########################################################
push @ack,$mh{shash}, $mh{mNo}."8002".$ioId.$mh{src}."00"
if( ($ioId eq $mh{dst}) #are we adressee
&& ($mh{mFlgH} & 0x20) #response required Flag
&& !$mh{wakupAck} #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983 not if wakeup is sent
&& @evtEt #only ack if we identified it
&& (!scalar(@ack)) #sender requested ACK
);
@ -3697,7 +3733,6 @@ sub CUL_HM_Parse($$) {#########################################################
&& ( $mh{devH}->{IODev}->{helper}{VTS_LZYCFG} # for TSCUL VTS0.34 up, wakeup Ack automatically sent
|| $mh{devH}->{IODev}->{TYPE} =~ m/^(?:HMLAN|HMUARTLGW)$/s ) ); # also for HMLAN/HMUARTLGW?
$flr = sprintf("%02X", hex($flr)|0x01);
$m =~ s/^(..)../$1$flr/s; #noansi: wakeup replacement
}
CUL_HM_SndCmd($h, $m);
}
@ -3706,7 +3741,7 @@ sub CUL_HM_Parse($$) {#########################################################
}
CUL_HM_ProcessCmdStack($mh{devH}) if ($respRemoved); # cont if complete
CUL_HM_sndIfOpen("x:".$mh{ioName});
#------------ process events ------------------
push @evtEt,[$mh{devH},1,"noReceiver:src:$mh{src} ".$mh{mFlg}.$mh{mTp}." $mh{p}"]
if(!@entities && !@evtEt);
@ -3747,6 +3782,7 @@ sub CUL_HM_parseCommon(@){#####################################################
}
$devHlpr->{prt}{sleeping} = 0;
CUL_HM_ProcessCmdStack($mhp->{devH});
$mhp->{wakupAck} = 1; #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983
}
}
$devHlpr->{prt}{sleeping} = 1 if (!$devHlpr->{prt}{sProc}); # set back to sleeping with next trigger, if nothing to do
@ -3760,6 +3796,7 @@ sub CUL_HM_parseCommon(@){#####################################################
CUL_HM_SndCmd($mhp->{devH}, $mhp->{mNo}.'8102'.CUL_HM_IoId($mhp->{devH}).$mhp->{src}.'00'); #noansi: Ack with wakeup bit set for CUL
}
CUL_HM_ProcessCmdStack($mhp->{devH});
$mhp->{wakupAck} = 1; #frank: noansi from https://forum.fhem.de/index.php/topic,121139.msg1158983.html#msg1158983
}
}
}
@ -3793,13 +3830,9 @@ sub CUL_HM_parseCommon(@){#####################################################
if ($devHlpr->{prt}{rspWait}{brstWu}){
if ($devHlpr->{prt}{rspWait}{mNo} == $mNoInt &&
$mhp->{mStp} eq "00"){
CUL_HM_appFromQ($mhp->{devN},"wu");# stack cmd(s) if waiting frank:
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",hex(substr($devHlpr->{prt}{rspWait}{cmd},6,2)));
CUL_HM_respPendRm($mhp->{devH});
return "done";
}
$mhp->{devH}{protCondBurst} = "on" if ( $mhp->{devH}{protCondBurst}
@ -3957,7 +3990,9 @@ sub CUL_HM_parseCommon(@){#####################################################
push @evtEt,[$chnhash,0,"CommandAccepted:$success"];
CUL_HM_ProcessCmdStack($mhp->{devH}) if(CUL_HM_IoId($mhp->{devH}) eq $mhp->{dst});
delete $devHlpr->{prt}{wuReSent}
if (!$devHlpr->{prt}{mmcS});
if ( !$devHlpr->{prt}{mmcS}
&& $devHlpr->{prt}{rspWait}{cmd}
&& substr($devHlpr->{prt}{rspWait}{cmd},8,2) ne '12');
}
$ret = $reply;
}
@ -4002,7 +4037,6 @@ sub CUL_HM_parseCommon(@){#####################################################
CUL_HM_respPendRm($mhp->{devH}); # remove all pending messages
delete $mhp->{devH}{cmdStack};
delete $devHlpr->{prt}{rspWait};
delete $devHlpr->{prt}{rspWaitSec};
delete $mhp->{devH}{READINGS}{"RegL_00."};
delete $mhp->{devH}{READINGS}{".RegL_00."};
push @evtEt,[$defs{$ioOwn},1,"hmPair:name:$mhp->{devN} SN:".$regser." model:$attr{$mhp->{devN}}{model}"];
@ -4152,8 +4186,10 @@ sub CUL_HM_parseCommon(@){#####################################################
}
elsif($mhp->{mStp} eq "02" ||$mhp->{mStp} eq "03"){ #ParamResp==============
my $mNoWait = $rspWait->{mNo};
if ( $pendType eq "RegisterRead" &&
($mNoWait == $mNoInt || $mNoInt == ($mNoWait+1)%256)){ #noWait +1 modulo 256
if ( $pendType eq "RegisterRead"
&& !(defined($rspWait->{data}) && $rspWait->{data} eq $mhp->{p})# no device retry
&& ($mNoWait == $mNoInt || $mNoInt == ($mNoWait+1)%256)){ # noWait +1 modulo 256
$rspWait->{data} = $mhp->{p}; # prevent timeout for device resends with mNo+2
$rspWait->{mNo} = $mNoInt; # next message will be numbered same or one plus
$repeat = 1;#prevent stop for messagenumber match
CUL_HM_m_setCh($mhp,$rspWait->{forChn});
@ -4206,7 +4242,21 @@ sub CUL_HM_parseCommon(@){#####################################################
}
}
else{
Log3 $mhp->{devH},4,"waiting for: $pendType, got:RegisterRead # await msgNo:".(defined $rspWait->{mNo} ? $rspWait->{mNo} :"-no msgNo").", rec:$mNoInt";
if( $pendType eq "RegisterRead"# frank: prevent timeout for device resends with mNo+2 or wrong destination
&& defined($rspWait->{data}) && $rspWait->{data} eq $mhp->{p}){
Log3 $mhp->{devH},3,"device resend for $pendType => mTp:$mhp->{mTp} mStp:$mhp->{mStp} mNo:".hex($mhp->{mNo})." dst:$mhp->{dst} data:$mhp->{p}\n "
.join("\n ",map{"$_:$rspWait->{$_}"}keys %{$rspWait});
$rspWait->{mNo} = $mNoInt; # next message will be numbered same or one plus
$repeat = 1;#prevent stop for messagenumber match
CUL_HM_respPendToutProlong($mhp->{devH});#wasn't last - reschedule timer
if( $mhp->{dst} ne CUL_HM_IoId($mhp->{devH}) # wrong destination, frank: manage fw bug HM-CC-TC
&& $mhp->{devH}->{IODev}->{TYPE} !~ m/^(?:HMLAN|HMUARTLGW)$/s){ # only for cul io
CUL_HM_SndCmd($mhp->{devH},"$mhp->{mNo}8002".CUL_HM_IoId($mhp->{devH})."$mhp->{src}00");
}
}
else{
Log3 $mhp->{devH},4,"waiting for: $pendType, got:RegisterRead # await msgNo:".(defined $rspWait->{mNo} ? $rspWait->{mNo} :"-no msgNo").", rec:$mNoInt";
}
}
$ret = "done";
}
@ -4726,8 +4776,9 @@ sub CUL_HM_Get($@) {#+++++++++++++++++ get command+++++++++++++++++++++++++++++
}
}
elsif($cmd eq "regTable") { ################################################
return 'not supported w/o HMinfo' if !defined &HMinfo_GetFn;
return HMinfo_GetFn($hash,$name,"register","-f","\^".$name."\$");
}
}
elsif($cmd eq "regList") { #################################################
return CUL_HM_getRegInfo($name) ;
}
@ -5339,13 +5390,11 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
$hash->{helper}{prt}{bErr}=0;
delete $hash->{cmdStack};
delete($hash->{protCmdPend});
delete $hash->{helper}{prt}{rspWait};
delete $hash->{helper}{prt}{rspWaitSec};
delete $hash->{helper}{prt}{mmcA};
delete $hash->{helper}{prt}{mmcS};
delete $hash->{lastMsg};
delete ($hash->{$_}) foreach (grep(/^prot/,keys %{$hash}));
delete ($hash->{$_}) foreach ( grep {$_ =~ m/^prot/ && $_ ne 'protCondBurst'} keys %{$hash} );
if ($hash->{IODev}{NAME} &&
$modules{CUL_HM}{$hash->{IODev}{NAME}} &&
@ -5642,7 +5691,6 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
my $chnNo = substr($channel,6,2);
CUL_HM_PushCmdStack($hash,"++".$flag.'01'.$id.$dst.$chnNo.'0E');
}
CUL_HM_stateUpdatDly($name,20) if (scalar(@chnIdList));
$state = "";
}
elsif($cmd eq "getSerial") { ################################################
@ -7587,10 +7635,17 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
CUL_HM_ProcessCmdStack($devHash);
}
}
elsif (CUL_HM_getAttrInt($name,"burstAccess")){ #burstConditional - have a try
$hash->{helper}{prt}{brstWu}=1;# start auto-burstWakeup
elsif (CUL_HM_getAttrInt($name,"burstAccess") # burstConditional - have a try
&& ( !defined($devHash->{helper}{prt}{awake}) # prevent A112/B112 at same time
|| defined($devHash->{helper}{prt}{awake}) && $devHash->{helper}{prt}{awake} != 1)# not if wuPrep is scheduled
&& !(defined($devHash->{helper}{io}{flgs}) && $devHash->{helper}{io}{flgs} & 0x02)){ # wuPrep is not active (for fhem start)
$devHash->{helper}{prt}{brstWu}=1;# start auto-burstWakeup
CUL_HM_SndCmd($devHash,"++B112$id$dst");
}
elsif ( $rxType & 0x18 # wu or lazy device
&& !(defined($devHash->{helper}{io}{flgs}) && $devHash->{helper}{io}{flgs} & 0x02)){ # wuPrep is not active
CUL_HM_hmInitMsgUpdt($devHash,1);
}
}
return ("",1);# no not generate trigger out of command
}
@ -8000,10 +8055,11 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
my $addr = substr($content,$l,2);
my $data = substr($content,$l+2,2);
if(!$regs || !($regs =~ s/$addr:../$addr:$data/)){
$regs .= " ".$addr.":".$data;
$regs .= " ".$addr.":".$data;
}
}
$sdH->{helper}{shadowReg}{$regLNp} = $regs; # update shadow
$sdH->{helper}{shadowReg}{$regLNp} = $regs; # update shadow
$sdH->{helper}{shadowRegChn}{$regLNp} = $chn; # save chn for later use, even with prep
my @changeList;
if ($prep eq "exec"){#update complete registerset
@changeList = keys%{$sdH->{helper}{shadowReg}};
@ -8033,11 +8089,12 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
if ($pN){($peerAddr,$peerChn) = unpack('A6A2', CUL_HM_name2Id($pN,$hash));}
else {($peerAddr,$peerChn) = ('000000','00');}
if (AttrVal($chnhash->{NAME},"peerIDs",0) =~ m/${peerAddr}00/){$peerChn = "00"}# if device we are not sure about device or channel. Check peers
if (AttrVal($chnhash->{NAME},"peerIDs","") =~ m/${peerAddr}00/){$peerChn = "00"}# if device we are not sure about device or channel. Check peers
CUL_HM_updtRegDisp($hash,$list,$peerAddr.$peerChn);
############partition
# my @chSplit = unpack('(A28)*',$change);
$chn = $sdH->{helper}{shadowRegChn}{$nrn};
my @chSplit = unpack('(A1120)*',$change);# makes max 40 lines, 280 byte
foreach my $chSpl(@chSplit){
my $mch = CUL_HM_lstCh($chnhash,$list,$chn);
@ -8046,7 +8103,7 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
$tl = length($chSpl);
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".
CUL_HM_PushCmdStack($hash, '++A001'.$src.$dst.$mch.'08'.
substr($chSpl,$l,$ml));
}
CUL_HM_PushCmdStack($hash,"++A001".$src.$dst.$mch."06");
@ -8452,8 +8509,10 @@ sub CUL_HM_respPendRm($) {#del response related entries in messageing entity
return if (!defined($hash->{DEF}));
$modules{CUL_HM}{prot}{rspPend}-- if($hash->{helper}{prt}{rspWait}{cmd});
delete $hash->{helper}{prt}{wuReSent} if ( !$hash->{helper}{prt}{mmcS}
&& $hash->{helper}{prt}{rspWait}{cmd}
&& substr($hash->{helper}{prt}{rspWait}{cmd},8,2) ne '12');
delete $hash->{helper}{prt}{rspWait};
delete $hash->{helper}{prt}{wuReSent};
delete $hash->{helper}{tmdOn};
# delete $hash->{helper}{prt}{mmcA};
# delete $hash->{helper}{prt}{mmcS};
@ -8468,7 +8527,6 @@ sub CUL_HM_respPendTout($) {
my $pHash = $hash->{helper}{prt};#shortcut
if ($hash && $hash->{DEF} ne '000000'){# we know the device
my $name = $hash->{NAME};
$pHash->{awake} = 0 if (defined $pHash->{awake});# set to asleep
return if(!$pHash->{rspWait}{reSent}); # Double timer?
my $rxt = CUL_HM_getRxType($hash);
if ($pHash->{rspWait}{brstWu}){#burst-wakeup try failed (conditionalBurst)
@ -8476,8 +8534,9 @@ sub CUL_HM_respPendTout($) {
$hash->{protCondBurst} = "off" if (!$hash->{protCondBurst}||
$hash->{protCondBurst} !~ m/forced/);;
$pHash->{brstWu} = 0;# finished
$pHash->{awake} = 0;# set to asleep
$pHash->{awake} = 1;# new mode => set to "wait for wu" (wuPrep)
CUL_HM_protState($hash,"CMDs_pending");
CUL_HM_hmInitMsgUpdt($hash,1);
# commandstack will be executed when device wakes up itself
}
elsif ($pHash->{try}){ #send try failed - revert, wait for wakeup
@ -8486,7 +8545,9 @@ sub CUL_HM_respPendTout($) {
unshift (@{$hash->{cmdStack}}, "++".substr($pHash->{rspWait}{cmd},6));
delete $pHash->{try};
CUL_HM_respPendRm($hash);# do not count problems with wakeup try, just wait
$pHash->{awake} = 1 if (defined $pHash->{awake}); # frank: new mode => set to "wait for wu" (wuPrep)
CUL_HM_protState($hash,"CMDs_pending");
CUL_HM_hmInitMsgUpdt($hash,1);
}
elsif (!CUL_HM_operIObyIOHash($hash->{IODev})){#IO errors
CUL_HM_eventP($hash,"IOdly");
@ -8509,11 +8570,20 @@ sub CUL_HM_respPendTout($) {
Log3 $name,5,"CUL_HM_Resend: $name nr ".$pHash->{rspWait}{reSent};
if ($hash->{protCondBurst} && $hash->{protCondBurst} eq "on" ){
#timeout while conditional burst was active. try re-wakeup
#need to fill back command to queue and wait for next wakeup # frank: change mechanism
if ($pHash->{mmcA}){#fillback multi-message command
unshift @{$hash->{cmdStack}},$_ foreach (reverse@{$pHash->{mmcA}});
delete $pHash->{mmcA};
delete $pHash->{mmcS};
}
else{#fillback simple command
unshift (@{$hash->{cmdStack}},"++".substr($pHash->{rspWait}{cmd},6));
}
$pHash->{wuReSent} = $pHash->{rspWait}{reSent};
delete $pHash->{rspWait};
$pHash->{awake}=4;#start re-wakeup # frank: change position
my $addr = CUL_HM_IoId($hash);
$pHash->{rspWaitSec}{$_} = $pHash->{rspWait}{$_}
foreach (keys%{$pHash->{rspWait}});
CUL_HM_SndCmd($hash,"++B112$addr$HMid");
$hash->{helper}{prt}{awake}=4;# start re-wakeup
}
elsif($rxt & 0x18){# wakeup/lazy devices
#need to fill back command to queue and wait for next wakeup
@ -8530,6 +8600,7 @@ sub CUL_HM_respPendTout($) {
CUL_HM_respPendRm($hash);#clear
CUL_HM_protState($hash,"CMDs_pending");
$pHash->{wuReSent} = $wuReSent;# restore'invalid' count after general delete
CUL_HM_hmInitMsgUpdt($hash,1); # frank:
}
else{# normal/burst device resend
if ($rxt & 0x02){# type = burst - need to set burst-Bit for retry
@ -8700,23 +8771,26 @@ sub CUL_HM_eventP($$) {#handle protocol events
$hash->{"protLastRcv"} = $t;
$t =~ s/[\:\-\ ]//g;
CUL_HM_UpdtReadSingle($hash,".protLastRcv",$t,0);
# return;
}
my $evnt = $hash->{"prot".$evntType} ? $hash->{"prot".$evntType} : "0";
my ($evntCnt,undef) = split(' last_at:',$evnt);
$hash->{"prot".$evntType} = ++$evntCnt." last_at:".TimeNow();
my $pHash = $hash->{helper}{prt}; # frank: change position
if ($evntType =~ m/^(Nack|ResndFail|IOerr|dummy)/){# unrecoverable Error
CUL_HM_UpdtReadSingle($hash,"state",$evntType,1);
$hash->{helper}{prt}{bErr}++;
$pHash->{bErr}++;
$hash->{protCmdDel} = 0 if(!$hash->{protCmdDel});
$hash->{protCmdDel} += scalar @{$hash->{cmdStack}} + 1
if ($hash->{cmdStack});
CUL_HM_protState($hash,"CMDs_done");
if ($pHash->{mmcA}){ # frank: uncommented in CUL_HM_respPendRm
delete $pHash->{mmcA};
delete $pHash->{mmcS};
}
CUL_HM_respPendRm($hash);
}
elsif($evntType eq "IOdly"){ # IO problem - will see whether it recovers
my $pHash = $hash->{helper}{prt};
if ($pHash->{mmcA}){
unshift @{$hash->{cmdStack}},$_ foreach (reverse@{$pHash->{mmcA}});
delete $pHash->{mmcA};
@ -8779,9 +8853,10 @@ sub CUL_HM_protState($$){
}
Log3 $name,5,"CUL_HM $name protEvent:$state".
($hash->{cmdStack}?" pending:".scalar @{$hash->{cmdStack}}:"");
CUL_HM_hmInitMsgUpdt($hash) if ( $hash->{helper}{prt}{sProc} != $sProcIn
&& ( $hash->{helper}{prt}{sProc} < 2
||($hash->{helper}{prt}{sProc} == 2 && $sProcIn == 0 )));
CUL_HM_hmInitMsgUpdt($hash) if( $hash->{helper}{prt}{sProc} != $sProcIn
&& defined $hash->{helper}{io}{flgs} && $hash->{helper}{io}{flgs} & 0x02 # wuPrep is active
&& !$hash->{helper}{q}{qReqConf} && !$hash->{helper}{q}{qReqStat} # no wuQueue is scheduled
&& $hash->{helper}{prt}{sProc} < 2); # any changing to idle/processing
}
###################-----------helper and shortcuts--------#####################
@ -9607,6 +9682,7 @@ sub CUL_HM_updtRegDisp($$$) {
}
sub CUL_HM_cfgStateDelay($) {#update cfgState: schedule for devices
my $name = shift;
return if IsIgnored($name);
CUL_HM_cfgStateUpdate("cfgStateUpdate:".CUL_HM_getDeviceName($name));
}
sub CUL_HM_cfgStateUpdate($) {#update cfgState
@ -9619,7 +9695,7 @@ sub CUL_HM_cfgStateUpdate($) {#update cfgState
){
$defs{$name}{helper}{cfgStateUpdt} = 0;
my ($hm) = devspec2array("TYPE=HMinfo");
HMinfo_GetFn($defs{$hm},$hm,"configCheck","-f","^(".join("|",(CUL_HM_getAssChnNames($name),$name)).")\$") if (defined $hm);
HMinfo_GetFn($defs{$hm},$hm,"configCheck","-f","^(".join("|",(CUL_HM_getAssChnNames($name),$name,CUL_HM_getPeers($name,"NamesExt"))).")\$") if (defined $hm);
}
else {
$defs{$name}{helper}{cfgStateUpdt} = 1; # use to remove duplicate timer
@ -11066,7 +11142,7 @@ sub CUL_HM_unQEntity($$){# remove entity from q
my ($name,$q) = @_;
my $devN = CUL_HM_getDeviceName($name);
return if (AttrVal($devN,"subType","") eq "virtual");
return if (AttrVal($devN,'subType','') eq 'virtual') || IsIgnored($devN) || IsDummy($devN);
my $dq = $defs{$devN}{helper}{q};
RemoveInternalTimer("sUpdt:$name") if ($q eq "qReqStat");#remove delayed
@ -11098,7 +11174,7 @@ sub CUL_HM_qEntity($$){ # add to queue
my ($name,$q) = @_;
return if ($modules{CUL_HM}{helper}{hmManualOper});#no autoaction when manual
my $devN = CUL_HM_getDeviceName($name);
return if (AttrVal($devN,"subType","") eq "virtual");
return if (AttrVal($devN,'subType','') eq 'virtual' || IsIgnored($devN) || IsDummy($devN));
$name = $devN if ($defs{$devN}{helper}{q}{$q} eq "00"); #already requesting all
if ($devN eq $name){#config for all device
@ -11109,7 +11185,7 @@ sub CUL_HM_qEntity($$){ # add to queue
$defs{$devN}{helper}{q}{$q}
.",".substr(CUL_HM_name2Id($name),6,2));
}
my $rxt = CUL_HM_getRxType($defs{$name});
my $rxt = CUL_HM_getRxType($defs{$devN});
my $wu = ($rxt & 0x1C) ? 'Wu' : ''; #normal or wakeup q?
$q .= $wu;
my $qa = $modules{CUL_HM}{helper}{$q};
@ -11125,7 +11201,12 @@ sub CUL_HM_qEntity($$){ # add to queue
InternalTimer(gettimeofday()+ $wT,"CUL_HM_procQs","CUL_HM_procQs", 0);
}
else {
CUL_HM_hmInitMsgUpdt($defs{$devN}, 1) if ($rxt & 0x18); #wakeup prep for wakeup, lazyConfig
if( $rxt & 0x18 #wakeup prep for wakeup, lazyConfig
&& !(CUL_HM_getAttrInt($devN,'burstAccess') && $defs{$devN}->{cmdStack})
&& !(defined($defs{$devN}->{helper}{io}{flgs}) && $defs{$devN}->{helper}{io}{flgs} & 0x02) # wuPrep is not active
){
CUL_HM_hmInitMsgUpdt($defs{$devN}, 1);
}
}
}
@ -11176,7 +11257,7 @@ sub CUL_HM_procQs($){#process non-wakeup queues
CUL_HM_Set($defs{$eN},$eN,"getConfig");
}
else{
my $ign = CUL_HM_getAttrInt($eN,'ignore');
my $ign = CUL_HM_getAttrInt($eN,'ignore') + IsDummy($eN);
CUL_HM_Set($defs{$eN},$eN,'statusRequest') if (!$ign);
CUL_HM_unQEntity($eN,'qReqStat') if (!$dq->{$q});
InternalTimer(gettimeofday()+20,'CUL_HM_readStateTo','sUpdt:'.$eN,0) if (!$ign);
@ -11302,8 +11383,6 @@ sub CUL_HM_getAttrInt($@){#return attrValue as integer
my ($name,$attrName,$default) = @_;
$default = 0 if (!defined $default);
if($modules{CUL_HM}{AttrListDef} && $modules{CUL_HM}{AttrListDef}{$attrName}){
}
if($name && $defs{$name}){
my $devN = $defs{$name}{device}?$defs{$name}{device}:$name;
@ -11314,9 +11393,7 @@ sub CUL_HM_getAttrInt($@){#return attrValue as integer
$val =~ s/(\d*).*/$1/;
return int($val);
}
else{
return $default;
}
return $default;
}
#+++++++++++++++++ external use +++++++++++++++++++++++++++++++++++++++++++++++
@ -11418,8 +11495,8 @@ sub CUL_HM_cleanShadowReg($){
# remove shadow-regs if those are identical to readings or
# the reading does not exist.
# return dirty "1" if some shadowregs still remain active
my ($name) = @_;
my $hash = $defs{$name};
my $name = shift // return 0;
my $hash = $defs{$name} // return 0;
my $dirty = 0;
foreach my $rLn (keys %{$hash->{helper}{shadowReg}}){
my $rLnP = ($hash->{helper}{expert}{raw} ? "" : ".").$rLn;