From 29d2fd4efbedbe5f59d2c18cb6b5bc017517a117 Mon Sep 17 00:00:00 2001 From: martinp876 <> Date: Sat, 31 Dec 2022 16:24:33 +0000 Subject: [PATCH] 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 --- fhem/FHEM/10_CUL_HM.pm | 199 ++++++++++++++++++++++++++++------------- 1 file changed, 138 insertions(+), 61 deletions(-) diff --git a/fhem/FHEM/10_CUL_HM.pm b/fhem/FHEM/10_CUL_HM.pm index c7b2dc00b..36143ddba 100755 --- a/fhem/FHEM/10_CUL_HM.pm +++ b/fhem/FHEM/10_CUL_HM.pm @@ -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;