diff --git a/fhem/CHANGED b/fhem/CHANGED index c9acd082a..a9df88cff 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - feature: 93_DbLog: new Attr convertTimezone -> logging in UTC time - bugfix: 93_DbRep: fix set ... deleteOther for SQLite - feature: 60_allergy: alternative data source with Attribute alternative3Day - feature: 49_SSCAM: allow placeholders #CAM, #DATE, #TIME, #FILE, #CTIME diff --git a/fhem/FHEM/93_DbLog.pm b/fhem/FHEM/93_DbLog.pm index 71b8eb6a1..8d7f14c1f 100644 --- a/fhem/FHEM/93_DbLog.pm +++ b/fhem/FHEM/93_DbLog.pm @@ -18,8 +18,9 @@ package main; use strict; use warnings; -eval "use DBI;1" or my $DbLogMMDBI = "DBI"; -eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; +eval "use DBI;1" or my $DbLogMMDBI = "DBI"; +eval "use FHEM::Meta;1" or my $modMetaAbsent = 1; +eval "use FHEM::Utility::CTZ qw(:all);1" or my $ctzAbsent = 1; use Data::Dumper; use Blocking; use Time::HiRes qw(gettimeofday tv_interval); @@ -30,6 +31,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # Version History intern by DS_Starter: my %DbLog_vNotesIntern = ( + "4.13.0" => "15.04.2022 new Attr convertTimezone, minor fixes in reduceLog(NbL) ", "4.12.7" => "08.03.2022 \$data{firstvalX} doesn't work, forum: https://forum.fhem.de/index.php/topic,126631.0.html ", "4.12.6" => "17.01.2022 change log message deprecated to outdated, forum:#topic,41089.msg1201261.html#msg1201261 ", "4.12.5" => "31.12.2021 standard unit assignment for readings beginning with 'temperature' and removed, forum:#125087 ", @@ -280,6 +282,7 @@ sub DbLog_Initialize { "colEvent ". "colReading ". "colValue ". + "convertTimezone:UTC,none ". "DbLogSelectionMode:Exclude,Include,Exclude/Include ". "DbLogType:Current,History,Current/History,SampleFill/History ". "SQLiteJournalMode:WAL,off ". @@ -468,6 +471,13 @@ sub DbLog_Attr { if ($aName eq "SQLiteCacheSize" || $aName eq "SQLiteJournalMode") { InternalTimer(gettimeofday()+1.0, "DbLog_attrForSQLite", $hash, 0); InternalTimer(gettimeofday()+1.5, "DbLog_attrForSQLite", $hash, 0); # muß zweimal ausgeführt werden - Grund unbekannt :-( + } + + if ($aName eq "convertTimezone") { + return "The library FHEM::Utility::CTZ is missed. Please update FHEM completely." if($ctzAbsent); + + my $rmf = reqModFail(); + return "You have to install the required perl module: ".$rmf if($rmf); } } @@ -1445,11 +1455,31 @@ sub DbLog_Log { my $event = $events->[$i]; $event = "" if(!defined($event)); $event = DbLog_charfilter($event) if(AttrVal($name, "useCharfilter",0)); - Log3 $name, 4, "DbLog $name -> check Device: $dev_name , Event: $event" if($vb4show && !$hash->{HELPER}{".RUNNING_PID"}); + Log3 ($name, 4, "DbLog $name -> check Device: $dev_name , Event: $event") if($vb4show && !$hash->{HELPER}{".RUNNING_PID"}); if($dev_name =~ m/^$re$/ || "$dev_name:$event" =~ m/^$re$/ || $DbLogSelectionMode eq 'Include') { my $timestamp = $ts_0; - $timestamp = $dev_hash->{CHANGETIME}[$i] if(defined($dev_hash->{CHANGETIME}[$i])); + $timestamp = $dev_hash->{CHANGETIME}[$i] if(defined($dev_hash->{CHANGETIME}[$i])); + + my $ctz = AttrVal($name, 'convertTimezone', 'none'); # convert time zone + if($ctz ne 'none') { + my $err; + my $params = { + name => $name, + dtstring => $timestamp, + tzcurrent => 'local', + tzconv => $ctz, + writelog => 0 + }; + + ($err, $timestamp) = convertTimeZone ($params); + + if ($err) { + Log3 ($name, 1, "DbLog $name - ERROR while converting time zone: $err - exit log loop !"); + last; + } + } + $event =~ s/\|/_ESC_/gxs; # escape Pipe "|" my @r = DbLog_ParseEvent($name,$dev_name, $dev_type, $event); @@ -1639,6 +1669,7 @@ sub DbLog_Log { else { Log3 ($name, 2, "DbLog $name -> Parameter TIMESTAMP got from valueFn is invalid: $TIMESTAMP"); } + $dev_name = $DEVICE if($DEVICE ne ''); $dev_type = $DEVICETYPE if($DEVICETYPE ne ''); $reading = $READING if($READING ne ''); @@ -4865,15 +4896,16 @@ sub DbLog_AddLog { $value_fn = ''; } - my $now = gettimeofday(); - + my $now = gettimeofday(); my $rdspec = (split ":",$devrdspec)[-1]; - my @dc = split(":",$devrdspec); + my @dc = split(":",$devrdspec); pop @dc; my $devspec = join(':',@dc); my @exdvs = devspec2array($devspec); + Log3 $name, 4, "DbLog $name -> Addlog known devices by devspec: @exdvs"; + foreach (@exdvs) { $dev_name = $_; if(!$defs{$dev_name}) { @@ -4886,6 +4918,7 @@ sub DbLog_AddLog { my $DbLogInclude = AttrVal($dev_name, "DbLogInclude", undef); my @exrds; my $found = 0; + foreach my $rd (sort keys %{$r}) { # jedes Reading des Devices auswerten my $do = 1; $found = 1 if($rd =~ m/^$rdspec$/); # Reading gefunden @@ -4909,6 +4942,7 @@ sub DbLog_AddLog { next if(!$do); push @exrds,$rd if($rd =~ m/^$rdspec$/); } + Log3 $name, 4, "DbLog $name -> Readings extracted from Regex: @exrds"; if(!$found) { @@ -4927,7 +4961,7 @@ sub DbLog_AddLog { no warnings 'uninitialized'; foreach (@exrds) { $dev_reading = $_; - $read_val = $value ne ""?$value:ReadingsVal($dev_name,$dev_reading,""); + $read_val = $value ne "" ? $value : ReadingsVal($dev_name,$dev_reading,""); $dev_type = uc($defs{$dev_name}{TYPE}); # dummy-Event zusammenstellen @@ -4938,15 +4972,36 @@ sub DbLog_AddLog { $dev_reading = $r[0]; $read_val = $r[1]; $ut = $r[2]; - if(!defined $dev_reading) {$dev_reading = "";} - if(!defined $read_val) {$read_val = "";} + if(!defined $dev_reading) {$dev_reading = "";} + if(!defined $read_val) {$read_val = "";} if(!defined $ut || $ut eq "") {$ut = AttrVal("$dev_name", "unit", "");} + $event = "addLog"; $defs{$dev_name}{Helper}{DBLOG}{$dev_reading}{$hash->{NAME}}{TIME} = $now; $defs{$dev_name}{Helper}{DBLOG}{$dev_reading}{$hash->{NAME}}{VALUE} = $read_val; + $ts = TimeNow(); + my $ctz = AttrVal($name, 'convertTimezone', 'none'); # convert time zone + if($ctz ne 'none') { + my $err; + my $params = { + name => $name, + dtstring => $ts, + tzcurrent => 'local', + tzconv => $ctz, + writelog => 0 + }; + + ($err, $ts) = convertTimeZone ($params); + + if ($err) { + Log3 ($name, 1, "DbLog $name - ERROR while converting time zone: $err - exit log loop !"); + last; + } + } + # Anwender spezifische Funktion anwenden if($value_fn ne '') { my $lastt = $defs{$dev_name}{Helper}{DBLOG}{$dev_reading}{$hash->{NAME}}{TIME}; # patch Forum:#111423 @@ -4962,7 +5017,7 @@ sub DbLog_AddLog { my $LASTVALUE = $lastv // ""; # patch Forum:#111423 my $UNIT = $ut; my $IGNORE = 0; - my $CN = $cn?$cn:""; + my $CN = $cn ? $cn : ""; eval $value_fn; Log3 $name, 2, "DbLog $name -> error valueFn: ".$@ if($@); @@ -4981,6 +5036,7 @@ sub DbLog_AddLog { else { Log3 ($name, 2, "DbLog $name -> Parameter TIMESTAMP got from valueFn is invalid: $TIMESTAMP"); } + $dev_name = $DEVICE if($DEVICE ne ''); $dev_type = $DEVICETYPE if($DEVICETYPE ne ''); $dev_reading = $READING if($READING ne ''); @@ -5006,7 +5062,11 @@ sub DbLog_AddLog { $data{DbLog}{$name}{cache}{index}++; my $index = $data{DbLog}{$name}{cache}{index}; $data{DbLog}{$name}{cache}{memcache}{$index} = $row; - my $memcount = $data{DbLog}{$name}{cache}{memcache}?scalar(keys %{$data{DbLog}{$name}{cache}{memcache}}):0; + + my $memcount = $data{DbLog}{$name}{cache}{memcache} ? + scalar(keys %{$data{DbLog}{$name}{cache}{memcache}}) : + 0; + if($ce == 1) { readingsSingleUpdate($hash, "CacheUsage", $memcount, 1); } @@ -5021,6 +5081,7 @@ sub DbLog_AddLog { } use warnings; } + if(!$async) { if(@row_array) { # synchoner Mode @@ -5230,12 +5291,14 @@ sub DbLog_reduceLog { .(($average && $filter) ? ", " : '').(($filter) ? uc((split('=',$a[-1]))[0]).'='.(split('=',$a[-1]))[1] : '')); my ($useac,$useta) = DbLog_commitMode($hash); - my $ac = ($dbh->{AutoCommit})?"ON":"OFF"; - my $tm = ($useta)?"ON":"OFF"; + my $ac = ($dbh->{AutoCommit}) ? "ON" : "OFF"; + my $tm = ($useta) ? "ON" : "OFF"; + Log3 $hash->{NAME}, 4, "DbLog $name -> AutoCommit mode: $ac, Transaction mode: $tm"; my ($od,$nd) = split(":",$a[2]); # $od - Tage älter als , $nd - Tage neuer als my ($ots,$nts); + if ($hash->{MODEL} eq 'SQLITE') { $ots = "datetime('now', '-$od days')"; $nts = "datetime('now', '-$nd days')" if($nd); @@ -5287,12 +5350,16 @@ sub DbLog_reduceLog { eval { my $i = 0; my $k = 1; - my $th = ($#dayRows <= 2000)?100:($#dayRows <= 30000)?1000:10000; + my $th = ($#dayRows <= 2000) ? 100 : + ($#dayRows <= 30000) ? 1000 : + 10000; + for my $delRow (@dayRows) { if($day != 00 || $delRow->[0] !~ /$lastHour/) { Log3($name, 5, "DbLog $name: DELETE FROM $history WHERE (DEVICE=$delRow->[1]) AND (READING=$delRow->[3]) AND (TIMESTAMP=$delRow->[0]) AND (VALUE=$delRow->[4])"); $sth_del->execute(($delRow->[1], $delRow->[3], $delRow->[0], $delRow->[4])); $i++; + if($i == $th) { my $prog = $k * $i; Log3($name, 3, "DbLog $name: reduceLog deletion progress of day: $processingDay is: $prog"); @@ -5302,6 +5369,7 @@ sub DbLog_reduceLog { } } }; + if ($@) { Log3($hash->{NAME}, 3, "DbLog $name: reduceLog ! FAILED ! for day $processingDay"); eval {$dbh->rollback() if(!$dbh->{AutoCommit});}; @@ -5313,6 +5381,7 @@ sub DbLog_reduceLog { $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; } + @dayRows = (); } @@ -5332,9 +5401,10 @@ sub DbLog_reduceLog { $updateCount += $c; Log3($name, 3, "DbLog $name: reduceLog (hourly-average) updating $c records of day: $processingDay") if($c); # else only push to @averageUpdD - my $i = 0; - my $k = 1; + my $i = 0; + my $k = 1; my $th = ($c <= 2000)?100:($c <= 30000)?1000:10000; + for my $hourHash (@averageUpd) { for my $hourKey (keys %$hourHash) { if ($hourHash->{$hourKey}->[0]) { # true if reading is a number @@ -5371,9 +5441,10 @@ sub DbLog_reduceLog { else { eval {$dbh->commit() if(!$dbh->{AutoCommit});}; } + $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; - @averageUpd = (); + @averageUpd = (); } if (defined($a[3]) && $a[3] =~ /average=day/i && scalar(@averageUpdD) && $day != 00) { @@ -5399,14 +5470,19 @@ sub DbLog_reduceLog { $deletedCount += $c; $updateCount += keys(%averageHash); - my ($id,$iu) = 0; - my ($kd,$ku) = 1; - my $thd = ($c <= 2000)?100:($c <= 30000)?1000:10000; - my $thu = ((keys %averageHash) <= 2000)?100:((keys %averageHash) <= 30000)?1000:10000; + my ($id,$iu) = (0,0); + my ($kd,$ku) = (1,1); + my $thd = ($c <= 2000)?100:($c <= 30000) ? 1000 : 10000; + my $thu = ((keys %averageHash) <= 2000) ? 100 : + ((keys %averageHash) <= 30000) ? 1000 : + 10000; + Log3($name, 3, "DbLog $name: reduceLog (daily-average) updating ".(keys %averageHash).", deleting $c records of day: $processingDay") if(keys %averageHash); + for my $reading (keys %averageHash) { $average = sprintf('%.3f', $averageHash{$reading}->{sum}/scalar(@{$averageHash{$reading}->{tedr}})); $lastUpdH = pop @{$averageHash{$reading}->{tedr}}; + for (@{$averageHash{$reading}->{tedr}}) { Log3($name, 5, "DbLog $name: DELETE FROM $history WHERE DEVICE='$_->[2]' AND READING='$_->[3]' AND TIMESTAMP='$_->[0]'"); $sth_delD->execute(($_->[2], $_->[3], $_->[0])); @@ -5419,7 +5495,9 @@ sub DbLog_reduceLog { $kd++; } } + Log3($name, 5, "DbLog $name: UPDATE $history SET TIMESTAMP=$averageHash{$reading}->{date} 12:00:00, EVENT='rl_av_d', VALUE=$average WHERE (DEVICE=$lastUpdH->[2]) AND (READING=$lastUpdH->[3]) AND (TIMESTAMP=$lastUpdH->[0])"); + $sth_updD->execute(($averageHash{$reading}->{date}." 12:00:00", 'rl_av_d', $average, $lastUpdH->[2], $lastUpdH->[3], $lastUpdH->[0])); $iu++; @@ -5439,12 +5517,14 @@ sub DbLog_reduceLog { else { eval {$dbh->commit() if(!$dbh->{AutoCommit});}; } + $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; } + %averageHash = (); %hourlyKnown = (); - @averageUpd = (); + @averageUpd = (); @averageUpdD = (); $currentHour = 99; } @@ -5455,9 +5535,11 @@ sub DbLog_reduceLog { if (defined($a[3]) && $a[3] =~ /average/i && keys(%hourlyKnown)) { push(@averageUpd, {%hourlyKnown}); } + %hourlyKnown = (); $currentHour = $hour; } + if (defined $hourlyKnown{$row->[1].$row->[3]}) { # remember first readings for device per h, other can be deleted push(@dayRows, [@$row]); if (defined($a[3]) && $a[3] =~ /average/i && defined($row->[4]) && $row->[4] =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/ && $hourlyKnown{$row->[1].$row->[3]}->[0]) { @@ -5471,6 +5553,7 @@ sub DbLog_reduceLog { for (@excludeRegex) { $exclude = 1 if("$row->[1]:$row->[3]" =~ /^$_$/); } + if ($exclude) { $excludeCount++ if($day != 00); } @@ -5478,14 +5561,18 @@ sub DbLog_reduceLog { $hourlyKnown{$row->[1].$row->[3]} = (defined($row->[4]) && $row->[4] =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/) ? [$row->[0],$row->[1],$row->[2],$row->[3],[$row->[4]]] : [0]; } } + $processingDay = (split(' ',$row->[0]))[0]; - } while( $day != 00 ); + + } while ($day != 00); my $result = "Rows processed: $rowCount, deleted: $deletedCount" .((defined($a[3]) && $a[3] =~ /average/i)? ", updated: $updateCount" : '') .(($excludeCount)? ", excluded: $excludeCount" : '') .", time: ".sprintf('%.2f',time() - $startTime)."sec"; + Log3($name, 3, "DbLog $name: reduceLog executed. $result"); + readingsSingleUpdate($hash,"reduceLogState",$result,1); $ret = "reduceLog executed. $result"; } @@ -5506,7 +5593,9 @@ sub DbLog_reduceLogNbl { my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0; my $history = $hash->{HELPER}{TH}; my $current = $hash->{HELPER}{TC}; + delete $hash->{HELPER}{REDUCELOG}; + my ($ret,$row,$filter,$exclude,$c,$day,$hour,$lastHour,$updDate,$updHour,$average,$processingDay,$lastUpdH,%hourlyKnown,%averageHash,@excludeRegex,@dayRows,@averageUpd,@averageUpdD); my ($startTime,$currentHour,$currentDay,$deletedCount,$updateCount,$sum,$rowCount,$excludeCount) = (time(),99,0,0,0,0,0,0); my ($dbh,$err); @@ -5514,10 +5603,10 @@ sub DbLog_reduceLogNbl { Log3 ($name, 5, "DbLog $name -> Start DbLog_reduceLogNbl"); my ($useac,$useta) = DbLog_commitMode($hash); - if(!$useac) { + if (!$useac) { eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, AutoCommit => 0 });}; } - elsif($useac == 1) { + elsif ($useac == 1) { eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, AutoCommit => 1 });}; } else { @@ -5534,9 +5623,11 @@ sub DbLog_reduceLogNbl { if ($a[-1] =~ /^EXCLUDE=(.+:.+)+/i) { ($filter) = $a[-1] =~ /^EXCLUDE=(.+)/i; @excludeRegex = split(',',$filter); - } elsif ($a[-1] =~ /^INCLUDE=.+:.+$/i) { + } + elsif ($a[-1] =~ /^INCLUDE=.+:.+$/i) { $filter = 1; } + if (defined($a[3])) { $average = ($a[3] =~ /average=day/i) ? "AVERAGE=DAY" : ($a[3] =~ /average/i) ? "AVERAGE=HOUR" : 0; } @@ -5545,11 +5636,12 @@ sub DbLog_reduceLogNbl { .(($average || $filter) ? ', ' : '').(($average) ? "$average" : '') .(($average && $filter) ? ", " : '').(($filter) ? uc((split('=',$a[-1]))[0]).'='.(split('=',$a[-1]))[1] : '')); - my $ac = ($dbh->{AutoCommit})?"ON":"OFF"; - my $tm = ($useta)?"ON":"OFF"; + my $ac = ($dbh->{AutoCommit}) ? "ON" : "OFF"; + my $tm = ($useta) ? "ON" : "OFF"; + Log3 $hash->{NAME}, 4, "DbLog $name -> AutoCommit mode: $ac, Transaction mode: $tm"; - my ($od,$nd) = split(":",$a[2]); # $od - Tage älter als , $nd - Tage neuer als + my ($od,$nd) = split(":",$a[2]); # $od - Tage älter als , $nd - Tage neuer als my ($ots,$nts); if ($hash->{MODEL} eq 'SQLITE') { @@ -5598,27 +5690,35 @@ sub DbLog_reduceLogNbl { $ret = 1; ($day,$hour) = $row->[0] =~ /-(\d{2})\s(\d{2}):/; $rowCount++ if($day != 00); + if ($day != $currentDay) { if ($currentDay) { # false on first executed day if (scalar @dayRows) { ($lastHour) = $dayRows[-1]->[0] =~ /(.*\d+\s\d{2}):/; $c = 0; + for my $delRow (@dayRows) { $c++ if($day != 00 || $delRow->[0] !~ /$lastHour/); } + if($c) { $deletedCount += $c; + Log3($name, 3, "DbLog $name: reduceLogNbl deleting $c records of day: $processingDay"); + $dbh->{RaiseError} = 1; $dbh->{PrintError} = 0; eval {$dbh->begin_work() if($dbh->{AutoCommit});}; + if ($@) { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } + eval { - my $i = 0; - my $k = 1; + my $i = 0; + my $k = 1; my $th = ($#dayRows <= 2000)?100:($#dayRows <= 30000)?1000:10000; + for my $delRow (@dayRows) { if($day != 00 || $delRow->[0] !~ /$lastHour/) { Log3($name, 4, "DbLog $name: DELETE FROM $history WHERE (DEVICE=$delRow->[1]) AND (READING=$delRow->[3]) AND (TIMESTAMP=$delRow->[0]) AND (VALUE=$delRow->[4])"); @@ -5648,9 +5748,11 @@ sub DbLog_reduceLogNbl { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } } + $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; } + @dayRows = (); } @@ -5661,6 +5763,7 @@ sub DbLog_reduceLogNbl { if ($@) { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } + eval { push(@averageUpd, {%hourlyKnown}) if($day != 00); @@ -5670,12 +5773,14 @@ sub DbLog_reduceLogNbl { $c++ if ($hourHash->{$hourKey}->[0] && scalar(@{$hourHash->{$hourKey}->[4]}) > 1); } } + $updateCount += $c; Log3($name, 3, "DbLog $name: reduceLogNbl (hourly-average) updating $c records of day: $processingDay") if($c); # else only push to @averageUpdD - my $i = 0; - my $k = 1; + my $i = 0; + my $k = 1; my $th = ($c <= 2000)?100:($c <= 30000)?1000:10000; + for my $hourHash (@averageUpd) { for my $hourKey (keys %$hourHash) { if ($hourHash->{$hourKey}->[0]) { # true if reading is a number @@ -5683,8 +5788,10 @@ sub DbLog_reduceLogNbl { if (scalar(@{$hourHash->{$hourKey}->[4]}) > 1) { # true if reading has multiple records this hour for (@{$hourHash->{$hourKey}->[4]}) { $sum += $_; } $average = sprintf('%.3f', $sum/scalar(@{$hourHash->{$hourKey}->[4]}) ); - $sum = 0; + $sum = 0; + Log3($name, 4, "DbLog $name: UPDATE $history SET TIMESTAMP=$updDate $updHour:30:00, EVENT='rl_av_h', VALUE=$average WHERE DEVICE=$hourHash->{$hourKey}->[1] AND READING=$hourHash->{$hourKey}->[3] AND TIMESTAMP=$hourHash->{$hourKey}->[0] AND VALUE=$hourHash->{$hourKey}->[4]->[0]"); + $sth_upd->execute(("$updDate $updHour:30:00", 'rl_av_h', $average, $hourHash->{$hourKey}->[1], $hourHash->{$hourKey}->[3], $hourHash->{$hourKey}->[0], $hourHash->{$hourKey}->[4]->[0])); $i++; @@ -5703,6 +5810,7 @@ sub DbLog_reduceLogNbl { } } }; + if ($@) { $err = $@; Log3($hash->{NAME}, 2, "DbLog $name - reduceLogNbl average=hour ! FAILED ! for day $processingDay: $err"); @@ -5718,6 +5826,7 @@ sub DbLog_reduceLogNbl { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } } + $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; @averageUpd = (); @@ -5730,6 +5839,7 @@ sub DbLog_reduceLogNbl { if ($@) { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } + eval { for (@averageUpdD) { push(@{$averageHash{$_->[3].$_->[4]}->{tedr}}, [$_->[0], $_->[1], $_->[3], $_->[4]]); @@ -5749,14 +5859,21 @@ sub DbLog_reduceLogNbl { $deletedCount += $c; $updateCount += keys(%averageHash); - my ($id,$iu) = 0; - my ($kd,$ku) = 1; - my $thd = ($c <= 2000)?100:($c <= 30000)?1000:10000; - my $thu = ((keys %averageHash) <= 2000)?100:((keys %averageHash) <= 30000)?1000:10000; + my ($id,$iu) = (0,0); + my ($kd,$ku) = (1,1); + my $thd = ($c <= 2000) ? 100 : + ($c <= 30000) ? 1000 : + 10000; + my $thu = ((keys %averageHash) <= 2000) ? 100 : + ((keys %averageHash) <= 30000) ? 1000 : + 10000; + Log3($name, 3, "DbLog $name: reduceLogNbl (daily-average) updating ".(keys %averageHash).", deleting $c records of day: $processingDay") if(keys %averageHash); + for my $reading (keys %averageHash) { - $average = sprintf('%.3f', $averageHash{$reading}->{sum}/scalar(@{$averageHash{$reading}->{tedr}})); + $average = sprintf('%.3f', $averageHash{$reading}->{sum}/scalar(@{$averageHash{$reading}->{tedr}})); $lastUpdH = pop @{$averageHash{$reading}->{tedr}}; + for (@{$averageHash{$reading}->{tedr}}) { Log3($name, 5, "DbLog $name: DELETE FROM $history WHERE DEVICE='$_->[2]' AND READING='$_->[3]' AND TIMESTAMP='$_->[0]'"); $sth_delD->execute(($_->[2], $_->[3], $_->[0])); @@ -5769,7 +5886,9 @@ sub DbLog_reduceLogNbl { $kd++; } } + Log3($name, 4, "DbLog $name: UPDATE $history SET TIMESTAMP=$averageHash{$reading}->{date} 12:00:00, EVENT='rl_av_d', VALUE=$average WHERE (DEVICE=$lastUpdH->[2]) AND (READING=$lastUpdH->[3]) AND (TIMESTAMP=$lastUpdH->[0])"); + $sth_updD->execute(($averageHash{$reading}->{date}." 12:00:00", 'rl_av_d', $average, $lastUpdH->[2], $lastUpdH->[3], $lastUpdH->[0])); $iu++; @@ -5794,15 +5913,18 @@ sub DbLog_reduceLogNbl { Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); } } + $dbh->{RaiseError} = 0; $dbh->{PrintError} = 1; } + %averageHash = (); %hourlyKnown = (); - @averageUpd = (); + @averageUpd = (); @averageUpdD = (); $currentHour = 99; } + $currentDay = $day; } @@ -5826,6 +5948,7 @@ sub DbLog_reduceLogNbl { for (@excludeRegex) { $exclude = 1 if("$row->[1]:$row->[3]" =~ /^$_$/); } + if ($exclude) { $excludeCount++ if($day != 00); } @@ -5834,13 +5957,16 @@ sub DbLog_reduceLogNbl { } } $processingDay = (split(' ',$row->[0]))[0]; + } while( $day != 00 ); my $result = "Rows processed: $rowCount, deleted: $deletedCount" .((defined($a[3]) && $a[3] =~ /average/i)? ", updated: $updateCount" : '') .(($excludeCount)? ", excluded: $excludeCount" : '') .", time: ".sprintf('%.2f',time() - $startTime)."sec"; + Log3($name, 3, "DbLog $name: reduceLogNbl finished. $result"); + $ret = $result; $ret = "reduceLogNbl finished. $result"; } @@ -8757,30 +8883,6 @@ attr SMA_Energymeter DbLogValueFn
- -
-
+ +
+ + +
+