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

new devices, HMLAN overload release changes, shadowreg simplify

git-svn-id: https://svn.fhem.de/fhem/trunk@4071 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
martinp876 2013-10-19 18:34:22 +00:00
parent ff4253ba79
commit b78fc866f6
3 changed files with 89 additions and 82 deletions

View File

@ -44,6 +44,7 @@ my %HMcond = ( 0 =>'ok'
# =>'overload'); # =>'overload');
my $HMOvLdRcvr = 6*60;# time HMLAN needs to recover from overload my $HMOvLdRcvr = 6*60;# time HMLAN needs to recover from overload
my $HMmlSlice = 6; # number of messageload slices per hour (10 = 6min)
sub HMLAN_Initialize($) { sub HMLAN_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
@ -108,7 +109,7 @@ sub HMLAN_Define($$) {#########################################################
my @arr = (); my @arr = ();
@{$hash->{helper}{q}{apIDs}} = \@arr; @{$hash->{helper}{q}{apIDs}} = \@arr;
$hash->{helper}{q}{cap}{$_} = 0 for (0..9); $hash->{helper}{q}{cap}{$_} = 0 for (0..($HMmlSlice-1));
$hash->{helper}{q}{cap}{last} = 0; $hash->{helper}{q}{cap}{last} = 0;
$hash->{helper}{q}{cap}{sum} = 0; $hash->{helper}{q}{cap}{sum} = 0;
HMLAN_UpdtMsgCnt("UpdtMsg:".$name); HMLAN_UpdtMsgCnt("UpdtMsg:".$name);
@ -231,27 +232,29 @@ sub HMLAN_UpdtMsgLoad($$) {####################################################
my $hash = $defs{$name}; my $hash = $defs{$name};
my $hCap = $hash->{helper}{q}{cap}; my $hCap = $hash->{helper}{q}{cap};
my $t = int(gettimeofday()/600)%6;# 10 min slices my $t = int(gettimeofday()/(3600/$HMmlSlice))%$HMmlSlice;
if ($hCap->{last} != $t){ if ($hCap->{last} != $t){
$hCap->{last} = $t; $hCap->{last} = $t;
$hCap->{$t} = 0; $hCap->{$t} = 0;
# try to release high-load condition with a dummy message # try to release high-load condition with a dummy message
# one a while # one a while
if (ReadingsVal($name,"cond","") =~ m /(Warning-HighLoad|ERROR-Overload)/){
$hash->{helper}{recoverTest} = 1;
HMLAN_Write($hash,"","As09998112" HMLAN_Write($hash,"","As09998112"
.AttrVal($name,"hmId","999999") .AttrVal($name,"hmId","999999")
."000001") ."000001");
if (ReadingsVal($name,"cond","") eq 'Warning-HighLoad'); }
} }
$hCap->{$hCap->{last}}+=$incr if ($incr); $hCap->{$hCap->{last}}+=$incr if ($incr);
my @tl; my @tl;
$hCap->{sum} = 0; $hCap->{sum} = 0;
for (($t-5)..$t){# we have 6 slices for (($t-$HMmlSlice+1)..$t){# we have 6 slices
push @tl,int($hCap->{$_%6}/16.8); push @tl,int($hCap->{$_%$HMmlSlice}/16.8);
$hCap->{sum} += $hCap->{$_%6}; # need to recalc incase a slice was removed $hCap->{sum} += $hCap->{$_%$HMmlSlice}; # need to recalc incase a slice was removed
} }
$hash->{msgLoadEst} = "1hour:".int($hCap->{sum}/16.8)."% 10min steps: ".join("/",reverse @tl); $hash->{msgLoadEst} = "1hour:".int($hCap->{sum}/16.8)."% "
.(60/$HMmlSlice)."min steps: ".join("/",reverse @tl);
#testing only ." :".$hCap->{sum} #testing only ." :".$hCap->{sum}
return; return;
} }
@ -610,18 +613,18 @@ sub HMLAN_SimpleWrite(@) {#####################################################
my $len = length($msg); my $len = length($msg);
# It is not possible to answer befor 100ms # It is not possible to answer befor 100ms
if ($len>51){ if ($len>51){
if($hash->{helper}{q}{HMcndN}){ if($hash->{helper}{q}{HMcndN}){
my $HMcnd = $hash->{helper}{q}{HMcndN}; my $HMcnd = $hash->{helper}{q}{HMcndN};
return if ($HMcnd == 4 || $HMcnd == 253);# no send if overload or disconnect return if ( ($HMcnd == 4 || $HMcnd == 253)
&& !$hash->{helper}{recoverTest});# no send if overload or disconnect
delete $hash->{helper}{recoverTest}; # test done
} }
$msg =~ m/(.{9}).(..).(.{8}).(..).(.{8}).(..)(..)(..)(.{6})(.{6})(.*)/; $msg =~ m/(.{9}).(..).(.{8}).(..).(.{8}).(..)(..)(..)(.{6})(.{6})(.*)/;
my ($s,$stat,$t,$d,$r,$no,$flg,$typ,$src,$dst,$p) = my ($s,$stat,$t,$d,$r,$no,$flg,$typ,$src,$dst,$p) =
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11); ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);
my $hmId = $attr{$name}{hmId}; my $hmId = AttrVal($name,"hmId","");
my $hDst = $hash->{helper}{$dst};# shortcut my $hDst = $hash->{helper}{$dst};# shortcut
my $tn = gettimeofday(); my $tn = gettimeofday();
if ($hDst->{nextSend}){ if ($hDst->{nextSend}){
@ -644,6 +647,7 @@ sub HMLAN_SimpleWrite(@) {#####################################################
HMLAN_qResp($hash,$dst,1) if ($hDst->{flg} == 1); HMLAN_qResp($hash,$dst,1) if ($hDst->{flg} == 1);
} }
} }
if ($len > 52){#channel information included, send sone kind of clearance if ($len > 52){#channel information included, send sone kind of clearance
my $chn = substr($msg,52,2); my $chn = substr($msg,52,2);
if ($hDst->{chn} && $hDst->{chn} ne $chn){ if ($hDst->{chn} && $hDst->{chn} ne $chn){
@ -677,7 +681,7 @@ sub HMLAN_DoInit($) {##########################################################
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $id = AttrVal($name, "hmId", undef); my $id = AttrVal($name, "hmId", "999999");
my ($k1no,$k1,$k2no,$k2,$k3no,$k3) my ($k1no,$k1,$k2no,$k2,$k3no,$k3)
=( "01",AttrVal($name,"hmKey","") =( "01",AttrVal($name,"hmKey","")
,"02",AttrVal($name,"hmKey2","") ,"02",AttrVal($name,"hmKey2","")
@ -691,7 +695,7 @@ sub HMLAN_DoInit($) {##########################################################
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 ne "999999");
HMLAN_SimpleWrite($hash, "C"); HMLAN_SimpleWrite($hash, "C");
HMLAN_SimpleWrite($defs{$name}, "Y01,".($k1?"$k1no,$k1":"00,")); HMLAN_SimpleWrite($defs{$name}, "Y01,".($k1?"$k1no,$k1":"00,"));
HMLAN_SimpleWrite($defs{$name}, "Y02,".($k2?"$k2no,$k2":"00,")); HMLAN_SimpleWrite($defs{$name}, "Y02,".($k2?"$k2no,$k2":"00,"));
@ -700,7 +704,6 @@ sub HMLAN_DoInit($) {##########################################################
delete $hash->{helper}{ref}; delete $hash->{helper}{ref};
HMLAN_condUpdate($hash,0xff); HMLAN_condUpdate($hash,0xff);
RemoveInternalTimer( "Overload:".$name);
$hash->{helper}{q}{cap}{$_}=0 foreach (keys %{$hash->{helper}{q}{cap}}); $hash->{helper}{q}{cap}{$_}=0 foreach (keys %{$hash->{helper}{q}{cap}});
foreach (keys %lhash){delete ($lhash{$_})};# clear IDs - HMLAN might have a reset foreach (keys %lhash){delete ($lhash{$_})};# clear IDs - HMLAN might have a reset
@ -710,6 +713,11 @@ sub HMLAN_DoInit($) {##########################################################
RemoveInternalTimer( "keepAliveCk:".$name);# avoid duplicate timer RemoveInternalTimer( "keepAliveCk:".$name);# avoid duplicate timer
RemoveInternalTimer( "keepAlive:".$name);# avoid duplicate timer RemoveInternalTimer( "keepAlive:".$name);# avoid duplicate timer
InternalTimer(gettimeofday()+$attr{$name}{wdTimer}, "HMLAN_KeepAlive", "keepAlive:".$name, 0); InternalTimer(gettimeofday()+$attr{$name}{wdTimer}, "HMLAN_KeepAlive", "keepAlive:".$name, 0);
# send first message to retrieve HMLAN condition
HMLAN_Write($hash,"","As09998112"
.$id
."000001");
return undef; return undef;
} }
sub HMLAN_KeepAlive($) {####################################################### sub HMLAN_KeepAlive($) {#######################################################
@ -775,11 +783,7 @@ sub HMLAN_qResp($$$) {#response-waiting queue##################################
); );
} }
} }
sub HMLAN_relOvrLd($) {########################################################
my(undef,$name) = split(':',$_[0]);
HMLAN_condUpdate($defs{$name},0xFE);
$defs{$name}{STATE} = "opened";
}
sub HMLAN_condUpdate($$) {##################################################### sub HMLAN_condUpdate($$) {#####################################################
my($hash,$HMcnd) = @_; my($hash,$HMcnd) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -788,7 +792,6 @@ sub HMLAN_condUpdate($$) {#####################################################
$hashCnd->{$HMcnd} = 0 if (!$hashCnd->{$HMcnd}); $hashCnd->{$HMcnd} = 0 if (!$hashCnd->{$HMcnd});
$hashCnd->{$HMcnd}++; $hashCnd->{$HMcnd}++;
if ($HMcnd == 4){#HMLAN needs a rest. Supress all sends exept keep alive if ($HMcnd == 4){#HMLAN needs a rest. Supress all sends exept keep alive
InternalTimer(gettimeofday()+$HMOvLdRcvr,"HMLAN_relOvrLd","Overload:".$name,1);
$hash->{STATE} = "overload"; $hash->{STATE} = "overload";
} }

View File

@ -206,7 +206,7 @@ sub CUL_HM_updateConfig($){
$hash->{helper}{role}{chn} = 1 if (length($id) == 6); #tc special $hash->{helper}{role}{chn} = 1 if (length($id) == 6); #tc special
$attr{$name}{stateFormat} = "last:trigLast" if ($chn eq "03"); $attr{$name}{stateFormat} = "last:trigLast" if ($chn eq "03");
} }
elsif ($md eq "HM-CC-RT-DN"){ elsif ($md =~ m/HM-CC-RT-DN/){
$attr{$name}{stateFormat} = "last:trigLast" if ($chn eq "03"); $attr{$name}{stateFormat} = "last:trigLast" if ($chn eq "03");
} }
elsif ("dimmer" eq $st) {#setup virtual dimmer channels elsif ("dimmer" eq $st) {#setup virtual dimmer channels
@ -267,7 +267,7 @@ sub CUL_HM_updateConfig($){
.($chn eq "02"?":playTone replay":""); .($chn eq "02"?":playTone replay":"");
} }
if (!$hash->{helper}{role}{chn} if (!$hash->{helper}{role}{chn}
&& $md eq "HM-CC-RT-DN") {$webCmd.=":burstXmit";} && $md =~ m/HM-CC-RT-DN/) {$webCmd.=":burstXmit";}
if ($webCmd){ if ($webCmd){
my $eventMap = AttrVal($name,"eventMap",undef); my $eventMap = AttrVal($name,"eventMap",undef);
@ -404,10 +404,6 @@ sub CUL_HM_Attr(@) {#################################
$hash->{READINGS}{".".$rdEntry} = $hash->{READINGS}{$rdEntry}; $hash->{READINGS}{".".$rdEntry} = $hash->{READINGS}{$rdEntry};
delete $hash->{READINGS}{$rdEntry}; delete $hash->{READINGS}{$rdEntry};
} }
foreach my $rdEntry (grep /^RegL_/,keys %{$hash->{helper}{shadowReg}}){
$hash->{helper}{shadowReg}{".".$rdEntry} = $hash->{helper}{shadowReg}{$rdEntry};
delete $hash->{helper}{shadowReg}{$rdEntry};
}
} }
elsif ($exLvl eq "1"){# on: Only register values, no raw data elsif ($exLvl eq "1"){# on: Only register values, no raw data
# move register to visible if available # move register to visible if available
@ -419,20 +415,12 @@ sub CUL_HM_Attr(@) {#################################
$hash->{READINGS}{substr($rdEntry,1)} = $hash->{READINGS}{$rdEntry}; $hash->{READINGS}{substr($rdEntry,1)} = $hash->{READINGS}{$rdEntry};
delete $hash->{READINGS}{$rdEntry}; delete $hash->{READINGS}{$rdEntry};
} }
foreach my $rdEntry (grep /^RegL_/,keys %{$hash->{helper}{shadowReg}}){
$hash->{helper}{shadowReg}{".".$rdEntry} = $hash->{helper}{shadowReg}{$rdEntry};
delete $hash->{helper}{shadowReg}{$rdEntry};
}
} }
elsif ($exLvl eq "2"){# full - incl raw data elsif ($exLvl eq "2"){# full - incl raw data
foreach my $rdEntry (grep /^\.R(egL_|-)/,keys %{$hash->{READINGS}}){ foreach my $rdEntry (grep /^\.R(egL_|-)/,keys %{$hash->{READINGS}}){
$hash->{READINGS}{substr($rdEntry,1)} = $hash->{READINGS}{$rdEntry}; $hash->{READINGS}{substr($rdEntry,1)} = $hash->{READINGS}{$rdEntry};
delete $hash->{READINGS}{$rdEntry}; delete $hash->{READINGS}{$rdEntry};
} }
foreach my $rdEntry (grep /^\.RegL_/ ,keys %{$hash->{helper}{shadowReg}}){
$hash->{helper}{shadowReg}{substr($rdEntry,1)} = $hash->{helper}{shadowReg}{$rdEntry};
delete $hash->{helper}{shadowReg}{$rdEntry};
}
} }
else{; else{;
} }
@ -773,7 +761,7 @@ sub CUL_HM_Parse($$) {##############################
} }
} }
} }
elsif($md eq "HM-CC-RT-DN") { ############################################### elsif($md =~ m/HM-CC-RT-DN/) { ##############################################
my %ctlTbl=( 0=>"auto", 1=>"manu", 2=>"party",3=>"boost"); my %ctlTbl=( 0=>"auto", 1=>"manu", 2=>"party",3=>"boost");
if ($mTp eq "10" && $p =~ m/^0A(....)(..)(..)(..)/) {#info-level if ($mTp eq "10" && $p =~ m/^0A(....)(..)(..)(..)/) {#info-level
my ($chn,$setTemp,$actTemp,$err,$bat,$vp,$ctrlMode) = my ($chn,$setTemp,$actTemp,$err,$bat,$vp,$ctrlMode) =
@ -1733,7 +1721,6 @@ sub CUL_HM_parseCommon(@){#####################################################
} }
CUL_HM_respPendRm($shash); CUL_HM_respPendRm($shash);
delete $chnHash->{helper}{shadowReg}{$regLNp}; #rm shadow delete $chnHash->{helper}{shadowReg}{$regLNp}; #rm shadow
delete $chnHash->{helper}{shadowReg}{".$regLNp"};#rm shadow
# peer Channel name from/for user entry. <IDorName> <deviceID> <ioID> # peer Channel name from/for user entry. <IDorName> <deviceID> <ioID>
CUL_HM_updtRegDisp($chnHash,$list, CUL_HM_updtRegDisp($chnHash,$list,
CUL_HM_peerChId($peer, CUL_HM_peerChId($peer,
@ -1753,14 +1740,15 @@ sub CUL_HM_parseCommon(@){#####################################################
my($chn,$peerID,$list,$data) = ($1,$2,$3,$4) if($p =~ m/^04(..)(........)(..)(.*)/); my($chn,$peerID,$list,$data) = ($1,$2,$3,$4) if($p =~ m/^04(..)(........)(..)(.*)/);
my $chnHash = $modules{CUL_HM}{defptr}{$src.$chn}; my $chnHash = $modules{CUL_HM}{defptr}{$src.$chn};
$chnHash = $shash if(!$chnHash); # will add param to dev if no chan $chnHash = $shash if(!$chnHash); # will add param to dev if no chan
my $regLN = ((CUL_HM_getAttrInt($chnHash->{NAME},"expert") == 2)?"":".")."RegL_$list:".CUL_HM_id2Name($peerID); my $regLNp = "RegL_$list:".CUL_HM_id2Name($peerID);
$regLN =~ s/broadcast//; $regLNp =~ s/broadcast//;
$regLN =~ s/ /_/g; #remove blanks $regLNp =~ s/ /_/g; #remove blanks
my $regLN = ((CUL_HM_getAttrInt($chnHash->{NAME},"expert") == 2)?"":".").$regLNp;
$data =~ s/(..)(..)/ $1:$2/g; $data =~ s/(..)(..)/ $1:$2/g;
my $lN = ReadingsVal($chnHash->{NAME},$regLN,""); my $lN = ReadingsVal($chnHash->{NAME},$regLN,"");
my $shdwReg = $chnHash->{helper}{shadowReg}{$regLN}; my $shdwReg = $chnHash->{helper}{shadowReg}{$regLNp};
foreach my $entry(split(' ',$data)){ foreach my $entry(split(' ',$data)){
my ($a,$d) = split(":",$entry); my ($a,$d) = split(":",$entry);
last if ($a eq "00"); last if ($a eq "00");
@ -1768,7 +1756,7 @@ sub CUL_HM_parseCommon(@){#####################################################
}else{ $lN .= " ".$entry;} }else{ $lN .= " ".$entry;}
$shdwReg =~ s/ $a:..// if ($shdwReg);# confirmed: remove from shadow $shdwReg =~ s/ $a:..// if ($shdwReg);# confirmed: remove from shadow
} }
$chnHash->{helper}{shadowReg}{$regLN} = $shdwReg; $chnHash->{helper}{shadowReg}{$regLNp} = $shdwReg;
$lN = join(' ',sort(split(' ',$lN)));# re-order $lN = join(' ',sort(split(' ',$lN)));# re-order
if ($lN =~ s/00:00//){$lN .= " 00:00"}; if ($lN =~ s/00:00//){$lN .= " 00:00"};
readingsSingleUpdate($chnHash,$regLN,$lN,0); readingsSingleUpdate($chnHash,$regLN,$lN,0);
@ -2777,7 +2765,7 @@ sub CUL_HM_Set($@) {
CUL_HM_PushCmdStack($hash,'++'.$flag.'11'.$id.$dst.$msg); CUL_HM_PushCmdStack($hash,'++'.$flag.'11'.$id.$dst.$msg);
} }
elsif($cmd eq "desired-temp") { ############################################# elsif($cmd eq "desired-temp") { #############################################
if ($md eq "HM-CC-RT-DN"){ if ($md =~ m/HM-CC-RT-DN/){
my $temp = ($a[2] eq "off")?9:($a[2] eq "on"?61:$a[2]*2); my $temp = ($a[2] eq "off")?9:($a[2] eq "on"?61:$a[2]*2);
return "invalid temp:$a[2]" if($temp <9 ||$temp > 60); return "invalid temp:$a[2]" if($temp <9 ||$temp > 60);
$temp = sprintf ("%02X",$temp); $temp = sprintf ("%02X",$temp);
@ -2798,7 +2786,7 @@ sub CUL_HM_Set($@) {
my $wd = $1; my $wd = $1;
$state= ""; $state= "";
my ($list,$addr,$prgChn); my ($list,$addr,$prgChn);
if ($md eq "HM-CC-RT-DN"){ if ($md =~ m/HM-CC-RT-DN/){
my %day2off = ( "Sat"=>"20", "Sun"=>"46", "Mon"=>"72", "Tue"=>"98", my %day2off = ( "Sat"=>"20", "Sun"=>"46", "Mon"=>"72", "Tue"=>"98",
"Wed"=>"124","Thu"=>"150","Fri"=>"176"); "Wed"=>"124","Thu"=>"150","Fri"=>"176");
($list,$addr,$prgChn) = (7,$day2off{$wd},0); ($list,$addr,$prgChn) = (7,$day2off{$wd},0);
@ -2818,7 +2806,7 @@ sub CUL_HM_Set($@) {
splice @a,2,1;#remove prep splice @a,2,1;#remove prep
} }
return "To few arguments" if(@a < 4); return "To few arguments" if(@a < 4);
return "To many arguments, max 24 pairs" if(@a > (($md eq "HM-CC-RT-DN")?28:50)); return "To many arguments, max 24 pairs" if(@a > (($md =~ m/HM-CC-RT-DN/)?28:50));
return "Bad format, use HH:MM TEMP ..." if(@a % 2); return "Bad format, use HH:MM TEMP ..." if(@a % 2);
return "Last time spec must be 24:00" if($a[@a-2] ne "24:00"); return "Last time spec must be 24:00" if($a[@a-2] ne "24:00");
@ -2829,7 +2817,7 @@ sub CUL_HM_Set($@) {
my ($h, $m) = ($1, $2); my ($h, $m) = ($1, $2);
my ($hByte,$lByte); my ($hByte,$lByte);
my $temp = $a[$idx+1]; my $temp = $a[$idx+1];
if ($md eq "HM-CC-RT-DN"){ if ($md =~ m/HM-CC-RT-DN/){
$temp = (int($temp*2)<<9) + ($h*12+($m/5)); $temp = (int($temp*2)<<9) + ($h*12+($m/5));
$hByte = $temp>>8; $hByte = $temp>>8;
$lByte = $temp & 0xff; $lByte = $temp & 0xff;
@ -3029,7 +3017,7 @@ sub CUL_HM_Set($@) {
my ($peerChn,$peerBtn,$peerHash,$myBtn); my ($peerChn,$peerBtn,$peerHash,$myBtn);
my $peerDst = substr($peerId,0,6); my $peerDst = substr($peerId,0,6);
if ($md eq "HM-CC-RT-DN" && $chn eq "05" ){# rt team peers cross from 05 to 04 if ($md =~ m/HM-CC-RT-DN/ && $chn eq "05" ){# rt team peers cross from 05 to 04
$myBtn = $peerBtn = "04"; $myBtn = $peerBtn = "04";
$peerChn = "05"; $peerChn = "05";
} }
@ -3274,18 +3262,19 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
my $peerN = ($peerAddr ne "000000")?CUL_HM_peerChName($peerAddr.$peerChn,$dst,""):""; my $peerN = ($peerAddr ne "000000")?CUL_HM_peerChName($peerAddr.$peerChn,$dst,""):"";
$peerN =~ s/broadcast//; $peerN =~ s/broadcast//;
$peerN =~ s/ /_/g;#remote blanks $peerN =~ s/ /_/g;#remote blanks
my $regLN = ((CUL_HM_getAttrInt($hash->{NAME},"expert") == 2)?"":"."). my $regLNp = "RegL_".$list.":".$peerN;
"RegL_".$list.":".$peerN; my $regPre = ((CUL_HM_getAttrInt($hash->{NAME},"expert") == 2)?"":".");
my $regLN = $regPre.$regLNp;
#--- copy data from readings to shadow #--- copy data from readings to shadow
my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn}; my $chnhash = $modules{CUL_HM}{defptr}{$dst.$chn};
$chnhash = $hash if (!$chnhash); $chnhash = $hash if (!$chnhash);
my $rRd = ReadingsVal($chnhash->{NAME},$regLN,""); my $rRd = ReadingsVal($chnhash->{NAME},$regLN,"");
if (!$chnhash->{helper}{shadowReg} || if (!$chnhash->{helper}{shadowReg} ||
!$chnhash->{helper}{shadowReg}{$regLN}){ !$chnhash->{helper}{shadowReg}{$regLNp}){
$chnhash->{helper}{shadowReg}{$regLN} = $rRd; $chnhash->{helper}{shadowReg}{$regLNp} = $rRd;
} }
#--- update with ne value #--- update with ne value
my $regs = $chnhash->{helper}{shadowReg}{$regLN}; my $regs = $chnhash->{helper}{shadowReg}{$regLNp};
for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow for(my $l = 0; $l < $tl; $l+=4) { #substitute changed bytes in shadow
my $addr = substr($content,$l,2); my $addr = substr($content,$l,2);
my $data = substr($content,$l+2,2); my $data = substr($content,$l+2,2);
@ -3293,7 +3282,7 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
$regs .= " ".$addr.":".$data; $regs .= " ".$addr.":".$data;
} }
} }
$chnhash->{helper}{shadowReg}{$regLN} = $regs; # update shadow $chnhash->{helper}{shadowReg}{$regLNp} = $regs; # update shadow
my @changeList; my @changeList;
if ($prep eq "exec"){#update complete registerset if ($prep eq "exec"){#update complete registerset
@changeList = keys%{$chnhash->{helper}{shadowReg}}; @changeList = keys%{$chnhash->{helper}{shadowReg}};
@ -3302,12 +3291,12 @@ sub CUL_HM_pushConfig($$$$$$$$@) {#generate messages to config data to register
return; #prepare shadowReg only. More data expected. return; #prepare shadowReg only. More data expected.
} }
else{ else{
push @changeList,$regLN; push @changeList,$regLNp;
} }
foreach my $nrn(@changeList){ foreach my $nrn(@changeList){
my $change; my $change;
my $nrRd = ReadingsVal($chnhash->{NAME},$nrn,""); my $nrRd = ReadingsVal($chnhash->{NAME},$regPre.$nrn,"");
foreach (sort split " ",$chnhash->{helper}{shadowReg}{$nrn}){ foreach (sort split " ",$chnhash->{helper}{shadowReg}{$nrn}){
$change .= $_." " if ($nrRd !~ m /$_/);# filter only changes $change .= $_." " if ($nrRd !~ m /$_/);# filter only changes
} }
@ -3596,7 +3585,8 @@ sub CUL_HM_respPendTout($) {
return if(!$pHash->{rspWait}{reSent}); # Double timer? return if(!$pHash->{rspWait}{reSent}); # Double timer?
if ($pHash->{rspWait}{wakeup}){ if ($pHash->{rspWait}{wakeup}){
CUL_HM_respPendRm($hash);# do not count problems with wakeup try, just wait CUL_HM_respPendRm($hash);# do not count problems with wakeup try, just wait
$hash->{protCondBurst} = "off" if ($hash->{protCondBurst} !~ m/forced/);; $hash->{protCondBurst} = "off" if (!$hash->{protCondBurst}||
$hash->{protCondBurst} !~ m/forced/);;
$pHash->{wakeup} = 0;# finished $pHash->{wakeup} = 0;# finished
$pHash->{awake} = 0;# set to asleep $pHash->{awake} = 0;# set to asleep
CUL_HM_protState($hash,"CMDs_pending"); CUL_HM_protState($hash,"CMDs_pending");
@ -3947,7 +3937,6 @@ sub CUL_HM_getRegFromStore($$$$@) {#read a register from backup data
$factor = $reg->{f}; $factor = $reg->{f};
$unit = " ".$reg->{u}; $unit = " ".$reg->{u};
} }
if(!$regLN){ if(!$regLN){
$regLN = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".") $regLN = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".")
.sprintf("RegL_%02X:",$list) .sprintf("RegL_%02X:",$list)
@ -3956,6 +3945,8 @@ sub CUL_HM_getRegFromStore($$$$@) {#read a register from backup data
CUL_HM_IOid($hash)):""); CUL_HM_IOid($hash)):"");
} }
$regLN =~ s/broadcast//; $regLN =~ s/broadcast//;
my $regLNp = $regLN;
$regLNp =~s/^\.//; #remove leading '.' in case ..
my $data=0; my $data=0;
my $convFlg = "";# confirmation flag - indicates data not confirmed by device my $convFlg = "";# confirmation flag - indicates data not confirmed by device
@ -3963,8 +3954,8 @@ sub CUL_HM_getRegFromStore($$$$@) {#read a register from backup data
my $addrS = sprintf("%02X",$addr); my $addrS = sprintf("%02X",$addr);
my ($dReadS,$dReadR) = (undef,""); my ($dReadS,$dReadR) = (undef,"");
$dReadS = $1 if( $hash->{helper}{shadowReg} $dReadS = $1 if( $hash->{helper}{shadowReg}
&& $hash->{helper}{shadowReg}{$regLN} && $hash->{helper}{shadowReg}{$regLNp}
&& $hash->{helper}{shadowReg}{$regLN} =~ m/$addrS:(..)/); && $hash->{helper}{shadowReg}{$regLNp} =~ m/$addrS:(..)/);
$dReadR = $1 if( $hash->{READINGS}{$regLN} $dReadR = $1 if( $hash->{READINGS}{$regLN}
&&$hash->{READINGS}{$regLN}{VAL} =~ m/$addrS:(..)/); &&$hash->{READINGS}{$regLN}{VAL} =~ m/$addrS:(..)/);
my $dRead = $dReadR; my $dRead = $dReadR;
@ -4033,7 +4024,7 @@ sub CUL_HM_updtRegDisp($$$) {
CUL_HM_TCtempReadings($hash) if (($list == 5 ||$list == 6) && CUL_HM_TCtempReadings($hash) if (($list == 5 ||$list == 6) &&
substr($hash->{DEF},6,2) eq "02"); substr($hash->{DEF},6,2) eq "02");
} }
if ($md eq "HM-CC-RT-DN"){#handle temperature readings if ($md =~ m/HM-CC-RT-DN/){#handle temperature readings
CUL_HM_RTtempReadings($hash) if ($list == 7); CUL_HM_RTtempReadings($hash) if ($list == 7);
} }
if ($md eq "HM-PB-4DIS-WM"){#add text if ($md eq "HM-PB-4DIS-WM"){#add text
@ -4221,12 +4212,12 @@ sub CUL_HM_4DisText($) {# convert text for 4dis
#text2: start at 70 (0x46) length 12 (0x0c) #text2: start at 70 (0x46) length 12 (0x0c)
my ($hash)=@_; my ($hash)=@_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $regLN = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".")."RegL_"; my $regPre = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".");
my $reg1 = ReadingsVal($name,$regLN."01:" ,""); my $reg1 = ReadingsVal($name,$regPre."RegL_01:" ,"");
my $pref = ""; my $pref = "";
if ($hash->{helper}{shadowReg}{$regLN."01:"}){ if ($hash->{helper}{shadowReg}{"RegL_01:"}){
$pref = "set_"; $pref = "set_";
$reg1 = $hash->{helper}{shadowReg}{$regLN."01:"}; $reg1 = $hash->{helper}{shadowReg}{"RegL_01:"};
} }
my %txt; my %txt;
foreach my $sAddr (54,70){ foreach my $sAddr (54,70){
@ -4248,9 +4239,9 @@ sub CUL_HM_4DisText($) {# convert text for 4dis
sub CUL_HM_TCtempReadings($) {# parse TC temperature readings sub CUL_HM_TCtempReadings($) {# parse TC temperature readings
my ($hash)=@_; my ($hash)=@_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $regLN = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".")."RegL_"; my $regPre = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".");
my $reg5 = ReadingsVal($name,$regLN."05:" ,""); my $reg5 = ReadingsVal($name,$regPre."RegL_05:" ,"");
my $reg6 = ReadingsVal($name,$regLN."06:" ,""); my $reg6 = ReadingsVal($name,$regPre."RegL_06:" ,"");
if (ReadingsVal($name,"R-controlMode","") =~ m/^party/){ if (ReadingsVal($name,"R-controlMode","") =~ m/^party/){
if ( $reg6 # ugly handling to add vanishing party register if ( $reg6 # ugly handling to add vanishing party register
@ -4278,8 +4269,8 @@ sub CUL_HM_TCtempReadings($) {# parse TC temperature readings
my $setting; my $setting;
my @changedRead; my @changedRead;
push (@changedRead,"tempList_State:". push (@changedRead,"tempList_State:".
(($hash->{helper}{shadowReg}{$regLN."05:"} || (($hash->{helper}{shadowReg}{"RegL_05:"} ||
$hash->{helper}{shadowReg}{$regLN."06:"} )?"set":"verified")); $hash->{helper}{shadowReg}{"RegL_06:"} )?"set":"verified"));
for (my $day = 0;$day<7;$day++){ for (my $day = 0;$day<7;$day++){
my $tSpan = 0; my $tSpan = 0;
my $dayRead = ""; my $dayRead = "";
@ -4307,10 +4298,10 @@ sub CUL_HM_TCtempReadings($) {# parse TC temperature readings
sub CUL_HM_RTtempReadings($) {# parse RT temperature readings sub CUL_HM_RTtempReadings($) {# parse RT temperature readings
my ($hash)=@_; my ($hash)=@_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $regLN = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".")."RegL_07:"; my $regPre = ((CUL_HM_getAttrInt($name,"expert") == 2)?"":".");
my $tempRegs = ReadingsVal($name,$regLN,""); my $tempRegs = ReadingsVal($name,$regPre."RegL_07:","");
my $stmpRegs = ($hash->{helper}{shadowReg}{$regLN})? # need to compare actual data my $stmpRegs = ($hash->{helper}{shadowReg}{"RegL_07:"})? # need to compare actual data
($hash->{helper}{shadowReg}{$regLN}) ($hash->{helper}{shadowReg}{"RegL_07:"})
:$tempRegs; :$tempRegs;
return "reglist incomplete\n" if ($tempRegs !~ m/00:00/); return "reglist incomplete\n" if ($tempRegs !~ m/00:00/);
@ -4329,7 +4320,7 @@ sub CUL_HM_RTtempReadings($) {# parse RT temperature readings
my $setting; my $setting;
my @changedRead; my @changedRead;
push (@changedRead,"tempList_State:". push (@changedRead,"tempList_State:".
($hash->{helper}{shadowReg}{$regLN} ?"set":"verified")); ($hash->{helper}{shadowReg}{"RegL_07:"} ?"set":"verified"));
for (my $day = 0;$day<7;$day++){ for (my $day = 0;$day<7;$day++){
my $dayRead = ""; my $dayRead = "";
my $pre =""; my $pre ="";
@ -4717,14 +4708,13 @@ sub CUL_HM_qAutoRead($$){
RemoveInternalTimer("CUL_HM_procQs"); RemoveInternalTimer("CUL_HM_procQs");
InternalTimer(gettimeofday()+ .5,"CUL_HM_procQs","CUL_HM_procQs", 0); InternalTimer(gettimeofday()+ .5,"CUL_HM_procQs","CUL_HM_procQs", 0);
} }
sub CUL_HM_unQEntity($$){ sub CUL_HM_unQEntity($$){# remove entity from q - task no longer necesary
my ($name,$q) = @_; my ($name,$q) = @_;
return if (AttrVal($name,"subType","") eq "virtual"); return if (AttrVal($name,"subType","") eq "virtual");
if ($defs{$name}{helper}{role}{dev}){ if ($defs{$name}{helper}{role}{dev}){
foreach (grep /channel_/,keys %{$defs{$name}}){# remove potential chn foreach (grep /channel_/,keys %{$defs{$name}}){# remove potential chn
my $ch = $defs{$name}{$_}; my $ch = $defs{$name}{$_};
@{$q} = grep !/^$ch$/,@{$q}; @{$q} = grep !/^$ch$/,@{$q};
delete $defs{$ch}{autoRead};
} }
} }
@{$q} = grep !/^$name$/,@{$q}; @{$q} = grep !/^$name$/,@{$q};
@ -4736,7 +4726,6 @@ sub CUL_HM_qEntity($$){
foreach (grep /channel_/,keys %{$defs{$name}}){# remove potential chn foreach (grep /channel_/,keys %{$defs{$name}}){# remove potential chn
my $ch = $defs{$name}{$_}; my $ch = $defs{$name}{$_};
@{$q} = grep !/^$ch$/,@{$q}; @{$q} = grep !/^$ch$/,@{$q};
delete $defs{$ch}{autoRead};
} }
@{$q} = CUL_HM_noDup(@{$q},$name); @{$q} = CUL_HM_noDup(@{$q},$name);
} }
@ -5456,7 +5445,7 @@ sub CUL_HM_reglUsed($) {# provide data for HMinfo
</ul><br> </ul><br>
</li> </li>
<li>Climate-Control (HM-CC-RT-DN) <li>Climate-Control (HM-CC-RT-DN|HM-CC-RT-DN-BoM)
<ul> <ul>
<li><B>controlMode &lt;auto|boost|day|night&gt;</B><br></li> <li><B>controlMode &lt;auto|boost|day|night&gt;</B><br></li>
<li><B>controlManu &lt;temp&gt;</B><br></li> <li><B>controlManu &lt;temp&gt;</B><br></li>
@ -5842,7 +5831,7 @@ sub CUL_HM_reglUsed($) {# provide data for HMinfo
incomplete or incorrect.<br> incomplete or incorrect.<br>
trigLast &lt;channel&gt; #last receiced trigger<br> trigLast &lt;channel&gt; #last receiced trigger<br>
</li> </li>
<li><B>HM-CC-RT-DN</B><br> <li><B>HM-CC-RT-DN and HM-CC-RT-DN-BoM</B><br>
state:T: $actTemp desired: $setTemp valve: $vp %<br> state:T: $actTemp desired: $setTemp valve: $vp %<br>
motorErr: [ok|ValveTight|adjustRangeTooLarge|adjustRangeTooSmall|communicationERR|unknown|lowBat|ValveErrorPosition] motorErr: [ok|ValveTight|adjustRangeTooLarge|adjustRangeTooSmall|communicationERR|unknown|lowBat|ValveErrorPosition]
measured-temp $actTemp<br> measured-temp $actTemp<br>

View File

@ -206,6 +206,10 @@ my %culHmModel=(
"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",},
"00AC" => {name=>"HM-ES-PMSw1-Pl " ,st=>'PwrMeterSwitch' ,cyc=>'00:10' ,rxt=>'' ,lst=>'1,1:2.3.4.5.6,3:1'
,chn=>"Sw:1:4,Pwr:2:2,CondP:3:3,CondI:4:4,CondU:5:5,CondF:6:6",},
"00AD" => {name=>"HM-TC-IT-WM-W-EU" ,st=>'thermostat' ,cyc=>'00:10' ,rxt=>'c:w' ,lst=>'p:1p.2p.6p.7p,3:3p.6p,1,7:2,8:2,9:2'
,chn=>"Weather:1:1,Climate:2:2,WindowRec:3:3,remote:6:6,SwitchTr:7:7",},
"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=>"",},
"00B1" => {name=>"HM-SEC-SC-2" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",}, "00B1" => {name=>"HM-SEC-SC-2" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
"00B2" => {name=>"HM-SEC-WDS-2" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",}, "00B2" => {name=>"HM-SEC-WDS-2" ,st=>'threeStateSensor' ,cyc=>'28:00' ,rxt=>'c:w' ,lst=>'1,4' ,chn=>"",},
@ -218,6 +222,7 @@ my %culHmModel=(
"00B9" => {name=>"HM-LC-Dim1T-CV-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:1,Sw1_V:2:3",}, "00B9" => {name=>"HM-LC-Dim1T-CV-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:1,Sw1_V:2:3",},
"00BA" => {name=>"HM-LC-Dim1T-FM-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:1,Sw1_V:2:3",}, "00BA" => {name=>"HM-LC-Dim1T-FM-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:1,Sw1_V:2:3",},
"00BB" => {name=>"HM-LC-Dim2T-SM-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:2,Sw1_V:3:4,Sw2_V:5:6",},# "00BB" => {name=>"HM-LC-Dim2T-SM-2" ,st=>'dimmer' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:2,Sw1_V:3:4,Sw2_V:5:6",},#
"00BD" => {name=>"HM-CC-RT-DN-BoM" ,st=>'thermostat' ,cyc=>'00:10' ,rxt=>'c:w:f' ,lst=>'p:1p.2p.5p.6p,3:3p.6p,1,7:4' ,chn=>"Weather:1:1,Climate:2:2,WindowRec:3:3,ClimRT_tr:4:4,ClimaTeam:5:5,remote:6:6"}, #
"8001" => {name=>"PS-switch" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:4",}, "8001" => {name=>"PS-switch" ,st=>'switch' ,cyc=>'' ,rxt=>'' ,lst=>'1,3' ,chn=>"Sw:1:4",},
"8002" => {name=>"PS-Th-Sens" ,st=>'THSensor' ,cyc=>'' ,rxt=>'' ,lst=>'1,4' ,chn=>"Sen:1:4",}, "8002" => {name=>"PS-Th-Sens" ,st=>'THSensor' ,cyc=>'' ,rxt=>'' ,lst=>'1,4' ,chn=>"Sen:1:4",},
#263 167 HM Smoke Detector Schueco #263 167 HM Smoke Detector Schueco
@ -810,6 +815,8 @@ $culHmRegModel{"HM-RC-Key4-2"} = $culHmRegModel{"HM-RC-4-2"};
$culHmRegModel{"HM-LC-SW4-BA-PCB"} = $culHmRegModel{"HM-LC-SW1-BA-PCB"}; $culHmRegModel{"HM-LC-SW4-BA-PCB"} = $culHmRegModel{"HM-LC-SW1-BA-PCB"};
$culHmRegModel{"HM-CC-RT-DN-BoM"} = $culHmRegModel{"HM-CC-RT-DN"};
my %culHmRegChan = (# if channelspecific then enter them here my %culHmRegChan = (# if channelspecific then enter them here
"HM-CC-TC02" =>{displayMode =>1,displayTemp =>1,displayTempUnit =>1, "HM-CC-TC02" =>{displayMode =>1,displayTemp =>1,displayTempUnit =>1,
controlMode =>1,decalcDay =>1, controlMode =>1,decalcDay =>1,
@ -875,6 +882,10 @@ $culHmRegChan{"HM-RC-19-SW12"} = $culHmRegChan{"HM-RC-1912"};
$culHmRegChan{"WDF-solar02"} = $culHmRegType{"dimmer"}; $culHmRegChan{"WDF-solar02"} = $culHmRegType{"dimmer"};
$culHmRegChan{"HM-CC-RT-DN-BoM03"}= $culHmRegType{"HM-CC-RT-DN03"};
$culHmRegChan{"HM-CC-RT-DN-BoM04"}= $culHmRegType{"HM-CC-RT-DN04"};
$culHmRegChan{"HM-CC-RT-DN-BoM06"}= $culHmRegType{"HM-CC-RT-DN06"};
##--------------- Conversion routines for register settings ##--------------- Conversion routines for register settings
##############################---get---######################################## ##############################---get---########################################
@ -1083,6 +1094,10 @@ my %culHmChanSets = (
# clones- - - - - - - - - - - - - - - - - # clones- - - - - - - - - - - - - - - - -
#$culHmChanSets{"HM-OU-CF-PL02"} = $culHmChanSets{"HM-OU-CF-PL01"}; #$culHmChanSets{"HM-OU-CF-PL02"} = $culHmChanSets{"HM-OU-CF-PL01"};
$culHmChanSets{"WDF-solar02"} = $culHmSubTypeSets{"blindActuator"}; $culHmChanSets{"WDF-solar02"} = $culHmSubTypeSets{"blindActuator"};
$culHmChanSets{"HM-CC-RT-DN-BoM00"}= $culHmSubTypeSets{"HM-CC-RT-DN00"};
$culHmChanSets{"HM-CC-RT-DN-BoM02"}= $culHmSubTypeSets{"HM-CC-RT-DN02"};
$culHmChanSets{"HM-CC-RT-DN-BoM04"}= $culHmSubTypeSets{"HM-CC-RT-DN04"};
$culHmChanSets{"HM-CC-RT-DN-BoM05"}= $culHmSubTypeSets{"HM-CC-RT-DN05"};
# RC send BCAST to specific address. Is the meaning understood? # RC send BCAST to specific address. Is the meaning understood?
my @culHmCmdFlags = ("WAKEUP", "WAKEMEUP", "CFG", "Bit3", my @culHmCmdFlags = ("WAKEUP", "WAKEMEUP", "CFG", "Bit3",