mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
98_hmInfo: readings about IO and errors
git-svn-id: https://svn.fhem.de/fhem/trunk@8175 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
a869c5c432
commit
0b4c7e0aa1
@ -19,6 +19,12 @@ sub CUL_Write($$$);
|
||||
sub CUL_SimpleWrite(@);
|
||||
sub CUL_WriteInit($);
|
||||
|
||||
sub CUL_SendHMPing($);
|
||||
|
||||
my $CUL_hmDestDel = 120; # destination Delay in ms for Answer Delay in HM
|
||||
my $CUL_hmMaxSysDly = 180; # max System delay for an Answer not to send
|
||||
my $CUL_hmSysACKwait = 0.1; # minimum wait in s before Answer in HM, Startvalue
|
||||
|
||||
my %gets = ( # Name, Data to send to the CUL, Regexp for the answer
|
||||
"ccconf" => 1,
|
||||
"version" => ["V", '^V .*'],
|
||||
@ -181,9 +187,12 @@ CUL_Define($$)
|
||||
$attr{$name}{dummy} = 1;
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
$hash->{helper}{ref}{hmSysACKwait} = $CUL_hmSysACKwait;
|
||||
|
||||
$hash->{DeviceName} = $dev;
|
||||
my $ret = DevIo_OpenDev($hash, 0, "CUL_DoInit");
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@ -222,8 +231,12 @@ CUL_Shutdown($)
|
||||
sub
|
||||
CUL_RemoveHMPair($)
|
||||
{
|
||||
my $hash = shift;
|
||||
my($in ) = shift;
|
||||
my(undef,$name) = split(':',$in);
|
||||
my $hash = $defs{$name};
|
||||
RemoveInternalTimer("hmPairForSec:$name");
|
||||
delete($hash->{hmPair});
|
||||
delete($hash->{hmPairSerial});
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -258,8 +271,9 @@ CUL_Set($@)
|
||||
} elsif($type eq "hmPairForSec") { ####################################
|
||||
return "Usage: set $name hmPairForSec <seconds_active>"
|
||||
if(!$arg || $arg !~ m/^\d+$/);
|
||||
CUL_RemoveHMPair("hmPairForSec:$name");
|
||||
$hash->{hmPair} = 1;
|
||||
InternalTimer(gettimeofday()+$arg, "CUL_RemoveHMPair", $hash, 1);
|
||||
InternalTimer(gettimeofday()+$arg, "CUL_RemoveHMPair", "hmPairForSec:$name", 1);
|
||||
|
||||
} elsif($type eq "hmPairSerial") { ################################
|
||||
return "Usage: set $name hmPairSerial <10-character-serialnumber>"
|
||||
@ -269,7 +283,10 @@ CUL_Set($@)
|
||||
$hash->{HM_CMDNR} = $hash->{HM_CMDNR} ? ($hash->{HM_CMDNR}+1)%256 : 1;
|
||||
CUL_SimpleWrite($hash, sprintf("As15%02x8401%s000000010A%s",
|
||||
$hash->{HM_CMDNR}, $id, unpack('H*', $arg)));
|
||||
CUL_RemoveHMPair("hmPairForSec:$name");
|
||||
$hash->{hmPair} = 1;
|
||||
$hash->{hmPairSerial} = $arg;
|
||||
InternalTimer(gettimeofday()+20, "CUL_RemoveHMPair", "hmPairForSec:".$name, 1);
|
||||
|
||||
} elsif($type eq "freq") { ######################################## MHz
|
||||
|
||||
@ -449,16 +466,54 @@ CUL_DoInit($)
|
||||
Log3 $name, 1, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$ver =~ s/[\r\n]//g;
|
||||
$hash->{VERSION} = $ver;
|
||||
|
||||
# Cmd-String feststellen
|
||||
my $vh = "";
|
||||
for (my $tr = 0;$tr<3;$tr++){
|
||||
CUL_SimpleWrite($hash, "VH");
|
||||
($err, $vh) = CUL_ReadAnswer($hash, "Version_HW", 0, undef);
|
||||
return "$name: $err" if($err && ($err !~ m/Timeout/ || $tr >= 2));
|
||||
last if($vh);
|
||||
}
|
||||
$vh =~ s/[\r\n]//g;
|
||||
$hash->{VERSION_HW} = $vh if ($vh ne $ver);
|
||||
|
||||
# Cmd-String feststellen, detect TimeStamp
|
||||
if($hash->{VERSION} =~ m/.* (\d+\.\d+).*/) {
|
||||
if ($1 > 1.61) {
|
||||
|
||||
my $ts = "no";
|
||||
for (my $trts = 0;$trts<3;$trts++){
|
||||
CUL_SimpleWrite($hash, "ApTiMeStAmP");
|
||||
($err, $ts) = CUL_ReadAnswer($hash, "TimeStamp", 0, undef);
|
||||
last if($ts);
|
||||
}
|
||||
$ts =~ s/[\r\n]//g;
|
||||
if ($ts =~ m/TiMeStAmP/){
|
||||
$ts = "yes";
|
||||
}
|
||||
$hash->{VERSION_TS} = $ts;
|
||||
|
||||
if ($ts eq "yes"){
|
||||
if (AttrVal($name,"rfmode","") eq "HomeMatic") {
|
||||
if (InternalVal($name,"initString","") !~ m/At1/) {
|
||||
$hash->{initString} .= "\nAt1";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $cmds = CUL_Get($hash, $name, "cmds", 0);
|
||||
$cmds =~ s/$name cmds =>//g;
|
||||
$cmds =~ s/ //g;
|
||||
$hash->{CMDS} = $cmds;
|
||||
Log3 $name, 3, "$name: Possible commands: " . $hash->{CMDS};
|
||||
|
||||
CUL_SimpleWrite($hash, "Ax") if ($hash->{CMDS} =~ m/A/); # reset AskSin
|
||||
CUL_SimpleWrite($hash, "Zx") if ($hash->{CMDS} =~ m/Z/); # reset Moritz
|
||||
|
||||
CUL_WriteInit($hash);
|
||||
|
||||
@ -582,38 +637,30 @@ CUL_XmitLimitCheck($$$)
|
||||
}
|
||||
|
||||
sub
|
||||
CUL_XmitDlyHM($$$)
|
||||
CUL_XmitDlyHM($$$$)
|
||||
{
|
||||
my ($hash,$fn,$now) = @_;
|
||||
my ($hash,$did,$now,$nxt) = @_;
|
||||
my $dDly = 0;
|
||||
|
||||
my (undef,$mTy,undef,$id) = unpack 'A8A2A6A6',$fn if(length($fn)>19);
|
||||
$dDly = $nxt - $now;
|
||||
$dDly -= $hash->{helper}{ref}{Sdly}*0.001; # correct with current delay of system
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend}); # only on answer we have to wait
|
||||
|
||||
if($id &&
|
||||
$modules{CUL_HM}{defptr}{$id} &&
|
||||
$modules{CUL_HM}{defptr}{$id}{helper}{io} &&
|
||||
$modules{CUL_HM}{defptr}{$id}{helper}{io}{nextSend}) {
|
||||
my $dDly = $modules{CUL_HM}{defptr}{$id}{helper}{io}{nextSend} - $now;
|
||||
#$dDly -= 0.04 if ($mTy eq "02");# while HM devices need a rest there are
|
||||
# still some devices that need faster
|
||||
# reactionfor ack.
|
||||
# Mode needs to be determined
|
||||
if ($dDly > 0.01){# wait less then 10 ms will not work
|
||||
$dDly = 0.1 if($dDly > 0.1);
|
||||
Log3 $hash->{NAME}, 5, "CUL $id dly:".int($dDly*1000)."ms";
|
||||
select(undef, undef, undef, $dDly);
|
||||
}
|
||||
if ($dDly > 0){
|
||||
$dDly = $hash->{helper}{ref}{hmSysACKwait} if($dDly > $hash->{helper}{ref}{hmSysACKwait});
|
||||
} else {
|
||||
$dDly = 0;
|
||||
}
|
||||
shift(@{$hash->{helper}{$id}{QUEUE}});
|
||||
InternalTimer($now+0.1, "CUL_XmitDlyHMTo", "$hash->{NAME}:$id", 1)
|
||||
if (scalar(@{$hash->{helper}{$id}{QUEUE}}));
|
||||
return 0;
|
||||
$modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly} = $dDly;
|
||||
|
||||
return $dDly; # s we have to wait
|
||||
}
|
||||
|
||||
sub
|
||||
CUL_XmitDlyHMTo($)
|
||||
{ # waited long enough - next send for this ID
|
||||
my ($name,$id) = split(":",$_[0]);
|
||||
CUL_SendFromQueue($defs{$name}, ${$defs{$name}{helper}{$id}{QUEUE}}[0]);
|
||||
my ($name,$did) = split(":",$_[0]);
|
||||
CUL_SendFromQueue($defs{$name}, ${$defs{$name}{helper}{$did}{QUEUE}}[0]);
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -682,14 +729,35 @@ CUL_Write($$$)
|
||||
|
||||
}
|
||||
|
||||
sub
|
||||
CUL_SendHMPing($)
|
||||
{
|
||||
my ($arg) = @_;
|
||||
my ($name,$undef) = split(":", $arg);
|
||||
my $hash = $defs{$name};
|
||||
my $now = gettimeofday();
|
||||
|
||||
CUL_SimpleWrite($hash, "ApCE"); # Send a ASKSIN Ping to CUL
|
||||
RemoveInternalTimer($arg);
|
||||
|
||||
if (defined($hash->{helper}{hmccredits}) &&
|
||||
(AttrVal($name,"rfmode","") eq "HomeMatic")) {
|
||||
if ($hash->{helper}{hmccredits} < 1) {
|
||||
InternalTimer($now+5, "CUL_SendHMPing", $arg, 1); # send another ping in 5s
|
||||
} elsif ($hash->{helper}{hmccredits} < 2) {
|
||||
InternalTimer($now+10, "CUL_SendHMPing", $arg, 1); # send another ping in 10s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub
|
||||
CUL_SendFromQueue($$)
|
||||
{
|
||||
my ($hash, $bstring) = @_;
|
||||
my $now = gettimeofday();
|
||||
my $name = $hash->{NAME};
|
||||
my $hm = ($bstring =~ m/^A/);
|
||||
my $to = ($hm ? 0.15 : 0.3);
|
||||
my $now = gettimeofday();
|
||||
if($bstring ne "") {
|
||||
my $sp = AttrVal($name, "sendpool", undef);
|
||||
if($sp) { # Is one of the CUL-fellows sending data?
|
||||
@ -707,7 +775,71 @@ CUL_SendFromQueue($$)
|
||||
}
|
||||
|
||||
if($hm) {
|
||||
CUL_SimpleWrite($hash, $bstring) if(!CUL_XmitDlyHM($hash,$bstring,$now));
|
||||
my ($fn,undef,$bs1,$did,$bs2) = unpack 'A1A1A14A6A*',$bstring;
|
||||
my $burst = hex(substr($bstring,6,1)) & 0x1;
|
||||
my $nxt;
|
||||
if(defined($did)) { # message to any device?
|
||||
#credit check
|
||||
if ($burst) {
|
||||
if (defined($hash->{helper}{hmccredits}) && ($hash->{helper}{hmccredits} < 2)) { # no credits for burst message
|
||||
InternalTimer($now+140, "CUL_XmitDlyHMTo", "$name:$did", 1); # try later again and collect credits
|
||||
my $lbstring = join(" ",unpack('A2A2A2A4A6A6A*',$bstring));
|
||||
Log3 $name, 2, "CUL_send: ".$name." try to send burst ".$lbstring." in 140s, low credits";
|
||||
CUL_SendHMPing("$hash->{NAME}:Ping"); #but ping to actualize credits state
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (defined($hash->{helper}{hmccredits}) && ($hash->{helper}{hmccredits} < 1)) { # no credits for non burst message
|
||||
InternalTimer($now+20, "CUL_XmitDlyHMTo", "$name:$did", 1); # try later again and collect credits
|
||||
my $lbstring = join(" ",unpack('A2A2A2A4A6A6A*',$bstring));
|
||||
Log3 $name, 2, "CUL_send: ".$name." try to send ".$lbstring." in 20s, low credits";
|
||||
CUL_SendHMPing("$hash->{NAME}:Ping"); #but ping to actualize credits state
|
||||
return;
|
||||
}
|
||||
}
|
||||
if($did && #not on broadcasts
|
||||
$modules{CUL_HM}{defptr}{$did} &&
|
||||
$modules{CUL_HM}{defptr}{$did}{helper}{io} &&
|
||||
$modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend}) {
|
||||
if(!$burst) {
|
||||
$nxt = $modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend};
|
||||
if (($now - $nxt) > 10) { # after 10 seconds forget about any answer. to be optimized!
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend});
|
||||
$nxt = undef;
|
||||
}
|
||||
} else { # burst can't be an answer
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend});
|
||||
}
|
||||
}
|
||||
}
|
||||
my $dDly;
|
||||
my $wt;
|
||||
if(defined($nxt)) {
|
||||
if($hash->{helper}{ref}{Sdly} <= $CUL_hmMaxSysDly) {
|
||||
$dDly = CUL_XmitDlyHM($hash,$did,$now,$nxt);
|
||||
$wt = int($dDly*125+0.5); # wait time in 8ms units
|
||||
if ($wt > 0) {
|
||||
$wt = 15 if ($wt > 15);
|
||||
$wt = sprintf("%X", $wt);
|
||||
$bstring = $fn."w0".$wt.$bs1.$did.$bs2; # new send string with send wait command
|
||||
}
|
||||
} else { #don't send answer without a chance to be in time, wait next try of device
|
||||
my $lbstring = join(" ",unpack('A2A2A2A4A6A6A*',$bstring));
|
||||
Log3 $name, 4, "CUL_send: ".$name." didn't send ".$lbstring." SDly:".$hash->{helper}{ref}{Sdly}.">".$CUL_hmMaxSysDly;
|
||||
$bstring = undef;
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{nextSend});
|
||||
}
|
||||
}
|
||||
CUL_SimpleWrite($hash, $bstring) if(defined($bstring));
|
||||
Log3 $name, 4, "CUL_send: ".$name." dly:".int($dDly*1000)." Sdly:".$hash->{helper}{ref}{Sdly}." id:".$did if(defined($dDly));
|
||||
if ($did) {
|
||||
if ($hash->{helper}{$did}{QUEUE}){
|
||||
shift(@{$hash->{helper}{$did}{QUEUE}});
|
||||
# InternalTimer($now+$hash->{helper}{ref}{hmSysACKwait}, "CUL_XmitDlyHMTo", "$name:$did", 1)
|
||||
InternalTimer($now+0.03, "CUL_XmitDlyHMTo", "$name:$did", 1)
|
||||
if (scalar(@{$hash->{helper}{$did}{QUEUE}}));
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
CUL_XmitLimitCheck($hash, $bstring, $now);
|
||||
@ -728,8 +860,8 @@ CUL_AddSendQueue($$)
|
||||
my ($hash, $bstring) = @_;
|
||||
my $qHash = $hash;
|
||||
if ($bstring =~ m/^A/){ # HM device
|
||||
my $id = substr($bstring,16,6);#get HMID destination
|
||||
$qHash = $hash->{helper}{$id};
|
||||
my $did = substr($bstring,16,6);#get HMID destination
|
||||
$qHash = $hash->{helper}{$did};
|
||||
}
|
||||
if(!$qHash->{QUEUE} || 0 == scalar(@{$qHash->{QUEUE}})) {
|
||||
$qHash->{QUEUE} = [ $bstring ];
|
||||
@ -788,44 +920,45 @@ sub
|
||||
CUL_Parse($$$$@)
|
||||
{
|
||||
my ($hash, $iohash, $name, $rmsg, $initstr) = @_;
|
||||
my $tn = gettimeofday(); # time of reception of message in s
|
||||
|
||||
if($rmsg =~ m/^\*/) { # STACKABLE_CC
|
||||
if($rmsg =~ m/^\*/) { # STACKABLE_CC
|
||||
Dispatch($hash, $rmsg, undef);
|
||||
return;
|
||||
}
|
||||
|
||||
my $rssi;
|
||||
my $dmsg = $rmsg;
|
||||
my $dmsgLog = (AttrVal($name,"rfmode","") eq "HomeMatic")
|
||||
? join(" ",(unpack'A1A2A2A4A6A6A*',$rmsg))
|
||||
:$dmsg;
|
||||
if($dmsg =~ m/^[AFTKEHRStZrib]([A-F0-9][A-F0-9])+$/) { # RSSI
|
||||
my $l = length($dmsg);
|
||||
$rssi = hex(substr($dmsg, $l-2, 2));
|
||||
$dmsg = substr($dmsg, 0, $l-2);
|
||||
$rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74));
|
||||
Log3 $name, 4, "CUL_Parse: $name $dmsgLog $rssi";
|
||||
} else {
|
||||
Log3 $name, 4, "CUL_Parse: $name $dmsgLog";
|
||||
my $dmsg = my $dmsgLog = $rmsg;
|
||||
my $len = length($dmsg);
|
||||
|
||||
if(!$dmsg || $len < 1){ # Bogus messages
|
||||
Log3 $name, 4, "CUL_Parse: $name Bogus messages";
|
||||
next;
|
||||
}
|
||||
|
||||
my $fn = substr($dmsg,0,1);
|
||||
my $rssi = "";
|
||||
|
||||
if($fn =~ m/[AFTKEHRStZrib]/) { # RSSI
|
||||
if($dmsg =~ m/^.([A-F0-9][A-F0-9])+[A-F0-9]*$/) {
|
||||
$rssi = hex(substr($dmsg, $len-2, 2));
|
||||
$rssi = ($rssi>=128 ? (($rssi-256)/2-74) : ($rssi/2-74));
|
||||
$dmsg = substr($dmsg, 0, $len-2);
|
||||
$len -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
###########################################
|
||||
#Translate Message from CUL to FHZ
|
||||
next if(!$dmsg || length($dmsg) < 1); # Bogus messages
|
||||
#Translate Message from CUL to FHZ
|
||||
|
||||
if ($dmsg eq 'SMODE' || $dmsg eq 'TMODE') { # brs/brt returns SMODE/TMODE
|
||||
Log3 $name, 5, "CUL_Parse: switched to $dmsg";
|
||||
return;
|
||||
}
|
||||
|
||||
if($dmsg =~ m/^[0-9A-F]{4}U./) { # RF_ROUTER
|
||||
Dispatch($hash, $dmsg, undef);
|
||||
return;
|
||||
}
|
||||
|
||||
my $fn = substr($dmsg,0,1);
|
||||
my $len = length($dmsg);
|
||||
|
||||
if($fn eq "F" && $len >= 9) { # Reformat for 10_FS20.pm
|
||||
CUL_AddSendQueue($iohash, ""); # Delay immediate replies
|
||||
$dmsg = sprintf("81%02x04xx0101a001%s00%s",
|
||||
@ -870,7 +1003,7 @@ CUL_Parse($$$$@)
|
||||
# Other K... Messages ar sent to CUL_WS
|
||||
} elsif($fn eq "r" && $len >= 23) { # Revolt
|
||||
$dmsg = lc($dmsg);
|
||||
} elsif($fn eq "i" && $len >= 7) { # IT
|
||||
} elsif($fn eq "i" && $len >= 7) { # IT
|
||||
$dmsg = lc($dmsg);
|
||||
} elsif($fn eq "Y" && $len >= 3) { # SOMFY RTS
|
||||
;
|
||||
@ -882,18 +1015,108 @@ CUL_Parse($$$$@)
|
||||
;
|
||||
} elsif($fn eq "I" && $len >= 12) { # IR-CUL/CUN/CUNO
|
||||
;
|
||||
} elsif($fn eq "A" && $len >= 20) { # AskSin/BidCos/HomeMatic
|
||||
my $src = substr($dmsg,9,6);
|
||||
if($modules{CUL_HM}{defptr}{$src}){
|
||||
$modules{CUL_HM}{defptr}{$src}{helper}{io}{nextSend} =
|
||||
gettimeofday() + 0.100;
|
||||
}
|
||||
$dmsg .= "::$rssi:$name" if(defined($rssi));
|
||||
} elsif($fn eq "A" ) { # AskSin/BidCos/HomeMatic
|
||||
|
||||
my $tnms = int($tn*1000); #"Reception" Timestamp in ms (time of computing received message)
|
||||
my $tnl = $tnms % 1000000;
|
||||
$tnl = sprintf("%06d", $tnl); #"Reception" Timestamp for log in ms (999999ms max)
|
||||
$dmsgLog = " ".$tnl;
|
||||
|
||||
my ($mId,$flg,$tc,$tp,$ts,$m) = unpack'A1A2A1A1A8A*',$dmsg; #$tc is credits coarse state
|
||||
if($flg eq "FF"){#2: iocu1: unknown message AFF02 00135B12 01 12
|
||||
|
||||
$ts = (hex($ts) & 0x1fffffff) << 3; #Timestamp ticks to ms, one tick -> 8ms
|
||||
|
||||
my $tsl = $ts & 0xffffff; #Timestamp for log in ms (24bit)
|
||||
$tsl = sprintf("%08d", $tsl); #Timestamp decimal in log in ms
|
||||
$tsl = " ".$mId." ".$flg.$tc.$tp." ".$tsl." ";
|
||||
|
||||
# credit level Ids, are ored to Timestamp ID (here extracted in $tc) should be given to 10_CUL_HM.pm to plan send of messages
|
||||
# TS_ID_CREDIT_NONE 0x0 -> credits < 5 not clearly enough credits for another non burst message
|
||||
# TS_ID_CREDIT_NONBURST 0x1 -> credits >= 5 still enough credits for another non burst message
|
||||
# TS_ID_CREDIT_BURST 0x2 -> credits >= 40 still enough credits for another burst message
|
||||
# TS_ID_CREDIT_10PCT 0x3 -> credits >= 10% of hourly credits left
|
||||
# TS_ID_CREDIT_20PCT 0x4 -> credits >= 20% of hourly credits left
|
||||
# TS_ID_CREDIT_40PCT 0x5 -> credits >= 40% of hourly credits left
|
||||
# TS_ID_CREDIT_60PCT 0x6 -> credits >= 60% of hourly credits left
|
||||
# TS_ID_CREDIT_80PCT 0x7 -> credits >= 80% of hourly credits left
|
||||
# TS_ID_CREDIT_90PCT 0x8 -> credits >= 90% of hourly credits left
|
||||
# TS_ID_CREDIT_100PCT 0xF -> credits == 100% of hourly credits left
|
||||
|
||||
if ($tp eq "1"){# 1: received message - dispatch
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
# process received message - dispatch
|
||||
CUL_dlytime($ts,$tnms,$hash);
|
||||
$dmsg = $mId.$m;
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} elsif ($tp eq "2"){# 2: ping message - log, but don't dispatch
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A*',$m));
|
||||
# process pings - implementation pending
|
||||
$dmsg = "";
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} elsif ($tp eq "3"){# 3: send timestamp success message, don't dispatch
|
||||
my $did = substr($m,14,6);
|
||||
if($modules{CUL_HM}{defptr}{$did}) {
|
||||
if($modules{CUL_HM}{defptr}{$did}{helper}{io}{lhmRecTm}) {
|
||||
my $dhmSt = ($ts - $modules{CUL_HM}{defptr}{$did}{helper}{io}{lhmRecTm})%4294967296;
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{lhmRecTm});
|
||||
# delay auto adjust
|
||||
if($modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly} &&
|
||||
($modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly} > 0) &&
|
||||
($modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly} < ($dhmSt*0.001)) &&
|
||||
($dhmSt < 384)) { # don't correct on strange delay, e.g. due to CCA
|
||||
if ($dhmSt > ($CUL_hmDestDel)) {
|
||||
$hash->{helper}{ref}{hmSysACKwait} -= 0.002; # slowly decrease delay
|
||||
$hash->{helper}{ref}{hmSysACKwait} = 0 if ($hash->{helper}{ref}{hmSysACKwait} < 0);
|
||||
}
|
||||
if ($dhmSt < $CUL_hmDestDel) {
|
||||
$hash->{helper}{ref}{hmSysACKwait} += 0.004; # faster increase delay
|
||||
$hash->{helper}{ref}{hmSysACKwait} = 0.120 if ($hash->{helper}{ref}{hmSysACKwait} > 0.120);
|
||||
}
|
||||
}
|
||||
Log3 $name, 4, "CUL_parse: ".$name." dhmSt:".$dhmSt." hmSysACKwait:".$hash->{helper}{ref}{hmSysACKwait} if ($dhmSt < 5000);
|
||||
}
|
||||
if($modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly}) {
|
||||
delete($modules{CUL_HM}{defptr}{$did}{helper}{io}{lastSndDly});
|
||||
}
|
||||
}
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
$dmsg = "";
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} elsif ($tp eq "4"){# 4: send timestamp fail channel busy message - do not process
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
$dmsg = "";
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} elsif ($tp eq "5"){# 5: send timestamp fail credits message - do not process
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
$dmsg = "";
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} elsif ($tp eq "6"){# 6: send timestamp fail message length message - do not process
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
$dmsg = "";
|
||||
$hash->{helper}{hmccredits} = hex($tc);
|
||||
} else { # unkown - do not process
|
||||
$dmsgLog .= $tsl.join(" ",(unpack'A2A2A4A6A6A*',$m));
|
||||
$dmsg = "";
|
||||
}
|
||||
$len = length($dmsg);
|
||||
} else {
|
||||
$dmsgLog .= " ".join(" ",(unpack'A1A2A2A4A6A6A*',$dmsg));
|
||||
}
|
||||
|
||||
if ( $len >= 20){
|
||||
my $src = substr($dmsg,9,6);
|
||||
if($modules{CUL_HM}{defptr}{$src}){
|
||||
$modules{CUL_HM}{defptr}{$src}{helper}{io}{nextSend} = $tn + $hash->{helper}{ref}{hmSysACKwait};
|
||||
$modules{CUL_HM}{defptr}{$src}{helper}{io}{lhmRecTm} = $ts;
|
||||
}
|
||||
$dmsg .= "::$rssi" if ($rssi ne "");
|
||||
$dmsg .= ":$name";
|
||||
}
|
||||
} elsif($fn eq "Z" && $len >= 21) { # Moritz/Max
|
||||
;
|
||||
} elsif($fn eq "b" && $len >= 24) { # Wireless M-Bus
|
||||
$dmsg .= "::$rssi" if (defined($rssi));
|
||||
$dmsg .= "::$rssi" if ($rssi ne "");
|
||||
} elsif($fn eq "t" && $len >= 5) { # TX3
|
||||
$dmsg = "TX".substr($dmsg,1); # t.* is occupied by FHTTK
|
||||
} elsif($fn eq "s" && $len >= 5) { # CUL_TCM97001
|
||||
@ -903,20 +1126,62 @@ CUL_Parse($$$$@)
|
||||
Log3 $name, 2, "$name: unknown message $dmsg";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Log3 $name, 4, "CUL_Parse: $name $dmsgLog $rssi";
|
||||
return if(!$dmsg);
|
||||
|
||||
$hash->{"${name}_MSGCNT"}++;
|
||||
$hash->{"${name}_TIME"} =
|
||||
# showtime attribute
|
||||
readingsSingleUpdate($hash, "state", $hash->{READINGS}{state}{VAL}, 0);
|
||||
$hash->{RAWMSG} = $rmsg;
|
||||
my %addvals = (RAWMSG => $dmsg);
|
||||
if(defined($rssi)) {
|
||||
if($rssi ne "") {
|
||||
$hash->{RSSI} = $rssi;
|
||||
$addvals{RSSI} = $rssi;
|
||||
}
|
||||
Dispatch($hash, $dmsg, \%addvals);
|
||||
#General Dispatch($hash, $dmsg, \%addvals);
|
||||
}
|
||||
|
||||
sub CUL_dlytime($$@) {#########################################################
|
||||
my ($hmtC,$sysC,$hash) = @_;
|
||||
# hmtC : hometic timecounter in ms
|
||||
# sysC : system time in ms
|
||||
# ref.hmtL : last timestamp of reception
|
||||
# ref.sysL : system timestamp of last calculation
|
||||
# ref.dly : delay of system computing received data
|
||||
# ref.kTs : keep alive timestamp
|
||||
# ref.offL : offset between time and HM timer
|
||||
|
||||
if (!defined $hash->{helper}{ref} ||
|
||||
!defined $hash->{helper}{ref}{sysL} ||
|
||||
!defined $hash->{helper}{ref}{hmtL}){
|
||||
$hash->{helper}{ref}{sysL} = $sysC;
|
||||
$hash->{helper}{ref}{hmtL} = $hmtC;
|
||||
}
|
||||
|
||||
my $ref = $hash->{helper}{ref};#shortcut
|
||||
|
||||
my ($ds,$di) = (($sysC - $ref->{sysL}),
|
||||
($hmtC - $ref->{hmtL})%4294967296);
|
||||
if (($ds < 0) || ($di < 0)) { #strange differences
|
||||
$ds = 0;
|
||||
$di = 1; # force new reference
|
||||
}
|
||||
|
||||
my $dly = $ds - $di;
|
||||
if($dly >= 0) {$ref->{Sdly} = $dly;} # system is delayed with computing received data
|
||||
else {$ref->{Sdly} = 0;} # minimal or less system delay
|
||||
|
||||
if(($dly <= 0) || # take a new reference to get better
|
||||
(($ds > 360000) && ($dly < 10))) # force a new reference every 6 minutes, but only with low delay
|
||||
{
|
||||
$ref->{sysL} = $sysC;
|
||||
$ref->{hmtL} = $hmtC;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
@ -956,7 +1221,15 @@ CUL_SimpleWrite(@)
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
if (AttrVal($name,"rfmode","") eq "HomeMatic"){
|
||||
Log3 $name, 4, "CUL_send: $name".join(" ",unpack('A2A2A2A4A6A6A*',$msg));
|
||||
my $tnms = int(gettimeofday()*1000); #Send Timestamp in ms
|
||||
my $tnl = $tnms % 1000000;
|
||||
$tnl = sprintf("%06d", $tnl); #Send Timestamp for log in ms (999999ms max)
|
||||
|
||||
if (substr($msg,1,1) eq "w") {
|
||||
Log3 $name, 4, "CUL_send: $name ".$tnl." ".join(" ",unpack('A2A2A2A2A4A6A6A*',$msg));
|
||||
} else {
|
||||
Log3 $name, 4, "CUL_send: $name ".$tnl." ".join(" ",unpack('A2A2A2A4A6A6A*',$msg));
|
||||
}
|
||||
}
|
||||
else{
|
||||
Log3 $name, 5, "SW: $msg";
|
||||
@ -994,6 +1267,12 @@ CUL_Attr(@)
|
||||
$hash->{MatchList} = \%matchListHomeMatic;
|
||||
CUL_SimpleWrite($hash, "Zx") if ($hash->{CMDS} =~ m/Z/); # reset Moritz
|
||||
$hash->{initString} = "X21\nAr"; # X21 is needed for RSSI reporting
|
||||
if (InternalVal($name,"VERSION_TS","") eq "yes"){
|
||||
if ($hash->{initString} !~ m/At1/){
|
||||
$hash->{initString} .= "\nAt1";
|
||||
}
|
||||
}
|
||||
|
||||
CUL_WriteInit($hash);
|
||||
|
||||
} else {
|
||||
@ -1039,8 +1318,6 @@ CUL_Attr(@)
|
||||
Log3 $name, 2, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return if($hash->{initString} eq "X21");
|
||||
$hash->{Clients} = $clientsSlowRF;
|
||||
@ -1057,9 +1334,11 @@ CUL_Attr(@)
|
||||
delete $hash->{".clientArray"};
|
||||
} elsif($aName eq "hmId"){
|
||||
if ($cmd eq "set"){
|
||||
return "wrong syntax: hmId must be 6-digit-hex-code (3 byte)"
|
||||
if ($aVal !~ m/^[A-F0-9]{6}$/i);
|
||||
}
|
||||
my $owner_ccu = InternalVal($name,"owner_CCU",undef);
|
||||
return "device owned by $owner_ccu" if ($owner_ccu);
|
||||
return "wrong syntax: hmId must be 6-digit-hex-code (3 byte)"
|
||||
if ($aVal !~ m/^[A-F0-9]{6}$/i);
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
@ -1305,7 +1584,7 @@ CUL_prefix($$$)
|
||||
</ul>
|
||||
</li><br>
|
||||
|
||||
<li><a name="hmId">hmId</a><br>
|
||||
<li><a name="hmId">hmId</a><br>
|
||||
Set the HomeMatic ID of this device. If this attribute is absent, the
|
||||
ID will be F1<FHTID>. Note 1: After setting or changing this
|
||||
attribute you have to relearn all your HomeMatic devices. Note 2: The
|
||||
|
@ -2231,9 +2231,9 @@ sub CUL_HM_Parse($$) {#########################################################
|
||||
# stateflag meaning unknown
|
||||
push @evtEt,[$shash,1,"state:".(($lvl eq "FF")?"locked":((hex($lvl)/2)))];
|
||||
if ($chn eq "01"){
|
||||
my %err = (0=>"no",1=>"TurnError",2=>"TiltError");
|
||||
my %err = (0=>"ok",1=>"TurnError",2=>"TiltError");
|
||||
my %dir = (0=>"no",1=>"up",2=>"down",3=>"undefined");
|
||||
push @evtEt,[$shash,1,"motorError:".$err{(hex($stat)>>1)&0x03}];
|
||||
push @evtEt,[$shash,1,"motorErr:" .$err{(hex($stat)>>1)&0x03}];
|
||||
push @evtEt,[$shash,1,"direction:" .$dir{(hex($stat)>>4)&0x03}];
|
||||
}
|
||||
else{ #should be akku
|
||||
@ -9031,7 +9031,7 @@ sub CUL_HM_tempListTmpl(@) { ##################################################
|
||||
</li>
|
||||
<li><B>winMatic</B><br>
|
||||
[locked|$value]<br>
|
||||
motorError [no|TurnError|TiltError]<br>
|
||||
motorErr [ok|TurnError|TiltError]<br>
|
||||
direction [no|up|down|undefined]<br>
|
||||
charge [trickleCharge|charge|dischange|unknown]<br>
|
||||
airing [inactiv|$air]<br>
|
||||
@ -10310,7 +10310,7 @@ sub CUL_HM_tempListTmpl(@) { ##################################################
|
||||
</li>
|
||||
<li><B>winMatic</B><br>
|
||||
[locked|$value]<br>
|
||||
motorError [no|TurnError|TiltError]<br>
|
||||
motorErr [ok|TurnError|TiltError]<br>
|
||||
direction [no|up|down|undefined]<br>
|
||||
charge [trickleCharge|charge|dischange|unknown]<br>
|
||||
airing [inactiv|$air]<br>
|
||||
|
@ -48,7 +48,7 @@ sub HMinfo_Define($$){#########################################################
|
||||
.",overload:off"
|
||||
.",overheat:off"
|
||||
.",reduced:off"
|
||||
.",motorError:no"
|
||||
.",motorErr:ok"
|
||||
.",error:none"
|
||||
.",uncertain:yes"
|
||||
.",smoke_detect:none"
|
||||
@ -136,6 +136,7 @@ sub HMinfo_status($){##########################################################
|
||||
}
|
||||
#--- used for IO, protocol and communication (e.g. rssi)
|
||||
my @IOdev;
|
||||
my %IOccu;
|
||||
|
||||
my %protC = (ErrIoId_ =>0,ErrIoAttack =>0);
|
||||
my %protE = (NACK =>0,IOerr =>0,ResndFail =>0,CmdDel =>0);
|
||||
@ -171,6 +172,7 @@ sub HMinfo_status($){##########################################################
|
||||
if ($ehash->{helper}{role}{dev}){#---restrict to devices
|
||||
$nbrD++;
|
||||
push @IOdev,$ehash->{IODev}{NAME} if($ehash->{IODev} && $ehash->{IODev}{NAME});
|
||||
$IOccu{(split ":",AttrVal($eName,"IOgrp",""))[0]}=1;
|
||||
push @Anames,$eName if ($attr{$eName}{actStatus} && $attr{$eName}{actStatus} ne "alive");
|
||||
|
||||
foreach (grep /ErrIoId_/, keys %{$ehash}){# detect addtional critical entries
|
||||
@ -203,32 +205,33 @@ sub HMinfo_status($){##########################################################
|
||||
my @updates;
|
||||
foreach my $read(grep {defined $sum{$_}} @info){ #--- disp crt count
|
||||
my $d;
|
||||
$d .= "$_:$sum{$read}{$_};"foreach(keys %{$sum{$read}});
|
||||
$d .= "$_:$sum{$read}{$_},"foreach(keys %{$sum{$read}});
|
||||
push @updates,"I_sum_$read:".$d;
|
||||
}
|
||||
foreach my $read(grep {defined $err{$_}} keys %errFlt){#--- disp err count
|
||||
my $d;
|
||||
$d .= "$_:$err{$read}{$_};"foreach(keys %{$err{$read}});
|
||||
$d .= "$_:$err{$read}{$_},"foreach(keys %{$err{$read}});
|
||||
push @updates,"ERR_$read:".$d;
|
||||
}
|
||||
|
||||
@errNames = grep !/^$/,HMinfo_noDup(@errNames);
|
||||
$hash->{ERR_names} = join",",@errNames if(@errNames);# and name entities
|
||||
|
||||
push @updates,"C_sumDefined:"."entities:$nbrE device:$nbrD channel:$nbrC virtual:$nbrV";
|
||||
push @updates,"C_sumDefined:"."entities:$nbrE,device:$nbrD,channel:$nbrC,virtual:$nbrV";
|
||||
# ------- display status of action detector ------
|
||||
push @updates,"I_actTotal:".$modules{CUL_HM}{defptr}{"000000"}{STATE};
|
||||
push @updates,"I_actTotal:".join",",(split" ",$modules{CUL_HM}{defptr}{"000000"}{STATE});
|
||||
$hash->{ERRactNames} = join",",@Anames if (@Anames);
|
||||
|
||||
# ------- what about IO devices??? ------
|
||||
push @IOdev,split ",",AttrVal($_,"IOList","")foreach (keys %IOccu);
|
||||
|
||||
my %tmp; # remove duplicates
|
||||
$tmp{$_}=0 for @IOdev;
|
||||
delete $tmp{""}; #remove empties if present
|
||||
@IOdev = sort keys %tmp;
|
||||
foreach (grep {$defs{$_}{READINGS}{cond}} @IOdev){
|
||||
$_ .= ",:".$defs{$_}{READINGS}{cond}{VAL};
|
||||
$hash->{I_HM_IOdevices} = "";
|
||||
$tmp{ReadingsVal($_,"cond",
|
||||
InternalVal($_,"STATE","unknown"))}{$_} = 1 foreach( @IOdev);
|
||||
foreach my $IOstat (sort keys %tmp){
|
||||
$hash->{I_HM_IOdevices} .= "$IOstat: ".join(",",sort keys %{$tmp{$IOstat}}).";";
|
||||
}
|
||||
$hash->{I_HM_IOdevices}= join",",@IOdev;
|
||||
|
||||
# ------- what about protocol events ------
|
||||
# Current Events are Rcv,NACK,IOerr,Resend,ResendFail,Snd
|
||||
@ -2074,7 +2077,7 @@ sub HMinfo_noDup(@) {#return list with no duplicates###########################
|
||||
<li>CUL_HM related IO devices and condition</li>
|
||||
<li>Device protocol events which are related to communication errors</li>
|
||||
<li>count of certain readings (e.g. batterie) and conditions - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
<li>count of error condition in readings (e.g. overheat, motorError) - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
<li>count of error condition in readings (e.g. overheat, motorErr) - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
@ -2502,7 +2505,7 @@ sub HMinfo_noDup(@) {#return list with no duplicates###########################
|
||||
<li>CUL_HM Geräte und Zustände</li>
|
||||
<li>Ereignisse im Zusammenhang mit Kommunikationsproblemen</li>
|
||||
<li>Zähler für bestimmte Readings und Zustände (z.B. battery) - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
<li>Zähler für Readings, die auf Fehler hindeuten (z.B. overheat, motorError) - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
<li>Zähler für Readings, die auf Fehler hindeuten (z.B. overheat, motorErr) - <a href="#HMinfoattr">attribut controlled</a></li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user