diff --git a/fhem/CHANGED b/fhem/CHANGED index 12b77e474..0fd738a39 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,8 @@ # 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. + - change: 93_DbRep: function "diffValue" added, readingnames changed to + ensure valid reading order, write "-" for reading-value if no + dataset is found in selection timerange - updated: 74_AMAD: New Minor Release 2.4 new AMADCommBridge API - changed: 10_ZWave: alarm Events text changed, comma replaced, Forum #53389 - feature: 93_DbRep: new module added - reporting of database content diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm index a4ce68a39..1578da427 100644 --- a/fhem/FHEM/93_DbRep.pm +++ b/fhem/FHEM/93_DbRep.pm @@ -37,7 +37,14 @@ ########################################################################################################### # Versions History: # -# 3.2 11.07.2016 handling of db-errors is relocated to blockingcall-subs +# 3.3.3 16.07.2016 bugfix of aggregation=week if month start is 01 and month end is 12 AND +# the last week of december is "01" like in 2014 (checked in version 11804) +# 3.3.2 16.07.2016 readings completed with begin of selection range to ensure valid reading order, +# also done if readingNameMap is set +# 3.3.1 15.07.2016 function "diffValue" changed, write "-" if no value +# 3.3 12.07.2016 function "diffValue" added +# 3.2.1 12.07.2016 DbRep_Notify prepared, switched from readingsSingleUpdate to readingsBulkUpdate +# 3.2 11.07.2016 handling of db-errors is relocated to blockingcall-subs (checked in version 11785) # 3.1.1 10.07.2016 state turns to initialized and connected after attr "disabled" is switched from "1" to "0" # 3.1 09.07.2016 new Attr "timeDiffToNow" and change subs according to that # 3.0 04.07.2016 no selection if timestamp isn't set and aggregation isn't set with fetchrows, delEntries @@ -96,6 +103,7 @@ sub DbRep_Initialize($) { my ($hash) = @_; $hash->{DefFn} = "DbRep_Define"; $hash->{UndefFn} = "DbRep_Undef"; + # $hash->{NotifyFn} = "DbRep_Notify"; $hash->{SetFn} = "DbRep_Set"; # $hash->{GetFn} = "DbRep_Get"; $hash->{AttrFn} = "DbRep_Attr"; @@ -162,6 +170,7 @@ sub DbRep_Set { "delEntries:noArg ". "maxValue:noArg ". "fetchrows:noArg ". + "diffValue:noArg ". "countEntries:noArg "; return if(IsDisabled($name)); @@ -196,6 +205,11 @@ sub DbRep_Set { } sqlexec($hash,"del"); + } elsif ($opt eq "diffValue") { + if (!AttrVal($hash->{NAME}, "reading", "")) { + return " The attribute reading for analyze is not set !"; + } + sqlexec($hash,"diff"); } else { @@ -263,6 +277,37 @@ sub DbRep_Attr { return undef; } + +################################################################################### +# DbRep_Notify Eventverarbeitung +################################################################################### + +sub DbRep_Notify { + my ($dbrep, $dev) = @_; + my $myName = $dbrep->{NAME}; # Name des eigenen Devices + my $devName = $dev->{NAME}; # Name des Devices welches Events erzeugt hat + + return if(IsDisabled($myName)); # Return if the module is disabled + + my $max = int(@{$dev->{CHANGED}}); # number of events / changes + + for (my $i = 0; $i < $max; $i++) { + my $s = $dev->{CHANGED}[$i]; + next if(!defined($s)); + my ($evName, $val) = split(" ", $s, 2); # resets $1 + next if($devName !~ m/^$myName$/); + + if ($evName =~ m/done/) { + # Log3 ($myName, 3, "DbRep $myName - Event received - device: $myName Event: $evName"); + # fhem ("trigger WEB JS:location.reload('false')"); + # FW_directNotify("#FHEMWEB:WEB", "location.reload('false')", ""); + # map {FW_directNotify("#FHEMWEB:$_", "location.reload('false')", "")} devspec2array("WEB.*"); + } + + } + +} + ################################################################################### # DbRep_Undef ################################################################################### @@ -294,7 +339,7 @@ sub DbRep_firstconnect { Log3 ($name, 2, "DbRep $name - DB connect failed. Credentials of $hash->{dbloghash}{NAME} are valid and database reachable ?"); readingsSingleUpdate($hash, "state", "disconnected", 1); } else { - Log3 ($name, 3, "DbRep $name - Test-Connection to db $dbconn was successful"); + Log3 ($name, 3, "DbRep $name - Connectiontest to db $dbconn was successful"); my $dbh = $hash->{DBH}; $dbh->disconnect(); } @@ -320,7 +365,7 @@ sub DbRep_Connect { if(!$dbh) { RemoveInternalTimer($hash); - Log3 ($name, 3, "DbRep $name - Test connection to database $dbconn with user $dbuser"); + Log3 ($name, 3, "DbRep $name - Connectiontest to database $dbconn with user $dbuser"); readingsSingleUpdate($hash, 'state', 'disconnected', 1); @@ -481,27 +526,31 @@ $hash->{HELPER}{CV} = \%cv; if ($opt eq "sum") { $hash->{helper}{RUNNING_PID} = BlockingCall("sumval_DoParse", "$name§$device§$reading§$ts", "sumval_ParseDone", $to, "ParseAborted", $hash); - } elsif ($opt eq "count" ) { + } elsif ($opt eq "count") { $hash->{helper}{RUNNING_PID} = BlockingCall("count_DoParse", "$name§$device§$reading§$ts", "count_ParseDone", $to, "ParseAborted", $hash); - } elsif ($opt eq "average" ) { + } elsif ($opt eq "average") { $hash->{helper}{RUNNING_PID} = BlockingCall("averval_DoParse", "$name§$device§$reading§$ts", "averval_ParseDone", $to, "ParseAborted", $hash); - } elsif ($opt eq "fetchrows" ) { + } elsif ($opt eq "fetchrows") { $runtime_string_first = defined($epoch_seconds_begin) ? strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin) : "1970-01-01 01:00:00"; $runtime_string_next = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_end); $hash->{helper}{RUNNING_PID} = BlockingCall("fetchrows_DoParse", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "fetchrows_ParseDone", $to, "ParseAborted", $hash); - } elsif ($opt eq "max" ) { + } elsif ($opt eq "max") { $hash->{helper}{RUNNING_PID} = BlockingCall("maxval_DoParse", "$name§$device§$reading§$ts", "maxval_ParseDone", $to, "ParseAborted", $hash); - } elsif ($opt eq "del" ) { + } elsif ($opt eq "del") { $runtime_string_first = AttrVal($hash->{NAME}, "timestamp_begin", undef) ? strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin) : "1970-01-01 01:00:00"; $runtime_string_next = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_end); $hash->{helper}{RUNNING_PID} = BlockingCall("del_DoParse", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "del_ParseDone", $to, "ParseAborted", $hash); - } + + } elsif ($opt eq "diff") { + $hash->{helper}{RUNNING_PID} = BlockingCall("diffval_DoParse", "$name§$device§$reading§$ts", "diffval_ParseDone", $to, "ParseAborted", $hash); + + } return; } @@ -572,8 +621,14 @@ sub averval_DoParse { Log3 ($name, 4, "DbRep $name -> BlockingCall averval_DoParse finished"); return "$name|''|$device|$reading|''|1"; } else { - Log3 ($name, 5, "DbRep $name - SQL result: $line") if($line); - $arrstr .= $runtime_string."#".$line."|"; + Log3 ($name, 5, "DbRep $name - SQL result: $line") if($line); + if(AttrVal($name, "aggregation", "") eq "hour") { + my @rsf = split(/[" "\|":"]/,$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."_".$rsf[1]."|"; + } else { + my @rsf = split(" ",$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."|"; + } } } @@ -618,24 +673,30 @@ sub averval_ParseDone { no warnings 'uninitialized'; # Readingaufbereitung + readingsBeginUpdate($hash); + my @arr = split("\\|", $arrstr); foreach my $row (@arr) { - my @a = split("#", $row); - my $runtime_string = $a[0]; - my $c = $a[1]; - + my @a = split("#", $row); + my $runtime_string = $a[0]; + my $c = $a[1]; + my $rsf = $a[2]."__"; + if (AttrVal($hash->{NAME}, "readingNameMap", "")) { - $reading_runtime_string = AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; + $reading_runtime_string = $rsf.AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; } else { my $ds = $device."__" if ($device); my $rds = $reading."__" if ($reading); - $reading_runtime_string = $ds.$rds."AVERAGE__".$runtime_string; + $reading_runtime_string = $rsf.$ds.$rds."AVERAGE__".$runtime_string; } - readingsSingleUpdate($hash, $reading_runtime_string, $c?sprintf("%.4f",$c):"-", 1); + readingsBulkUpdate($hash, $reading_runtime_string, $c?sprintf("%.4f",$c):"-"); } - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall averval_ParseDone finished"); @@ -710,7 +771,13 @@ sub count_DoParse { return "$name|''|$device|$reading|''|1"; } else { Log3 ($name, 5, "DbRep $name - SQL result: $line") if($line); - $arrstr .= $runtime_string."#".$line."|"; + if(AttrVal($name, "aggregation", "") eq "hour") { + my @rsf = split(/[" "\|":"]/,$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."_".$rsf[1]."|"; + } else { + my @rsf = split(" ",$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."|"; + } } } @@ -758,24 +825,29 @@ sub count_ParseDone { no warnings 'uninitialized'; # Readingaufbereitung + readingsBeginUpdate($hash); + my @arr = split("\\|", $arrstr); foreach my $row (@arr) { - my @a = split("#", $row); - my $runtime_string = $a[0]; - my $c = $a[1]; + my @a = split("#", $row); + my $runtime_string = $a[0]; + my $c = $a[1]; + my $rsf = $a[2]."__"; if (AttrVal($hash->{NAME}, "readingNameMap", "")) { - $reading_runtime_string = AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; + $reading_runtime_string = $rsf.AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; } else { my $ds = $device."__" if ($device); my $rds = $reading."__" if ($reading); - $reading_runtime_string = $ds.$rds."COUNT__".$runtime_string; + $reading_runtime_string = $rsf.$ds.$rds."COUNT__".$runtime_string; } - readingsSingleUpdate($hash, $reading_runtime_string, $c?$c:"-", 1); + readingsBulkUpdate($hash, $reading_runtime_string, $c?$c:"-"); } - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall count_ParseDone finished"); @@ -853,10 +925,19 @@ sub maxval_DoParse { return "$name|''|$device|$reading|''|1"; } else { my @array= map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]."\n" } @{ $sth->fetchall_arrayref() }; + + if(!@array) { + if(AttrVal($name, "aggregation", "") eq "hour") { + my @rsf = split(/[" "\|":"]/,$runtime_string_first); + @array = ($runtime_string." "."0"." ".$rsf[0]."_".$rsf[1]."\n"); + } else { + my @rsf = split(" ",$runtime_string_first); + @array = ($runtime_string." "."0"." ".$rsf[0]."\n"); + } + } + push(@row_array, @array); - } - - # $sth->finish(); + } } # SQL-Laufzeit ermitteln @@ -916,8 +997,8 @@ sub maxval_ParseDone { my $runtime_string = decode_base64($a[0]); $lastruntimestring = $runtime_string if ($i == 1); my $value = $a[1]; - $a[3] =~ s/:/-/g; # substituieren unsopported characters -> siehe fhem.pl - my $timestamp = $a[2]."_".$a[3]; + $a[3] =~ s/:/-/g if($a[3]); # substituieren unsopported characters -> siehe fhem.pl + my $timestamp = $a[3]?$a[2]."_".$a[3]:$a[2]; # Leerzeichen am Ende $timestamp entfernen $timestamp =~ s/\s+$//g; @@ -942,31 +1023,33 @@ sub maxval_ParseDone { } $i++; } + + # Readingaufbereitung + readingsBeginUpdate($hash); + + # only for this block because of warnings if details of readings are not set + no warnings 'uninitialized'; foreach my $key (sort(keys(%rh))) { Log3 ($name, 5, "DbRep $name - runtimestring Key: $key, value: ".$rh{$key}); my @k = split("\\|",$rh{$key}); + my $rsf = $k[2]."__" if($k[2]); - # Readingaufbereitung - - # only for this block because of warnings if details of readings are not set - no warnings 'uninitialized'; - if (AttrVal($hash->{NAME}, "readingNameMap", "")) { - $reading_runtime_string = AttrVal($hash->{NAME}, "readingNameMap", "")."__".$k[0]; + $reading_runtime_string = $rsf.AttrVal($hash->{NAME}, "readingNameMap", "")."__".$k[0]; } else { - my $rmts = $k[2]."__" if($k[2]); my $ds = $device."__" if ($device); my $rds = $reading."__" if ($reading); - $reading_runtime_string = $rmts.$ds.$rds."MAX__".$k[0]; + $reading_runtime_string = $rsf.$ds.$rds."MAX__".$k[0]; } - - readingsSingleUpdate($hash, $reading_runtime_string, $k[1], 1); + my $rv = $k[1]; + readingsBulkUpdate($hash, $reading_runtime_string, $rv?sprintf("%.4f",$rv):"-"); } - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall maxval_ParseDone finished"); @@ -974,6 +1057,219 @@ sub maxval_ParseDone { return; } +#################################################################################################### +# nichtblockierende DB-Abfrage diffValue +#################################################################################################### + +sub diffval_DoParse { + my ($string) = @_; + my ($name, $device, $reading, $ts) = split("\\§", $string); + my $hash = $defs{$name}; + + my $dbloghash = $hash->{dbloghash}; + my $dbconn = $dbloghash->{dbconn}; + my $dbuser = $dbloghash->{dbuser}; + my $dblogname = $dbloghash->{NAME}; + my $dbpassword = $attr{"sec$dblogname"}{secret}; + + Log3 ($name, 4, "DbRep $name -> Start BlockingCall diffval_DoParse"); + + my $dbh; + eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1 });}; + + if ($@) { + Log3 ($name, 2, "DbRep $name - $@"); + Log3 ($name, 4, "DbRep $name -> BlockingCall diffval_DoParse finished"); + return "$name|''|$device|$reading|''|1"; + } + + # only for this block because of warnings if details of readings are not set + no warnings 'uninitialized'; + + # Timestampstring to Array + my @ts = split("\\|", $ts); + + # SQL-Startzeit + my $st = [gettimeofday]; + + # DB-Abfrage zeilenweise für jeden Array-Eintrag + my @row_array; + foreach my $row (@ts) { + + my @a = split("#", $row); + my $runtime_string = $a[0]; + my $runtime_string_first = $a[1]; + my $runtime_string_next = $a[2]; + + # SQL zusammenstellen für DB-Operation + my $sql = "SELECT VALUE,TIMESTAMP FROM `history` where "; + $sql .= "`DEVICE` = '$device' AND " if($device); + $sql .= "`READING` = '$reading' AND " if($reading); + $sql .= "TIMESTAMP BETWEEN ? AND ? ORDER BY TIMESTAMP ;"; + + # SQL zusammenstellen für Logausgabe + my $sql1 = "SELECT VALUE,TIMESTAMP FROM `history` where "; + $sql1 .= "`DEVICE` = '$device' AND " if($device); + $sql1 .= "`READING` = '$reading' AND " if($reading); + $sql1 .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' ORDER BY TIMESTAMP;"; + + Log3 ($name, 4, "DbRep $name - SQL to execute: $sql1"); + + $runtime_string = encode_base64($runtime_string,""); + my $sth = $dbh->prepare($sql); + + eval {$sth->execute($runtime_string_first, $runtime_string_next);}; + + if ($@) { + Log3 ($name, 2, "DbRep $name - $@"); + $dbh->disconnect; + Log3 ($name, 4, "DbRep $name -> BlockingCall diffval_DoParse finished"); + return "$name|''|$device|$reading|''|1"; + } else { + my @array= map { $runtime_string." ".$_ -> [0]." ".$_ -> [1]."\n" } @{ $sth->fetchall_arrayref() }; + + if(!@array) { + if(AttrVal($name, "aggregation", "") eq "hour") { + my @rsf = split(/[" "\|":"]/,$runtime_string_first); + @array = ($runtime_string." "."0"." ".$rsf[0]."_".$rsf[1]."\n"); + } else { + my @rsf = split(" ",$runtime_string_first); + @array = ($runtime_string." "."0"." ".$rsf[0]."\n"); + } + } + push(@row_array, @array); + } + } + + # SQL-Laufzeit ermitteln + my $rt = tv_interval($st); + + $dbh->disconnect; + + my $rowlist = join('|', @row_array); + Log3 ($name, 5, "DbRep $name -> row_array: @row_array"); + + # Daten müssen als Einzeiler zurückgegeben werden + $rowlist = encode_base64($rowlist,""); + + Log3 ($name, 4, "DbRep $name -> BlockingCall diffval_DoParse finished"); + + return "$name|$rowlist|$device|$reading|$rt|0"; +} + +#################################################################################################### +# Auswertungsroutine der nichtblockierenden DB-Abfrage diffValue +#################################################################################################### + +sub diffval_ParseDone { + my ($string) = @_; + my @a = split("\\|",$string); + my $hash = $defs{$a[0]}; + my $name = $hash->{NAME}; + + my $rowlist = decode_base64($a[1]); + my $device = $a[2]; + my $reading = $a[3]; + my $rt = $a[4]; + my $dberr = $a[5]; + my $reading_runtime_string; + + Log3 ($name, 4, "DbRep $name -> Start BlockingCall diffval_ParseDone"); + + if ($dberr) { + readingsSingleUpdate($hash, "state", "error", 1); + delete($hash->{helper}{RUNNING_PID}); + Log3 ($name, 4, "DbRep $name -> BlockingCall diffval_ParseDone finished"); + return; + } + + my @row_array = split("\\|", $rowlist); + + Log3 ($name, 5, "DbRep $name - row_array decoded: @row_array"); + + + my %rh = (); + my $lastruntimestring; + my $i = 1; + my $fe; # Startelement Value + my $le; # letztes Element Value + my $max = ($#row_array)+1; # Anzahl aller Listenelemente + + foreach my $row (@row_array) { + my @a = split("[ \t][ \t]*", $row); + my $runtime_string = decode_base64($a[0]); + $lastruntimestring = $runtime_string if ($i == 1); + my $value = $a[1]; + $a[3] =~ s/:/-/g if($a[3]); # substituieren unsopported characters -> siehe fhem.pl + my $timestamp = $a[3]?$a[2]."_".$a[3]:$a[2]; + + # Leerzeichen am Ende $timestamp entfernen + $timestamp =~ s/\s+$//g; + + Log3 ($name, 5, "DbRep $name - Runtimestring: $runtime_string, DEVICE: $device, READING: $reading, TIMESTAMP: $timestamp, VALUE: $value"); + + if ($runtime_string eq $lastruntimestring) { + if ($i == 1) { + $fe = $value; + $le = $value; + } + + if ($value >= $le) { + $le = $value; + my $diff = $le - $fe; + + $rh{$runtime_string} = $runtime_string."|".$diff."|".$timestamp; + } + } else { + # neuer Zeitabschnitt beginnt, ersten Value-Wert erfassen + $lastruntimestring = $runtime_string; + $i = 1; + $fe = $value; + $le = $value; + + if ($value >= $le) { + $le = $value; + my $diff = $le - $fe; + + $rh{$runtime_string} = $runtime_string."|".$diff."|".$timestamp; + } + } + $i++; + } + + # Readingaufbereitung + readingsBeginUpdate($hash); + + # only for this block because of warnings if details of readings are not set + no warnings 'uninitialized'; + + foreach my $key (sort(keys(%rh))) { + Log3 ($name, 4, "DbRep $name - runtimestring Key: $key, value: ".$rh{$key}); + my @k = split("\\|",$rh{$key}); + my $rsf = $k[2]."__"; + + if (AttrVal($hash->{NAME}, "readingNameMap", "")) { + $reading_runtime_string = $rsf.AttrVal($hash->{NAME}, "readingNameMap", "")."__".$k[0]; + } else { + my $ds = $device."__" if ($device); + my $rds = $reading."__" if ($reading); + $reading_runtime_string = $rsf.$ds.$rds."DIFF__".$k[0]; + } + my $rv = $k[1]; + readingsBulkUpdate($hash, $reading_runtime_string, $rv?sprintf("%.4f",$rv):"-"); + + } + + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); + + delete($hash->{helper}{RUNNING_PID}); + Log3 ($name, 4, "DbRep $name -> BlockingCall diffval_ParseDone finished"); + +return; +} + #################################################################################################### # nichtblockierende DB-Abfrage sumValue #################################################################################################### @@ -1040,7 +1336,13 @@ sub sumval_DoParse { return "$name|''|$device|$reading|''|1"; } else { Log3($name, 5, "DbRep $name - SQL result: $line") if($line); - $arrstr .= $runtime_string."#".$line."|"; + if(AttrVal($name, "aggregation", "") eq "hour") { + my @rsf = split(/[" "\|":"]/,$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."_".$rsf[1]."|"; + } else { + my @rsf = split(" ",$runtime_string_first); + $arrstr .= $runtime_string."#".$line."#".$rsf[0]."|"; + } } } @@ -1086,25 +1388,29 @@ sub sumval_ParseDone { no warnings 'uninitialized'; # Readingaufbereitung + readingsBeginUpdate($hash); + my @arr = split("\\|", $arrstr); foreach my $row (@arr) { - my @a = split("#", $row); - my $runtime_string = $a[0]; - my $c = $a[1]; - + my @a = split("#", $row); + my $runtime_string = $a[0]; + my $c = $a[1]; + my $rsf = $a[2]."__"; + if (AttrVal($hash->{NAME}, "readingNameMap", "")) { - $reading_runtime_string = AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; + $reading_runtime_string = $rsf.AttrVal($hash->{NAME}, "readingNameMap", "")."__".$runtime_string; } else { my $ds = $device."__" if ($device); my $rds = $reading."__" if ($reading); - $reading_runtime_string = $ds.$rds."SUM__".$runtime_string; + $reading_runtime_string = $rsf.$ds.$rds."SUM__".$runtime_string; } - readingsSingleUpdate($hash, $reading_runtime_string, $c?sprintf("%.4f",$c):"-", 1); + readingsBulkUpdate($hash, $reading_runtime_string, $c?sprintf("%.4f",$c):"-"); } - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall sumval_ParseDone finished"); @@ -1210,15 +1516,17 @@ sub del_ParseDone { my $ds = $device." -- " if ($device); my $rds = $reading." -- " if ($reading); my $reading_runtime_string = $ds.$rds." -- DELETED ROWS -- "; - - readingsSingleUpdate($hash, $reading_runtime_string, $rows, 1); + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, $reading_runtime_string, $rows); $rows = $ds.$rds.$rows; Log3 ($name, 3, "DbRep $name - Entries of database $hash->{dbloghash}{NAME} deleted: $rows"); - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall del_ParseDone finished"); @@ -1327,6 +1635,9 @@ sub fetchrows_ParseDone { Log3 ($name, 5, "DbRep $name - row_array decoded: @row_array"); + # Readingaufbereitung + readingsBeginUpdate($hash); + foreach my $row (@row_array) { my @a = split("[ \t][ \t]*", $row, 5); my $dev = $a[0]; @@ -1335,18 +1646,18 @@ sub fetchrows_ParseDone { my $ts = $a[2]."_".$a[3]; my $val = $a[4]; - # Readingaufbereitung if ($reading && AttrVal($hash->{NAME}, "readingNameMap", "")) { $reading_runtime_string = $ts."__".AttrVal($hash->{NAME}, "readingNameMap", "") ; } else { $reading_runtime_string = $ts."__".$dev."__".$rea; } - readingsSingleUpdate($hash, $reading_runtime_string, $val, 1); + readingsBulkUpdate($hash, $reading_runtime_string, $val); } - readingsSingleUpdate($hash, "state", "done", 1); - readingsSingleUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt), 1) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); delete($hash->{helper}{RUNNING_PID}); Log3 ($name, 4, "DbRep $name -> BlockingCall fetchrows_ParseDone finished"); @@ -1452,8 +1763,10 @@ sub collaggstr { $runtime_orig = $runtime; - my $w = strftime "%V", localtime($runtime); # Wochennummer des aktuellen Startdatum/Zeit - $runtime_string = "week_".$w; # für Readingname + my $w = strftime "%V", localtime($runtime); # Wochennummer des aktuellen Startdatum/Zeit + $runtime_string = "week_".$w; # für Readingname + my $ms = strftime "%m", localtime($runtime); # Startmonat (01-12) + my $me = strftime "%m", localtime($epoch_seconds_end); # Endemonat (01-12) if ($i==1) { # nur im ersten Schleifendurchlauf @@ -1466,7 +1779,7 @@ sub collaggstr { $runtime_orig = $runtime-$aggsec; # die Woche Beginn ist gleich der Woche von Ende Auswertung - if((strftime "%V", localtime($epoch_seconds_end)) eq $w) { + if((strftime "%V", localtime($epoch_seconds_end)) eq ($w) && ($ms+$me != 13)) { $runtime_string_next = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_end); $ll=1; } else { @@ -1594,12 +1907,13 @@ return ($runtime,$runtime_string,$runtime_string_first,$runtime_string_next,$ll)