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

98_ArduCounter.pm: neues Reading longX

git-svn-id: https://svn.fhem.de/fhem/trunk@15148 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
StefanStrobel 2017-09-28 18:10:35 +00:00
parent bef1811d01
commit 437d765d0c

View File

@ -44,7 +44,8 @@
# 2017-02-06 Doku korrigiert # 2017-02-06 Doku korrigiert
# 2017-02-18 fixed a bug that caused a missing open when the device is defined while fhem is already initialized # 2017-02-18 fixed a bug that caused a missing open when the device is defined while fhem is already initialized
# 2017-05-09 fixed character encoding for documentation text # 2017-05-09 fixed character encoding for documentation text
# 2017-09-24 interpolation of lost impulses during fhem restart / arduino reset
#
# ideas / todo: # ideas / todo:
# #
@ -66,7 +67,7 @@ my %ArduCounter_gets = (
"info" => "" "info" => ""
); );
my $ArduCounter_Version = '4.71 - 9.5.2017'; my $ArduCounter_Version = '4.8 - 24.9.2017';
# #
# FHEM module intitialisation # FHEM module intitialisation
@ -92,6 +93,7 @@ sub ArduCounter_Initialize($)
"factor " . "factor " .
"readingNameCount[0-9]+ " . "readingNameCount[0-9]+ " .
"readingNamePower[0-9]+ " . "readingNamePower[0-9]+ " .
"readingNameLongCount[0-9]+ " .
"readingFactor[0-9]+ " . "readingFactor[0-9]+ " .
"readingStartTime[0-9]+ " . "readingStartTime[0-9]+ " .
"verboseReadings[0-9]+ " . "verboseReadings[0-9]+ " .
@ -569,10 +571,13 @@ sub ArduCounter_Parse($)
my $retStr = ""; my $retStr = "";
my @lines = split /\n/, $hash->{buffer}; my @lines = split /\n/, $hash->{buffer};
my $now = gettimeofday();
foreach my $line (@lines) { foreach my $line (@lines) {
# Log3 $name, 5, "$name: Parse line: $line"; # Log3 $name, 5, "$name: Parse line: $line";
if ($line =~ 'R([\d]+) C([\d]+) D([\d]+) T([\d]+)( N[\d]+)?( X[\d]+)?( F[\d]+)?(L [\d]+)?( A[\d]+)?') if ($line =~ 'R([\d]+) C([\d]+) D([\d]+) T([\d]+)( N[\d]+)?( X[\d]+)?( F[\d]+)?(L [\d]+)?( A[\d]+)?')
{ {
# new count is beeing reported
my $pin = $1; my $pin = $1;
my $count = $2; my $count = $2;
my $diff = $3; my $diff = $3;
@ -584,12 +589,12 @@ sub ArduCounter_Parse($)
my $avgLen = ($9 ? substr($9, 2) : ""); my $avgLen = ($9 ? substr($9, 2) : "");
my $factor = AttrVal($name, "readingFactor$pin", AttrVal($name, "factor", 1000)); my $factor = AttrVal($name, "readingFactor$pin", AttrVal($name, "factor", 1000));
my $rcname = AttrVal($name, "readingNameCount$pin", "pin$pin"); my $rcname = AttrVal($name, "readingNameCount$pin", "pin$pin"); # internal count reading name
my $rpname = AttrVal($name, "readingNamePower$pin", "power$pin"); my $rlname = AttrVal($name, "readingNameLongCount$pin", "long$pin"); # long count - continues after reset, interpolates
my $lName = AttrVal($name, "readingNamePower$pin", AttrVal($name, "readingNameCount$pin", "pin$pin")); my $rpname = AttrVal($name, "readingNamePower$pin", "power$pin"); # power reading name
my $lName = AttrVal($name, "readingNamePower$pin", AttrVal($name, "readingNameCount$pin", "pin$pin")); # for logging
my $chIdx = 0; my $chIdx = 0;
my $now = gettimeofday();
my $sTime = $now - $time/1000; # start of observation interval (~first pulse) my $sTime = $now - $time/1000; # start of observation interval (~first pulse)
my $fSTime = FmtDateTime($sTime); # formatted my $fSTime = FmtDateTime($sTime); # formatted
my $fSdTim = FmtTime($sTime); # only time formatted my $fSdTim = FmtTime($sTime); # only time formatted
@ -597,10 +602,44 @@ sub ArduCounter_Parse($)
my $eTime = $now; # now / end of observation interval my $eTime = $now; # now / end of observation interval
my $fETime = FmtDateTime($eTime); # formatted my $fETime = FmtDateTime($eTime); # formatted
my $fEdTim = FmtTime($eTime); # only time formatted my $fEdTim = FmtTime($eTime); # only time formatted
if (!$time || !$factor) {
Log3 $name, 3, "$name: Pin $pin ($lName) skip line because time or factor is 0: $line";
next;
}
my $power = sprintf ("%.3f", ($time ? $diff/$time/1000*3600*$factor : 0)); my $power = sprintf ("%.3f", ($time ? $diff/$time/1000*3600*$factor : 0));
my $longCount;
Log3 $name, 4, "$name: Pin $pin ($lName) count $count (diff $diff) in " .
if (AttrVal($name, "verboseReadings$pin", 0)) {
$longCount = ReadingsVal($name, $rlname, 0); # alter long count Wert im Reading
if (!$hash->{CounterInterpolated}{$pin} && $hash->{CounterResetTime}) {
my $lastCountTime = ReadingsTimestamp ($name, $rlname, 0); # last time this reading was set
my $lastCountTNum = time_str2num($lastCountTime);
my $offlineTime = sprintf ("%.2f", $hash->{CounterResetTime} - $lastCountTNum);
my $lastInterval = ReadingsVal ($name, "timeDiff$pin", 0);
my $lastCDiff = ReadingsVal ($name, "countDiff$pin", 0);
my $lastRatio = $lastCDiff / $lastInterval;
my $curRatio = $diff / $time;
my $intRatio = 1000 * ($lastRatio + $curRatio) / 2;
my $interpolationCount = int($offlineTime * $intRatio) + 1; # add one that gets lost as start of new interval
if ($lastCountTime && $lastInterval && $lastCDiff) {
Log3 $name, 4, "$name: interpolation after counter reset for pin $pin ($lName): offline $offlineTime secs, $interpolationCount estimated pulses (before $lastCDiff in $lastInterval ms, now $diff in $time ms, avg ratio $intRatio p/s)";
Log3 $name, 4, "$name: adding interpolated $interpolationCount and $diff to long count $longCount";
$longCount += $interpolationCount;
} else {
Log3 $name, 4, "$name: interpolation for pin $pin ($lName) not possible - no historic data";
}
$hash->{CounterInterpolated}{$pin} = 1;
}
$longCount += $diff;
}
Log3 $name, 4, "$name: Pin $pin ($lName) count $count longCount $longCount (diff $diff) in " .
sprintf("%.3f", $time/1000) . "s" . sprintf("%.3f", $time/1000) . "s" .
((defined($reject) && $reject ne "") ? ", reject $reject" : "") . ((defined($reject) && $reject ne "") ? ", reject $reject" : "") .
($avgLen ? ", Avg Len ${avgLen}ms" : "") . ($avgLen ? ", Avg Len ${avgLen}ms" : "") .
@ -612,19 +651,22 @@ sub ArduCounter_Parse($)
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
if (AttrVal($name, "readingStartTime$pin", 0)) { if (AttrVal($name, "readingStartTime$pin", 0)) {
$hash->{".updateTime"} = $sTime;
$hash->{".updateTimestamp"} = $fSTime;
Log3 $name, 5, "$name: readingStartTime$pin specified: setting reading timestamp to $fSdTim"; Log3 $name, 5, "$name: readingStartTime$pin specified: setting reading timestamp to $fSdTim";
Log3 $name, 5, "$name: set readings $rpname to $power, timeDiff$pin to $time and countDiff$pin to $diff"; Log3 $name, 5, "$name: set readings $rpname to $power, timeDiff$pin to $time and countDiff$pin to $diff";
$hash->{".updateTime"} = $sTime;
$hash->{".updateTimestamp"} = $fSTime;
readingsBulkUpdate($hash, $rpname, $power) if ($time); readingsBulkUpdate($hash, $rpname, $power) if ($time);
$hash->{CHANGETIME}[$chIdx++] = $fSTime; # Intervall start $hash->{CHANGETIME}[$chIdx++] = $fSTime; # Intervall start
$hash->{".updateTime"} = $eTime; $hash->{".updateTime"} = $eTime;
$hash->{".updateTimestamp"} = $fETime; $hash->{".updateTimestamp"} = $fETime;
readingsBulkUpdate($hash, $rcname, $count); readingsBulkUpdate($hash, $rcname, $count);
$hash->{CHANGETIME}[$chIdx++] = $fETime; $hash->{CHANGETIME}[$chIdx++] = $fETime;
if (AttrVal($name, "verboseReadings$pin", 0)) { if (AttrVal($name, "verboseReadings$pin", 0)) {
readingsBulkUpdate($hash, $rlname, $longCount);
$hash->{CHANGETIME}[$chIdx++] = $fETime;
readingsBulkUpdate($hash, "timeDiff$pin", $time); readingsBulkUpdate($hash, "timeDiff$pin", $time);
$hash->{CHANGETIME}[$chIdx++] = $fETime; $hash->{CHANGETIME}[$chIdx++] = $fETime;
readingsBulkUpdate($hash, "countDiff$pin", $diff); readingsBulkUpdate($hash, "countDiff$pin", $diff);
@ -639,9 +681,10 @@ sub ArduCounter_Parse($)
} else { } else {
Log3 $name, 5, "$name: set readings $rpname to $power, timeDiff$pin to $time and countDiff$pin to $diff"; Log3 $name, 5, "$name: set readings $rpname to $power, timeDiff$pin to $time and countDiff$pin to $diff";
readingsBulkUpdate($hash, $rpname, $power) if ($time); readingsBulkUpdate($hash, $rpname, $power) if ($time);
$eTime = time_str2num(ReadingsTimestamp ($name, $rpname, 0)); #$eTime = time_str2num(ReadingsTimestamp ($name, $rpname, 0));
readingsBulkUpdate($hash, $rcname, $count); readingsBulkUpdate($hash, $rcname, $count);
if (AttrVal($name, "verboseReadings$pin", 0)) { if (AttrVal($name, "verboseReadings$pin", 0)) {
readingsBulkUpdate($hash, $rlname, $longCount);
readingsBulkUpdate($hash, "timeDiff$pin", $time); readingsBulkUpdate($hash, "timeDiff$pin", $time);
readingsBulkUpdate($hash, "countDiff$pin", $diff); readingsBulkUpdate($hash, "countDiff$pin", $diff);
readingsBulkUpdate($hash, "lastMsg$pin", $line); readingsBulkUpdate($hash, "lastMsg$pin", $line);
@ -710,10 +753,12 @@ sub ArduCounter_Parse($)
if ($hash->{Initialized}) { if ($hash->{Initialized}) {
ArduCounter_ConfigureDevice($hash) # send pin configuration ArduCounter_ConfigureDevice($hash) # send pin configuration
} }
delete $hash->{WaitForHello}; delete $hash->{WaitForHello};
RemoveInternalTimer ("hwait:$name"); # dont wait for hello reply if already sent RemoveInternalTimer ("hwait:$name"); # dont wait for hello reply if already sent
RemoveInternalTimer ("sendHello:$name"); # Hello not needed anymore if not sent yet RemoveInternalTimer ("sendHello:$name"); # Hello not needed anymore if not sent yet
$hash->{CounterResetTime} = $now;
delete $hash->{CounterInterpolated};
} elsif ($line =~ /V([\d\.]+).?Setup done/) { # old setup message } elsif ($line =~ /V([\d\.]+).?Setup done/) { # old setup message
Log3 $name, 3, "$name: device is flashed with an old and incompatible firmware : $1"; Log3 $name, 3, "$name: device is flashed with an old and incompatible firmware : $1";
@ -1005,6 +1050,8 @@ sub ArduCounter_Ready($)
<li><b>readingNameCount[0-9]+</b></li> <li><b>readingNameCount[0-9]+</b></li>
Change the name of the counter reading pinX to something more meaningful. Change the name of the counter reading pinX to something more meaningful.
<li><b>readingNameLongCount[0-9]+</b></li>
Change the name of the long counter reading longX (only created when verboseReadingsX is set to 1) to something more meaningful.
<li><b>readingNamePower[0-9]+</b></li> <li><b>readingNamePower[0-9]+</b></li>
Change the name of the power reading powerX to something more meaningful. Change the name of the power reading powerX to something more meaningful.
<li><b>readingFactor[0-9]+</b></li> <li><b>readingFactor[0-9]+</b></li>
@ -1022,7 +1069,8 @@ sub ArduCounter_Ready($)
the current count at this pin the current count at this pin
<li><b>power.*</b></li> <li><b>power.*</b></li>
the current calculated power at this pin the current calculated power at this pin
Most reading names can be customized with attribues and many more readings can be generated by setting the attribute verboseReadings[0-9]+ to 1. Most reading names can be customized with attribues and many more readings can be generated by setting the attribute verboseReadings[0-9]+ to 1.<br>
This includes the "long count" reading which keeps on counting up after fhem restarts whereas the pin.* count is only a temporary internal count that starts at 0 when the arduino board starts.
</ul> </ul>
<br> <br>
</ul> </ul>