2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-16 16:56:04 +00:00

10_CUL_HM:introduce modelForce, correct message repeat for burst devices

git-svn-id: https://svn.fhem.de/fhem/trunk@18153 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
martinp876 2019-01-05 23:21:58 +00:00
parent b8622f98c3
commit c467ba303f

View File

@ -154,6 +154,11 @@ my $evtDly = 0; # ugly switch to delay set readings if in parser - actually n
sub CUL_HM_Initialize($) {
my ($hash) = @_;
my @modellist;
foreach my $model (keys %{$culHmModel}){
push @modellist,$culHmModel->{$model}{name};
}
$hash->{Match} = "^A....................";
$hash->{DefFn} = "CUL_HM_Define";
$hash->{UndefFn} = "CUL_HM_Undef";
@ -168,7 +173,7 @@ sub CUL_HM_Initialize($) {
."IODev IOList IOgrp "
."rssiLog:1,0 " # enable writing RSSI to Readings (device only)
."actCycle " # also for action detector
."hmKey hmKey2 hmKey3 "
."hmKey hmKey2 hmKey3 "
."readingOnDead:multiple,noChange,state,periodValues,periodString,channels "
;
$hash->{Attr}{devPhy} = # -- physical device only attributes
@ -176,9 +181,12 @@ sub CUL_HM_Initialize($) {
."actStatus "
."autoReadReg:0_off,1_restart,2_pon-restart,3_onChange,4_reqStatus,5_readMissing,8_stateOnly "
."burstAccess:0_off,1_auto "
."msgRepeat "
."msgRepeat "
."hmProtocolEvents:0_off,1_dump,2_dumpFull,3_dumpTrigger "
."aesKey:5,4,3,2,1,0 "
."modelForce:".join(",", sort @modellist)." "
.".mId "
."subType:" .join(",",CUL_HM_noDup(map { $culHmModel->{$_}{st} } keys %{$culHmModel}))." "
;
$hash->{Attr}{chn} = "repPeers " # -- channel only attributes
."peerIDs "
@ -193,6 +201,7 @@ sub CUL_HM_Initialize($) {
."readOnly:0,1 "
."actAutoTry:0_off,1_on "
."aesCommReq:1,0 " # IO will request AES if
."model "
;
$hash->{AttrList} = $hash->{Attr}{glb}
.$hash->{Attr}{dev}
@ -202,13 +211,9 @@ sub CUL_HM_Initialize($) {
;
CUL_HM_initRegHash();
my @modellist;
foreach my $model (keys %{$culHmModel}){
push @modellist,$culHmModel->{$model}{name};
}
$hash->{AttrList} .= " model:" .join(",", sort @modellist);
$hash->{AttrList} .= " subType:".join(",",
CUL_HM_noDup(map { $culHmModel->{$_}{st} } keys %{$culHmModel}));
# $hash->{AttrList} .= " model:" .join(",", sort @modellist);
# $hash->{AttrList} .= " subType:".join(",",
# CUL_HM_noDup(map { $culHmModel->{$_}{st} } keys %{$culHmModel}));
$hash->{prot}{rspPend} = 0;#count Pending responses
my @statQArr = ();
@ -236,6 +241,7 @@ sub CUL_HM_Initialize($) {
}
sub CUL_HM_updateConfig($){
my $type = shift;
# this routine is called 5 sec after the last define of a restart
# this gives FHEM sufficient time to fill in attributes
# it will also be called after each manual definition
@ -245,7 +251,17 @@ sub CUL_HM_updateConfig($){
InternalTimer(1,"CUL_HM_updateConfig", "updateConfig", 0);#start asap once FHEM is operational
return;
}
if ($type eq "startUp"){# only once after startup
foreach(devspec2array("TYPE=CUL_HM:FILTER=DEF=......:FILTER=subType!=virtual")){
if ($attr{$_}{".mId"} && $culHmModel->{$attr{$_}{".mId"}}){ #if mId is available set model to its original value -at least temporarliy
$attr{$_}{model} = $culHmModel->{$attr{$_}{name}};
}
else{#if mId is not available use attr model and assign it.
$attr{$_}{".mId"} = CUL_HM_getmIdFromModel($attr{$_}{model});
}
CUL_HM_updtDeviceModel($_,AttrVal($_,"modelForce",AttrVal($_,"model","")));
}
}
foreach my $name (@{$modules{CUL_HM}{helper}{updtCfgLst}}){
my $hash = $defs{$name};
next if (!$hash->{DEF}); # likely renamed
@ -776,6 +792,7 @@ sub CUL_HM_Attr(@) {#################################
return;
}
elsif($attrName eq "model" && $hash->{helper}{role}{dev}){
return "$attrName must not be changed by User. \nUse modelForce instead" if ($init_done);
delete $hash->{helper}{rxType}; # needs new calculation
delete $hash->{helper}{mId};
if ($attrVal eq "CCU-FHEM"){
@ -788,7 +805,27 @@ sub CUL_HM_Attr(@) {#################################
}
$attr{$name}{$attrName} = $attrVal if ($cmd eq "set");
}
elsif($attrName eq "modelForce"){
if ($init_done){# while init allow anything. Correct with CUL_HM_updateConfig after init_done
if ($cmd eq "set"){
if (!defined $attr{$name}{".mId"} && defined $attr{$name}{model}){ # set .mId in case it is missing
$attr{$name}{".mId"} = CUL_HM_getmIdFromModel($attr{$name}{model});
}
return "invalid model name:$attrVal. Please check options" if (!CUL_HM_getmIdFromModel($attrVal));
CUL_HM_updtDeviceModel($name,$attrVal);
}
else{
$attr{$name}{model} = $culHmModel->{$attr{$name}{".mId"}}{name};# return to old model name
CUL_HM_updtDeviceModel($name,$attr{$name}{model});
}
}
}
elsif($attrName eq ".mId"){
return "$attrName must not be changed by User. \nUse modelForce instead" if ($init_done);
}
elsif($attrName eq "subType"){
return "$attrName must not be changed by User. \nUse modelForce instead" if ($init_done);
$updtReq = 1;
}
elsif($attrName eq "aesCommReq" ){
@ -1151,7 +1188,7 @@ sub CUL_HM_Parse($$) {#########################################################
my $sname = "HM_$mh{src}";
Log3 undef, 2, "CUL_HM Unknown device $sname is now defined";
DoTrigger("global","UNDEFINED $sname CUL_HM $mh{src}");
$mh{devH} = CUL_HM_id2Hash($mh{src}); #sourcehash - changed to channel entity
$mh{devH} = CUL_HM_id2Hash($mh{src}); #sourcehash - changed to channel entity
$mh{devH}->{IODev} = $iohash;
$mh{devH}->{helper}{io}{nextSend} = $mh{rectm}+0.09 if(!defined($mh{devH}->{helper}{io}{nextSend}));# io couldn't set
}
@ -4076,15 +4113,15 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
if( $culHmFunctSets->{$fkt} && $roleC){foreach(keys %{$culHmFunctSets->{$fkt}} ){push @arr1,"$_:".${$culHmFunctSets->{$fkt}}{$_} }};
@arr1 = CUL_HM_noDup(@arr1);
foreach(@arr1){
my ($cmd,$val) = split(":",$_,2);
my ($cmdS,$val) = split(":",$_,2);
if (!$val){ # no agruments possible
$_ = "$cmd:noArg";
$_ = "$cmdS:noArg";
}
elsif($val !~ m/^\[.*\]$/ ||
$val =~ m/\[.*\[/ ||
$val =~ m/(\<|\>)]/
){
$_ = $cmd;
$_ = $cmdS;
}
else{
$val =~ s/(\[|\])//g;
@ -4096,7 +4133,7 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
$_ = join(",",@list);
}
}
$_ = "$cmd:".join(",",@vArr);
$_ = "$cmdS:".join(",",@vArr);
}
}
@arr1 = ("--") if (!scalar @arr1);
@ -4495,7 +4532,7 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
$state = "";
my $sn = ReadingsVal($name,"D-serialNr","");
return "serial number unknown" if (! $sn);
CUL_HM_PushCmdStack($hash,'++8401'.$id.'000000010A'.uc(unpack('H*', $sn)));
CUL_HM_PushCmdStack($hash,'++8401'.$id.$dst.'010A'.uc(unpack('H*', $sn)));
}
elsif($cmd eq "getConfig") { ################################################
CUL_HM_unQEntity($name,"qReqConf");
@ -6319,7 +6356,7 @@ sub CUL_HM_Set($@) {#+++++++++++++++++ set command+++++++++++++++++++++++++++++
my $ret = HMinfo_SetFn($defs{hm},$hm,"templateSet",$name,$tpl,"$tPeer$tTyp",@par);
return $ret;
}
elsif($cmd =~ m/tplPara(..)(.)_.*/) { #####################################
elsif($cmd =~ m/tplPara(..)(.)_.*/) { #######################################
$state = "";
my ($tNo,$pNo) = ($1,$2);
my ($hm) = devspec2array("TYPE=HMinfo");
@ -6484,21 +6521,24 @@ sub CUL_HM_weather(@) {#periodically send weather data
CUL_HM_SndCmd($hash,"++8470".$ioId."00000000".$hash->{helper}{weather});
InternalTimer(gettimeofday()+150,"CUL_HM_weather","weather:$name",0);
}
sub CUL_HM_infoUpdtDevData($$$) {#autoread config
my($name,$hash,$p) = @_;
my($fw1,$fw2,$mId,$serNo,$stc,$devInfo) = unpack('A1A1A4A20A2A*', $p);
my $md = $culHmModel->{$mId}{name} ? $culHmModel->{$mId}{name}:"unknown";
my $md = $culHmModel->{$mId}{name} ? $culHmModel->{$mId}{name}:"unknown";# original model
my $serial = pack('H*',$serNo);
my $fw = sprintf("%d.%d", hex($fw1),hex($fw2));
$attr{$name}{model} = $md;
$attr{$name}{".mId"} = $mId;
$attr{$name}{model} = AttrVal($name,"modelForce",$md); #may be overwritten by modelForce
$attr{$name}{subType} = $culHmModel->{$mId}{st};
$attr{$name}{serialNr} = $serial; # to be removed from attributes
$attr{$name}{firmware} = $fw; # to be removed from attributes
# $attr{$name}{".devInfo"} = $devInfo; # to be removed from attributes
# $attr{$name}{".stc"} = $stc; # to be removed from attributes
CUL_HM_configUpdate($name) if(ReadingsVal($name,"D-firmware","") ne $fw
CUL_HM_updtDeviceModel($name,$attr{$name}{model});
CUL_HM_configUpdate($name) if(ReadingsVal($name,"D-firmware","") ne $fw # force read register
||ReadingsVal($name,"D-serialNr","") ne $serial
||ReadingsVal($name,".D-devInfo","") ne $devInfo
||ReadingsVal($name,".D-stc" ,"") ne $stc
@ -6507,33 +6547,84 @@ sub CUL_HM_infoUpdtDevData($$$) {#autoread config
"D-serialNr:$serial",
".D-devInfo:$devInfo",
".D-stc:$stc");
# delete $hash->{helper}{rxType};
# CUL_HM_getRxType($hash); #will update rxType
# $mId = CUL_HM_getMId($hash);# set helper valiable and use result
#
# # autocreate undefined channels
# my @chanTypesList = split(',',$culHmModel->{$mId}{chn});
# foreach my $chantype (@chanTypesList){
# my ($chnTpName,$chnStart,$chnEnd) = split(':',$chantype);
# my $chnNoTyp = 1;
# for (my $chnNoAbs = $chnStart; $chnNoAbs <= $chnEnd;$chnNoAbs++){
# my $chnId = $hash->{DEF}.sprintf("%02X",$chnNoAbs);
# if (!$modules{CUL_HM}{defptr}{$chnId}){
# my $chnName = $name."_".$chnTpName.(($chnStart == $chnEnd)?
# '':'_'.sprintf("%02d",$chnNoTyp));
#
# CommandDefine(undef,$chnName.' CUL_HM '.$chnId);
# $attr{CUL_HM_id2Name($chnId)}{model} = $attr{$name}{model};
# }
# $attr{CUL_HM_id2Name($chnId)}{model} = $attr{$name}{model};
# $chnNoTyp++;
# }
# }
# if ($culHmModel->{$mId}{cyc}){
# CUL_HM_ActAdd($hash->{DEF},AttrVal($name,"actCycle",
# $culHmModel->{$mId}{cyc}));
# }
}
sub CUL_HM_updtDeviceModel($$) {#change the model for a device - obey overwrite modelForce
my($name,$model) = @_;
my $hash = $defs{$name};
$attr{$name}{model} = $model;
delete $hash->{helper}{rxType};
delete $hash->{helper}{mId};
CUL_HM_getRxType($hash); #will update rxType
$mId = CUL_HM_getMId($hash);# set helper valiable and use result
my $mId = CUL_HM_getMId($hash);# set helper valiable and use result
$attr{$name}{subType} = $culHmModel->{$mId}{st};
# autocreate undefined channels
my @chanTypesList = split(',',$culHmModel->{$mId}{chn});
foreach my $chantype (@chanTypesList){
my ($chnTpName,$chnStart,$chnEnd) = split(':',$chantype);
my $chnNoTyp = 1;
for (my $chnNoAbs = $chnStart; $chnNoAbs <= $chnEnd;$chnNoAbs++){
my $chnId = $hash->{DEF}.sprintf("%02X",$chnNoAbs);
if (!$modules{CUL_HM}{defptr}{$chnId}){
my $chnName = $name."_".$chnTpName.(($chnStart == $chnEnd)?
'':'_'.sprintf("%02d",$chnNoTyp));
CommandDefine(undef,$chnName.' CUL_HM '.$chnId);
$attr{CUL_HM_id2Name($chnId)}{model} = $md;
}
$attr{CUL_HM_id2Name($chnId)}{model} = $md;
$chnNoTyp++;
}
my %chanExist;
%chanExist = map { $_ => 0 } CUL_HM_getAssChnIds($name);
if ($attr{$name}{subType} eq "virtual"){# du not apply all possible channels for virtual
$attr{CUL_HM_id2Name($_)}{model} = $model foreach(keys %chanExist);
}
if ($culHmModel->{$mId}{cyc}){
CUL_HM_ActAdd($hash->{DEF},AttrVal($name,"actCycle",
$culHmModel->{$mId}{cyc}));
else{
my @chanTypesList = split(',',$culHmModel->{$mId}{chn});
foreach my $chantype (@chanTypesList){# check all regulat channels
my ($chnTpName,$chnStart,$chnEnd) = split(':',$chantype);
my $chnNoTyp = 1;
for (my $chnNoAbs = $chnStart; $chnNoAbs <= $chnEnd;$chnNoAbs++){
my $chnId = $hash->{DEF}.sprintf("%02X",$chnNoAbs);
if (!$modules{CUL_HM}{defptr}{$chnId}){# not existing by now - create
my $chnName = $name."_".$chnTpName.(($chnStart == $chnEnd)?''
:'_'.sprintf("%02d",$chnNoTyp));
CommandDefine(undef,$chnName.' CUL_HM '.$chnId);
Log3 $name,3,"CUL_HM_update: $name add channel ID: $chnId name: $chnName";
}
$attr{CUL_HM_id2Name($chnId)}{model} = $model;
$chanExist{$chnId} = 1; # mark this channel as required
$chnNoTyp++;
}
}
if (scalar @chanTypesList == 0){# we won't delete channel 01. This may be on purpose
$chanExist{$defs{$name}{DEF}."01"} = 1;
my $cn01 = CUL_HM_id2Name($defs{$name}{DEF}."01");
$attr{$cn01}{model} = $model if (defined $attr{$cn01});
}
foreach(keys %chanExist){
next if ($chanExist{$_} == 1);
CommandDelete(undef,CUL_HM_id2Name($_));
Log3 $name,3,"CUL_HM_update: $name delete channel name: $_";
}
CUL_HM_ActAdd($hash->{DEF},AttrVal($name,"actCycle", $culHmModel->{$mId}{cyc}))if ($culHmModel->{$mId}{cyc});
CUL_HM_queueUpdtCfg($name);
}
}
sub CUL_HM_getConfig($){
my $hash = shift;
my $flag = 'A0';
@ -6829,7 +6920,7 @@ sub CUL_HM_responseSetup($$) {#store all we need to handle the response
if (($mFlg & 0x20) && ($dst ne '000000')){#msg wants ack
my $rss = $hash->{helper}{prt}{wuReSent}
? $hash->{helper}{prt}{wuReSent}
:1;#resend count - may need preloaded for WU device
:1;#resend counter start value - may need preloaded for WU device
if ($mTp eq '01' && $sTp) {
if ($sTp eq "03"){ #PeerList-----------
@ -7205,10 +7296,9 @@ sub CUL_HM_respPendTout($) {
}
else{# manage retries
$pHash->{rspWait}{reSent}++;
CUL_HM_eventP($hash,"Resnd");
Log3 $name,4,"CUL_HM_Resend: $name nr ".$pHash->{rspWait}{reSent};
if ($hash->{protCondBurst}&&$hash->{protCondBurst} eq "on" ){
if ($hash->{protCondBurst} && $hash->{protCondBurst} eq "on" ){
#timeout while conditional burst was active. try re-wakeup
my $addr = CUL_HM_IoId($hash);
$pHash->{rspWaitSec}{$_} = $pHash->{rspWait}{$_}
@ -7232,7 +7322,7 @@ sub CUL_HM_respPendTout($) {
CUL_HM_protState($hash,"CMDs_pending");
$pHash->{wuReSent} = $wuReSent;# restore'invalid' count after general delete
}
else{# normal device resend
else{# normal/burst device resend
if ($rxt & 0x02){# type = burst - need to set burst-Bit for retry
if ($pHash->{mmcA}){#fillback multi-message command
unshift @{$hash->{cmdStack}},$_ foreach (reverse@{$pHash->{mmcA}});
@ -7242,7 +7332,9 @@ sub CUL_HM_respPendTout($) {
my $cmd = shift @{$hash->{cmdStack}};
$cmd = sprintf("As%02X01%s", length($cmd)/2, substr($cmd,2));
$pHash->{rspWait}{cmd} = $cmd;
my $rss = $pHash->{rspWait}{reSent}; # rescue repeat counter (will be overwritten in responseSetup)
CUL_HM_responseSetup($hash,$cmd);
$pHash->{rspWait}{reSent} = $rss; # restore repeat counter
}
my ($pre,$tp,$tail) = unpack 'A6A2A*',$pHash->{rspWait}{cmd};
@ -7603,22 +7695,20 @@ sub CUL_HM_getMId($) {#in: hash(chn or dev) out:model key (key for %culHmModel)
my $hash = shift;
$hash = CUL_HM_getDeviceHash($hash);
return "" if (!$hash->{NAME});
if (!defined $hash->{helper}{mId} || !$hash->{helper}{mId}){
my $model = AttrVal($hash->{NAME}, "model", "");
$hash->{helper}{mId} = "";
foreach my $mIdKey(keys%{$culHmModel}){
next if (!$culHmModel->{$mIdKey}{name} ||
$culHmModel->{$mIdKey}{name} ne $model);
$hash->{helper}{mId} = $mIdKey;
#--- mId is updated - now update the reglist
foreach(CUL_HM_getAssChnNames($hash->{NAME})){
$defs{$_}{helper}{regLst} = CUL_HM_getChnList($defs{$_});
}
last;
}
if (!defined $hash->{helper}{mId} || !$hash->{helper}{mId}){# need to search
$hash->{helper}{mId} = CUL_HM_getmIdFromModel(AttrVal($hash->{NAME}, "model", ""));
$hash->{helper}{subType} = $hash->{helper}{mId} ? $culHmModel->{$hash->{helper}{mId}}{st}:"";
#--- mId is updated - now update the reglist
$defs{$_}{helper}{regLst} = CUL_HM_getChnList($defs{$_}) foreach(CUL_HM_getAssChnNames($hash->{NAME}));
}
return $hash->{helper}{mId};
}
sub CUL_HM_getmIdFromModel($){# enter model and receive the corresponding ID
my $model = shift;
foreach (keys%{$culHmModel}){
return $_ if ($culHmModel->{$_}{name} && $culHmModel->{$_}{name} eq $model);
}
}
sub CUL_HM_getRxType($) { #in:hash(chn or dev) out:binary coded Rx type
# Will store result in device helper
my ($hash) = @_;
@ -11094,6 +11184,11 @@ sub CUL_HM_tempListTmpl(@) { ##################################################
attr myChannel levelRange 10,80<br>
</code></ul>
</li>
<li><a name="#CUL_HMmodelForce">modelForce</a>,
modelForce overwrites the model attribute. Doing that it converts the device and its channel to the new model.<br>
Reason for this attribute is an eQ3 bug as some devices are delivered with wrong Module IDs.<br>
ATTENTION: changing model id automatically starts reconfiguration of the device and its channels! channels may be deleted or incarnated<br>
</li>
<li><a name="#CUL_HMmodel">model</a>,
<a name="subType">subType</a><br>
These attributes are set automatically after a successful pairing.
@ -12501,6 +12596,12 @@ sub CUL_HM_tempListTmpl(@) { ##################################################
Um das template nicht zu nutzen kann man es auf '0'setzen.<br>
Format ist &lt;file&gt;:&lt;templatename&gt;.
</li>
<li><a name="#CUL_HMmodelForce">modelForce</a>,
modelForce überschreibt das model attribut. Dabei wird das Device und seine Kanäle reconfguriert.<br>
Grund für dieses Attribut ist ein eQ3 bug bei welchen Devices mit falscher ID ausgeliefert werden. Das Attribut
erlaubt dies zu ueberschreiben<br>
ACHTUNG: Durch das Eintragen eines anderen model werden die Entites modifiziert, ggf. neu angelegt oder gelöscht.<br>
</li>
<li><a name="CUL_HMmodel">model</a>,
<a name="subType">subType</a><br>
Diese Attribute werden bei erfolgreichem Pairing automatisch gesetzt.