93_DbRep: diffValue - recognize if diff is 0 or no value available

git-svn-id: https://svn.fhem.de/fhem/trunk@25280 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2021-12-01 21:44:21 +00:00
parent e5850b4b3e
commit e4ceb4777a
2 changed files with 106 additions and 86 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: 93_DbRep: diffValue - recognize if diff is 0 or no value available
- change: 72_FB_CALLLIST: reading "count-missed-calls" only counts incoming - change: 72_FB_CALLLIST: reading "count-missed-calls" only counts incoming
missed calls missed calls
- bugfix: 88_HMCCU: Fixed device detection bug - bugfix: 88_HMCCU: Fixed device detection bug

View File

@ -57,6 +57,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
my %DbRep_vNotesIntern = ( my %DbRep_vNotesIntern = (
"8.44.1" => "27.11.2021 change diffValue: recognize if diff is 0 or no value available ",
"8.44.0" => "21.11.2021 new attr numDecimalPlaces ", "8.44.0" => "21.11.2021 new attr numDecimalPlaces ",
"8.43.1" => "02.11.2021 fix SQL statement if devspec can't be resolved, Forum:https://forum.fhem.de/index.php/topic,53584.msg1184155.html#msg1184155 ", "8.43.1" => "02.11.2021 fix SQL statement if devspec can't be resolved, Forum:https://forum.fhem.de/index.php/topic,53584.msg1184155.html#msg1184155 ",
"8.43.0" => "22.09.2021 consider attr device, reading in sqlCmd, remove length limit of attr device, reading ", "8.43.0" => "22.09.2021 consider attr device, reading in sqlCmd, remove length limit of attr device, reading ",
@ -3997,7 +3998,7 @@ return;
# nichtblockierende DB-Abfrage diffValue # nichtblockierende DB-Abfrage diffValue
#################################################################################################### ####################################################################################################
sub diffval_DoParse { sub diffval_DoParse {
my ($string) = @_; my $string = shift;
my ($name,$device,$reading,$prop,$ts) = split("\\§", $string); my ($name,$device,$reading,$prop,$ts) = split("\\§", $string);
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
@ -4006,18 +4007,22 @@ sub diffval_DoParse {
my $dblogname = $dbloghash->{NAME}; my $dblogname = $dbloghash->{NAME};
my $dbmodel = $dbloghash->{MODEL}; my $dbmodel = $dbloghash->{MODEL};
my $dbpassword = $attr{"sec$dblogname"}{secret}; my $dbpassword = $attr{"sec$dblogname"}{secret};
my ($dbh,$sql,$sth,$err,$selspec); my ($dbh,$sql,$sth,$err,$selspec);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1 });}; eval { $dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0,
RaiseError => 1,
if ($@) { AutoInactiveDestroy => 1
$err = encode_base64($@,""); }
); 1;
}
or do { $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|$device|$reading|''|''|''|$err|''"; return "$name|''|$device|$reading|''|''|''|$err|''";
} };
# only for this block because of warnings if details of readings are not set # only for this block because of warnings if details of readings are not set
no warnings 'uninitialized'; no warnings 'uninitialized';
@ -4033,7 +4038,8 @@ sub diffval_DoParse {
#vorbereiten der DB-Abfrage, DB-Modell-abhaengig #vorbereiten der DB-Abfrage, DB-Modell-abhaengig
if($dbmodel eq "MYSQL") { if($dbmodel eq "MYSQL") {
$selspec = "TIMESTAMP,VALUE, if(VALUE-\@V < 0 OR \@RB = 1 , \@diff:= 0, \@diff:= VALUE-\@V ) as DIFF, \@V:= VALUE as VALUEBEFORE, \@RB:= '0' as RBIT "; $selspec = "TIMESTAMP,VALUE, if(VALUE-\@V < 0 OR \@RB = 1 , \@diff:= 0, \@diff:= VALUE-\@V ) as DIFF, \@V:= VALUE as VALUEBEFORE, \@RB:= '0' as RBIT ";
} else { }
else {
$selspec = "TIMESTAMP,VALUE"; $selspec = "TIMESTAMP,VALUE";
} }
@ -4063,9 +4069,11 @@ sub diffval_DoParse {
if ($IsTimeSet || $IsAggrSet) { if ($IsTimeSet || $IsAggrSet) {
$sql = DbRep_createSelectSql($hash,"history",$selspec,$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",'ORDER BY TIMESTAMP'); $sql = DbRep_createSelectSql($hash,"history",$selspec,$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",'ORDER BY TIMESTAMP');
} else { }
else {
$sql = DbRep_createSelectSql($hash,"history",$selspec,$device,$reading,undef,undef,'ORDER BY TIMESTAMP'); $sql = DbRep_createSelectSql($hash,"history",$selspec,$device,$reading,undef,undef,'ORDER BY TIMESTAMP');
} }
Log3 ($name, 4, "DbRep $name - SQL execute: $sql"); Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
eval{ $sth = $dbh->prepare($sql); eval{ $sth = $dbh->prepare($sql);
@ -4076,11 +4084,12 @@ sub diffval_DoParse {
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$device|$reading|''|''|''|$err|''"; return "$name|''|$device|$reading|''|''|''|$err|''";
}
} else {
if($dbmodel eq "MYSQL") { if($dbmodel eq "MYSQL") {
@array = map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]." ".$_ -> [2]."\n" } @{ $sth->fetchall_arrayref() }; @array = map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]." ".$_ -> [2]."\n" } @{ $sth->fetchall_arrayref() };
} else { }
else {
@array = map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]."\n" } @{ $sth->fetchall_arrayref() }; @array = map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]."\n" } @{ $sth->fetchall_arrayref() };
if (@array) { if (@array) {
@ -4088,18 +4097,21 @@ sub diffval_DoParse {
my $dse = 0; my $dse = 0;
my $vold; my $vold;
my @sqlite_array; my @sqlite_array;
foreach my $row (@array) {
for my $row (@array) {
@sp = split("[ \t][ \t]*", $row, 4); @sp = split("[ \t][ \t]*", $row, 4);
my $runtime_string = $sp[0]; my $runtime_string = $sp[0];
my $timestamp = $sp[2]?$sp[1]." ".$sp[2]:$sp[1]; my $timestamp = $sp[2] ? $sp[1]." ".$sp[2] : $sp[1];
my $vnew = $sp[3]; my $vnew = $sp[3];
$vnew =~ tr/\n//d; $vnew =~ tr/\n//d;
$dse = ($vold && (($vnew-$vold) > 0))?($vnew-$vold):0; $dse = $vold && (($vnew-$vold) > 0) ? ($vnew-$vold) : 0;
@sp = $runtime_string." ".$timestamp." ".$vnew." ".$dse."\n"; @sp = $runtime_string." ".$timestamp." ".$vnew." ".$dse."\n";
$vold = $vnew; $vold = $vnew;
push(@sqlite_array, @sp); push(@sqlite_array, @sp);
} }
@array = @sqlite_array; @array = @sqlite_array;
} }
} }
@ -4109,17 +4121,19 @@ sub diffval_DoParse {
if($aval eq "hour") { if($aval eq "hour") {
my @rsf = split(/[ :]/,$runtime_string_first); my @rsf = split(/[ :]/,$runtime_string_first);
@array = ($runtime_string." ".$rsf[0]."_".$rsf[1]."\n"); @array = ($runtime_string." ".$rsf[0]."_".$rsf[1]."\n");
} elsif($aval eq "minute") { }
elsif($aval eq "minute") {
my @rsf = split(/[ :]/,$runtime_string_first); my @rsf = split(/[ :]/,$runtime_string_first);
@array = ($runtime_string." ".$rsf[0]."_".$rsf[1]."-".$rsf[2]."\n"); @array = ($runtime_string." ".$rsf[0]."_".$rsf[1]."-".$rsf[2]."\n");
} else { }
else {
my @rsf = split(" ",$runtime_string_first); my @rsf = split(" ",$runtime_string_first);
@array = ($runtime_string." ".$rsf[0]."\n"); @array = ($runtime_string." ".$rsf[0]."\n");
} }
} }
push(@row_array, @array); push(@row_array, @array);
} }
}
# SQL-Laufzeit ermitteln # SQL-Laufzeit ermitteln
my $rt = tv_interval($st); my $rt = tv_interval($st);
@ -4133,8 +4147,9 @@ sub diffval_DoParse {
# Berechnung diffValue aus Selektionshash # Berechnung diffValue aus Selektionshash
my %rh = (); # Ergebnishash, wird alle Ergebniszeilen enthalten my %rh = (); # Ergebnishash, wird alle Ergebniszeilen enthalten
my %ch = (); # counthash, enthält die Anzahl der verarbeiteten Datasets pro runtime_string my %ch = (); # counthash, enthält die Anzahl der verarbeiteten Datasets pro runtime_string
my $lastruntimestring;
my $i = 1; my $i = 1;
my $max = ($#row_array)+1; # Anzahl aller Listenelemente
my $lastruntimestring;
my $lval; # immer der letzte Wert von $value my $lval; # immer der letzte Wert von $value
my $rslval; # runtimestring von lval my $rslval; # runtimestring von lval
my $uediff; # Übertragsdifferenz (Differenz zwischen letzten Wert einer Aggregationsperiode und dem ersten Wert der Folgeperiode) my $uediff; # Übertragsdifferenz (Differenz zwischen letzten Wert einer Aggregationsperiode und dem ersten Wert der Folgeperiode)
@ -4142,7 +4157,6 @@ sub diffval_DoParse {
my $diff_before; # Differenzwert vorheriger Datensatz my $diff_before; # Differenzwert vorheriger Datensatz
my $rejectstr; # String der ignorierten Differenzsätze my $rejectstr; # String der ignorierten Differenzsätze
my $diff_total; # Summenwert aller berücksichtigten Teildifferenzen my $diff_total; # Summenwert aller berücksichtigten Teildifferenzen
my $max = ($#row_array)+1; # Anzahl aller Listenelemente
Log3 ($name, 5, "DbRep $name - data of row_array result assigned to fields:\n"); Log3 ($name, 5, "DbRep $name - data of row_array result assigned to fields:\n");
@ -4177,7 +4191,7 @@ sub diffval_DoParse {
# Ergebnishash erzeugen # Ergebnishash erzeugen
if ($runtime_string eq $lastruntimestring) { if ($runtime_string eq $lastruntimestring) {
if ($i == 1) { if ($i == 1) {
$diff_total = $diff?$diff:0 if($diff <= $difflimit); $diff_total = $diff ? $diff : 0 if($diff <= $difflimit);
$rh{$runtime_string} = $runtime_string."|".$diff_total."|".$timestamp; $rh{$runtime_string} = $runtime_string."|".$diff_total."|".$timestamp;
$ch{$runtime_string} = 1 if($value); $ch{$runtime_string} = 1 if($value);
$lval = $value; $lval = $value;
@ -4198,20 +4212,20 @@ sub diffval_DoParse {
# neuer Zeitabschnitt beginnt, ersten Value-Wert erfassen und Übertragsdifferenz bilden # neuer Zeitabschnitt beginnt, ersten Value-Wert erfassen und Übertragsdifferenz bilden
$lastruntimestring = $runtime_string; $lastruntimestring = $runtime_string;
$i = 1; $i = 1;
$uediff = $value - $lval if($value > $lval); $uediff = $value - $lval if($value > $lval);
$diff = $uediff; $diff = $uediff;
$lval = $value if($value); # Übetrag über Perioden mit value = 0 hinweg ! $lval = $value if($value); # Übetrag über Perioden mit value = 0 hinweg !
$rslval = $runtime_string; $rslval = $runtime_string;
Log3 ($name, 4, "DbRep $name - balance difference of $uediff between $rslval and $runtime_string"); Log3 ($name, 4, "DbRep $name - balance difference of $uediff between $rslval and $runtime_string");
$diff_total = $diff ? $diff : 0 if($diff <= $difflimit);
$diff_total = $diff?$diff:0 if($diff <= $difflimit);
$rh{$runtime_string} = $runtime_string."|".$diff_total."|".$timestamp; $rh{$runtime_string} = $runtime_string."|".$diff_total."|".$timestamp;
$ch{$runtime_string} = 1 if($value); $ch{$runtime_string} = 1 if($value);
$uediff = 0; $uediff = 0;
} }
$i++; $i++;
} }
@ -4242,13 +4256,16 @@ sub diffval_DoParse {
# Ergebnisse in Datenbank schreiben # Ergebnisse in Datenbank schreiben
my ($wrt,$irowdone); my ($wrt,$irowdone);
if($prop =~ /writeToDB/) { if($prop =~ /writeToDB/) {
($wrt,$irowdone,$err) = DbRep_OutputWriteToDB($name,$device,$reading,$rows,"diff"); ($wrt,$irowdone,$err) = DbRep_OutputWriteToDB($name,$device,$reading,$rows,"diff");
if ($err) { if ($err) {
Log3 $hash->{NAME}, 2, "DbRep $name - $err"; Log3 $hash->{NAME}, 2, "DbRep $name - $err";
$err = encode_base64($err,""); $err = encode_base64($err,"");
return "$name|''|$device|$reading|''|''|''|$err|''"; return "$name|''|$device|$reading|''|''|''|$err|''";
} }
$rt = $rt+$wrt; $rt = $rt+$wrt;
} }
@ -4267,7 +4284,7 @@ sub diffval_DoParse {
# Auswertungsroutine der nichtblockierenden DB-Abfrage diffValue # Auswertungsroutine der nichtblockierenden DB-Abfrage diffValue
#################################################################################################### ####################################################################################################
sub diffval_ParseDone { sub diffval_ParseDone {
my ($string) = @_; my $string = shift;
my @a = split("\\|",$string); my @a = split("\\|",$string);
my $hash = $defs{$a[0]}; my $hash = $defs{$a[0]};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -4312,8 +4329,9 @@ sub diffval_ParseDone {
my %ncp = split("§", $ncpslist); my %ncp = split("§", $ncpslist);
my $ncpstr; my $ncpstr;
if(%ncp) { if(%ncp) {
foreach my $ncpkey (sort(keys(%ncp))) { for my $ncpkey (sort(keys(%ncp))) {
$ncpstr .= $ncpkey." || "; $ncpstr .= $ncpkey." || ";
} }
} }
@ -4322,15 +4340,17 @@ sub diffval_ParseDone {
my %rh = split("§", $rowlist); my %rh = split("§", $rowlist);
Log3 ($name, 4, "DbRep $name - result of diffValue calculation after decoding:"); Log3 ($name, 4, "DbRep $name - result of diffValue calculation after decoding:");
foreach my $key (sort(keys(%rh))) { for my $key (sort(keys(%rh))) {
Log3 ($name, 4, "DbRep $name - runtimestring Key: $key, value: ".$rh{$key}); Log3 ($name, 4, "DbRep $name - runtimestring Key: $key, value: ".$rh{$key});
} }
my $state = $erread?$erread:"done"; my $state = $erread?$erread:"done";
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
foreach my $key (sort(keys(%rh))) { for my $key (sort(keys(%rh))) {
my $valid = 0; # Datensatz hat kein Ergebnis als default
my @k = split("\\|",$rh{$key}); my @k = split("\\|",$rh{$key});
$valid = 1 if($k[2] =~ /(\d{4})-(\d{2})-(\d{2})_(\d{2}):(\d{2}):(\d{2})/x); # Datensatz hat einen Wert wenn kompletter Timestamp ist enthalten
my $rts = $k[2]."__"; my $rts = $k[2]."__";
$rts =~ s/:/-/g; # substituieren unsupported characters -> siehe fhem.pl $rts =~ s/:/-/g; # substituieren unsupported characters -> siehe fhem.pl
@ -4345,16 +4365,15 @@ sub diffval_ParseDone {
} }
my $rv = $k[1]; my $rv = $k[1];
ReadingsBulkUpdateValue ($hash, $reading_runtime_string, $rv ? sprintf("%.${ndp}f", $rv) : "-"); ReadingsBulkUpdateValue ($hash, $reading_runtime_string, (!$valid ? "-" : defined $rv ? sprintf "%.${ndp}f", $rv : "-"));
} }
ReadingsBulkUpdateValue ($hash, "db_lines_processed", $irowdone) if($hash->{LASTCMD} =~ /writeToDB/); ReadingsBulkUpdateValue ($hash, "db_lines_processed", $irowdone) if($hash->{LASTCMD} =~ /writeToDB/);
ReadingsBulkUpdateValue ($hash, "diff_overrun_limit_".$difflimit, $rowsrej) if($rowsrej); ReadingsBulkUpdateValue ($hash, "diff_overrun_limit_".$difflimit, $rowsrej) if($rowsrej);
ReadingsBulkUpdateValue ($hash, "less_data_in_period", $ncpstr) if($ncpstr); ReadingsBulkUpdateValue ($hash, "less_data_in_period", $ncpstr) if($ncpstr);
ReadingsBulkUpdateTimeState($hash,$brt,$rt,($ncpstr||$rowsrej)?"Warning":$state); ReadingsBulkUpdateTimeState ($hash,$brt,$rt,($ncpstr||$rowsrej)?"Warning":$state);
readingsEndUpdate($hash, 1); readingsEndUpdate ($hash, 1);
return; return;
} }