2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 07:19:24 +00:00

repeater bugfix, HM manual mode, protocol cleanup

git-svn-id: https://svn.fhem.de/fhem/trunk@4135 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
martinp876 2013-10-30 10:07:00 +00:00
parent d9e009a5a7
commit a1defcef2a
3 changed files with 92 additions and 49 deletions

View File

@ -115,7 +115,6 @@ sub CUL_HM_putHash($);
# ----------------modul globals-----------------------
my $respRemoved; # used to control trigger of stack processing
my $IOpoll = 0.2;# poll speed to scan IO device out of order
my $IOpolltout = 60; # poll timeout - stop poll and discard if to late
my $maxPendCmds = 10; #number of parallel requests
@ -144,8 +143,6 @@ sub CUL_HM_Initialize($) {
"param msgRepeat ".
".stc .devInfo ".
$readingFnAttributes;
$hash->{hmAutoReadScan} = 4; # delay autoConf readings
#autoReadReg:
# ,6_allForce
# ,4_backUpdt
@ -166,6 +163,9 @@ sub CUL_HM_Initialize($) {
$hash->{helper}{qReqConf} = \@confQArr;
$hash->{helper}{qReqConfWu} = \@confQWuArr;
CUL_HM_initRegHash();
$hash->{hmIoMaxDly} = 60;# poll timeout - stop poll and discard
$hash->{hmAutoReadScan} = 4; # delay autoConf readings
$hash->{helper}{hmManualOper} = 0;# default automode
}
sub CUL_HM_updateConfig($){
@ -1615,10 +1615,12 @@ sub CUL_HM_parseCommon(@){#####################################################
$ret = $reply;
}
elsif($mTp eq "00"){######################################
CUL_HM_infoUpdtDevData($shash->{NAME}, $shash,$p);#update data
my $iohash = $shash->{IODev};
my $id = CUL_HM_Id($iohash);
CUL_HM_infoUpdtDevData($shash->{NAME}, $shash,$p)
if (!$modules{CUL_HM}{helper}{hmManualOper}#no autoaction
||$iohash->{hmPair}
||$iohash->{hmPairSerial} );
if( $dst =~ m /(000000|$id)/ #--- see if we need to pair
&&($iohash->{hmPair}
@ -1848,6 +1850,10 @@ sub CUL_HM_parseCommon(@){#####################################################
}
sub CUL_HM_queueUpdtCfg($){
my $name = shift;
if ($modules{CUL_HM}{helper}{hmManualOper}){ # no update when manual operation
delete $modules{CUL_HM}{helper}{updtCfgLst};
return;
}
my @arr;
if ($modules{CUL_HM}{helper}{updtCfgLst}){
@arr = CUL_HM_noDup((@{$modules{CUL_HM}{helper}{updtCfgLst}}, $name));
@ -2596,7 +2602,6 @@ sub CUL_HM_Set($@) {
return "entry must be between 1 and 36" if ($eNo < 1 || $eNo > 36);
my $sndID = CUL_HM_name2Id($sId);
my $recID = CUL_HM_name2Id($rId);
$sndID = AttrVal($sId,"hmId","");
if ($sndID !~ m/(^[0-9A-F]{6})$/){$sndID = AttrVal($sId,"hmId","");};
if ($recID !~ m/(^[0-9A-F]{6})$/){$recID = AttrVal($rId,"hmId","");};
return "sender ID $sId unknown:".$sndID if ($sndID !~ m/(^[0-9A-F]{6})$/);
@ -3385,12 +3390,12 @@ sub CUL_HM_ProcessCmdStack($) {
return;
}
sub CUL_HM_prtInit ($){ #setup protocol variables after define
sub CUL_HM_prtInit($){ #setup protocol variables after define
my ($hash)=@_;
$hash->{helper}{prt}{sProc} = 0; # stack not being processed by now
$hash->{helper}{prt}{bErr}=0;
}
sub CUL_HM_respWaitSu ($@){ #setup response for multi-message response
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)
@ -3533,11 +3538,11 @@ sub CUL_HM_sndIfOpen($) {
my(undef,$io) = split(':',$_[0]);
RemoveInternalTimer("sndIfOpen:$io");# should not be necessary, but
my $ioHash = $defs{$io};
if ( $ioHash->{STATE} ne "opened"
if ( $ioHash->{STATE} !~ m/^(opened|Initialized)$/
||(defined $ioHash->{XmitOpen} && $ioHash->{XmitOpen} == 0)
# ||$modules{CUL_HM}{prot}{rspPend}>=$maxPendCmds
){#still no send allowed
if ($modules{CUL_HM}{$io}{tmrStart} < gettimeofday() - $IOpolltout){
if ($modules{CUL_HM}{$io}{tmrStart} < gettimeofday() - $modules{CUL_HM}{hmIoMaxDly}){
# we need to clean up - this is way to long Stop delay
if ($modules{CUL_HM}{$io}{pendDev}) {
while(@{$modules{CUL_HM}{$io}{pendDev}}){
@ -3570,10 +3575,10 @@ sub CUL_HM_SndCmd($$) {
|| AttrVal($hash->{NAME},"ignore","")
|| AttrVal($hash->{NAME},"dummy",""));
my $ioName = $io->{NAME};
if ((hex substr($cmd,2,2) & 0x20) && ( # check for commands with resp-req
$io->{STATE} !~ m/^(opened|Initialized)$/ # we need to queue
|| $modules{CUL_HM}{$ioName}{tmr} # queue already running
||(defined $io->{XmitOpen} && $io->{XmitOpen} == 0)#overload, dont send
if ( $io->{STATE} !~ m/^(opened|Initialized)$/ # we need to queue
||(hex substr($cmd,2,2) & 0x20) && ( # check for commands with resp-req
$modules{CUL_HM}{$ioName}{tmr} # queue already running
||(defined $io->{XmitOpen} && $io->{XmitOpen} == 0)#overload, dont send
)
){
@ -3582,7 +3587,7 @@ sub CUL_HM_SndCmd($$) {
# repetition will be stopped after 1min forsecurity reason.
my @arr = ();
$hash->{cmdStack} = \@arr if(!$hash->{cmdStack});
unshift (@{$hash->{cmdStack}}, $cmd);#pushback cmd, wait for opportunitiy
unshift (@{$hash->{cmdStack}}, $cmd);#pushback cmd, wait for opportunity
# push device to list
if (!defined $modules{CUL_HM}{$ioName}{tmr}){
@ -3596,7 +3601,6 @@ sub CUL_HM_SndCmd($$) {
@{$modules{CUL_HM}{$ioName}{pendDev}} =
CUL_HM_noDup(@{$modules{CUL_HM}{$ioName}{pendDev}},$hash->{NAME});
CUL_HM_respPendRm($hash);#rm timer - we are out
if ($modules{CUL_HM}{$ioName}{tmr} != 1){# need to start timer
my $tn = gettimeofday();
InternalTimer($tn+$IOpoll, "CUL_HM_sndIfOpen", "sndIfOpen:$ioName", 0);
@ -3633,6 +3637,8 @@ sub CUL_HM_respPendRm($) {#del response related entries in messageing entity
$modules{CUL_HM}{prot}{rspPend}-- if($hash->{helper}{prt}{rspWait}{cmd});
delete ($hash->{helper}{prt}{rspWait});
delete $hash->{helper}{tmdOn};
delete $hash->{helper}{prt}{mmcA};
delete $hash->{helper}{prt}{mmcS};
RemoveInternalTimer($hash); # remove resend-timer
RemoveInternalTimer("respPend:$hash->{DEF}");# remove responsePending timer
$respRemoved = 1;
@ -3654,26 +3660,17 @@ sub CUL_HM_respPendTout($) {
$pHash->{awake} = 0;# set to asleep
CUL_HM_protState($hash,"CMDs_pending");
}
elsif ($hash->{IODev}->{STATE} !~ m/^(opened|Initialized)$/){#IO errors
CUL_HM_eventP($hash,"IOdly");
CUL_HM_ProcessCmdStack($hash) if(CUL_HM_getRxType($hash) & 0x03);
}
elsif ($pHash->{rspWait}{reSent} > AttrVal($hash->{NAME},"msgRepeat",3) # too much
||((CUL_HM_getRxType($hash) & 0x83) == 0)){ #to slow
if ($pHash->{mmcA}){
#shall we re-insert commands?
#unshift @{$hash->{cmdStack}},@{$pHash->{mmcA}};
delete $pHash->{mmcA};
delete $pHash->{mmcS};
}
if ($hash->{IODev}->{STATE} !~ m/^(opened|Initialized)$/){#IO errors
CUL_HM_eventP($hash,"IOerr");
readingsSingleUpdate($hash,"state","IOerr",1);
}
else{
my $pendCmd = ($pHash->{rspWait}{Pending}
my $pendCmd = ($pHash->{rspWait}{Pending}
?"RESPONSE TIMEOUT:".$pHash->{rspWait}{Pending}
:"MISSING ACK");# save before remove
CUL_HM_eventP($hash,"ResndFail");
readingsSingleUpdate($hash,"state",$pendCmd,1);
}
CUL_HM_eventP($hash,"ResndFail");
readingsSingleUpdate($hash,"state",$pendCmd,1);
CUL_HM_ProcessCmdStack($hash); # continue processing commands if any
}
else{# manage retries
@ -3682,7 +3679,8 @@ sub CUL_HM_respPendTout($) {
$pHash->{rspWait}{reSent}++;
my (undef,$addr,$msg) = unpack 'A10A12A*',$hash->{helper}{prt}{rspWait}{cmd};
$pHash->{rspWaitSec}{$_} = $pHash->{rspWait}{$_} foreach (keys%{$pHash->{rspWait}}); ;
$pHash->{rspWaitSec}{$_} = $pHash->{rspWait}{$_}
foreach (keys%{$pHash->{rspWait}});
CUL_HM_SndCmd($hash,"++B112$addr");
$hash->{helper}{prt}{awake}=4;# start re-wakeup
}
@ -3717,16 +3715,24 @@ sub CUL_HM_eventP($$) {#handle protocol events
$nAttr->{"prot".$evntType} = ++$evntCnt." last_at:".TimeNow();
if ($evntType =~ m/(Nack|ResndFail|IOerr)/){# unrecoverable Error
readingsSingleUpdate($hash,"state",$evntType,1);
$hash->{helper}{prt}{bErr}++;
$nAttr->{protCmdDel}++;
if ( (CUL_HM_getRxType($hash) & 0x01) == 0 #to slow for wakeup and config
#no retry for burst either
|| $evntType eq "IOerr"){ #IO problem
$nAttr->{protCmdDel} = 0 if(!$nAttr->{protCmdDel});
$nAttr->{protCmdDel} += scalar @{$hash->{cmdStack}}
$nAttr->{protCmdDel} = 0 if(!$nAttr->{protCmdDel});
$nAttr->{protCmdDel} += scalar @{$hash->{cmdStack}} + 1
if ($hash->{cmdStack});
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{prt}{bErr}?
("_Errors:".$hash->{helper}{prt}{bErr}):""));
CUL_HM_protState($hash,"CMDs_done".($hash->{helper}{prt}{bErr}?
("_Errors:".$hash->{helper}{prt}{bErr}):""));
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};
delete $pHash->{mmcS};
}
else{
unshift @{$hash->{cmdStack}}, $pHash->{rspWait}{cmd};#pushback
}
CUL_HM_respPendRm($hash);
}
@ -4804,6 +4810,7 @@ sub CUL_HM_unQEntity($$){# remove entity from q - task no longer necesary
}
sub CUL_HM_qEntity($$){
my ($name,$q) = @_;
return if ($modules{CUL_HM}{helper}{hmManualOper});#no autoaction when manual
$q = $modules{CUL_HM}{helper}{$q};
return if (AttrVal($name,"subType","") eq "virtual");
if ($defs{$name}{helper}{role}{dev}){

View File

@ -23,11 +23,12 @@ sub HMinfo_Initialize($$) {####################################################
$hash->{DefFn} = "HMinfo_Define";
$hash->{SetFn} = "HMinfo_SetFn";
$hash->{AttrFn} = "HMinfo_Attr";
$hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 ".
"sumStatus sumERROR ".
"autoUpdate ".
"hmAutoReadScan ".
$readingFnAttributes;
$hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 "
."sumStatus sumERROR "
."autoUpdate "
."hmAutoReadScan hmIoMaxDly "
."hmManualOper:0_auto,1_manual "
.$readingFnAttributes;
}
sub HMinfo_Define($$){#########################################################
@ -69,7 +70,7 @@ sub HMinfo_Attr(@) {#################################
$hash->{helper}{autoUpdate} = $sec;
InternalTimer(gettimeofday()+$sec,"HMinfo_autoUpdate","sUpdt:".$name,0);
}
elsif ($attrName eq "hmAutoReadScan"){# 00:00 hh:mm
elsif($attrName eq "hmAutoReadScan"){# 00:00 hh:mm
if ($cmd eq "del"){
$modules{CUL_HM}{hmAutoReadScan} = 4;# return to default
}
@ -83,6 +84,29 @@ sub HMinfo_Attr(@) {#################################
CUL_HM_queueAutoRead(""); #will restart timer
}
}
elsif($attrName eq "hmIoMaxDly"){#
if ($cmd eq "del"){
$modules{CUL_HM}{hmIoMaxDly} = 60;# return to default
}
else{
return "please add plain integer between 0 and 3600"
if ( $attrVal !~ m/^(\d+)$/
||$attrVal<0
||$attrVal >3600 );
## implement new timer to CUL_HM
$modules{CUL_HM}{hmIoMaxDly}=$attrVal;
}
}
elsif($attrName eq "hmManualOper"){# 00:00 hh:mm
if ($cmd eq "del"){
$modules{CUL_HM}{helper}{hmManualOper} = 0;# default automode
}
else{
return "please set 0 or 1" if ($attrVal !~ m/^(0|1)/);
## implement new timer to CUL_HM
$modules{CUL_HM}{helper}{hmManualOper} = substr($attrVal,0,1);
}
}
return;
}
sub HMinfo_autoUpdate($){#in:name, send status-request
@ -1359,6 +1383,18 @@ sub HMinfo_noDup(@) {#return list with no duplicates
Note that compressing will increase message load while stretch will extent waiting time.
data. <br>
</li>
<li><a name="#HMhmIoMaxDly">hmIoMaxDly</a>
max time in seconds CUL_HM stacks messages if the IO device is not ready to send.
If the IO device will not reappear in time all command will be deleted and IOErr will be reported.<br>
Note: commands will be executed after the IO device reappears - which could lead to unexpected
activity long after command issue.<br>
default is 60sec. max value is 3600sec<br>
</li>
<li><a name="#HMhmManualOper">hmManualOper</a>
set to 1 will prevent any automatic operation, update or default settings
in CUL_HM.<br>
</li>
</ul>
<br>
<a name="HMinfovariables"><b>Variables</b></a>

View File

@ -1342,8 +1342,8 @@ my %culHmBits = (
BUTTON => '00,2,$val=(hex($val)&0x3F)',
LONG => '00,2,$val=(hex($val)&0x40)?1:0',
LOWBAT => '00,2,$val=(hex($val)&0x80)?1:0',
VALUE => '02,2,$val=(hex($val))',
NEXT => '04,2,$val=(hex($val))',} },
NBR => '02,2,$val=(hex($val))',
VALUE => '04,2,$val=(hex($val))',} },
"53" => { txt => "SensorData" , params => {
CMD => "00,2",
Fld1=> "02,2",