93_DbRep: contrib 8.34.0

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@21447 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2020-03-18 20:39:15 +00:00
parent bbeb9a65b3
commit 1f7d94b1eb

View File

@ -1,5 +1,5 @@
########################################################################################################## ##########################################################################################################
# $Id: 93_DbRep.pm 21169 2020-02-10 21:15:23Z DS_Starter $ # $Id: 93_DbRep.pm 21429 2020-03-15 15:23:50Z DS_Starter $
########################################################################################################## ##########################################################################################################
# 93_DbRep.pm # 93_DbRep.pm
# #
@ -58,6 +58,10 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
our %DbRep_vNotesIntern = ( our %DbRep_vNotesIntern = (
"8.34.0" => "18.03.2020 option writeToDBSingle for functions averageValue, sumValue ",
"8.33.0" => "18.03.2020 option older than days and newer than days for reduceLog function ",
"8.32.4" => "15.03.2020 fix rights check for index operation ",
"8.32.3" => "10.03.2020 better logfile messages in some cases of index operation ",
"8.32.2" => "01.03.2020 fix PERL WARNING: Argument \"\" isn't numeric in sprintf at ./FHEM/93_DbRep.pm line 10708 again ", "8.32.2" => "01.03.2020 fix PERL WARNING: Argument \"\" isn't numeric in sprintf at ./FHEM/93_DbRep.pm line 10708 again ",
"8.32.1" => "08.02.2020 fix PERL WARNING: Argument \"\" isn't numeric in sprintf at ./FHEM/93_DbRep.pm line 10708 ", "8.32.1" => "08.02.2020 fix PERL WARNING: Argument \"\" isn't numeric in sprintf at ./FHEM/93_DbRep.pm line 10708 ",
"8.32.0" => "29.01.2020 new option \"deleteOther\" for minValue ", "8.32.0" => "29.01.2020 new option \"deleteOther\" for minValue ",
@ -544,8 +548,8 @@ sub DbRep_Set($@) {
my $setlist = "Unknown argument $opt, choose one of ". my $setlist = "Unknown argument $opt, choose one of ".
"eraseReadings:noArg ". "eraseReadings:noArg ".
(($hash->{ROLE} ne "Agent")?"sumValue:display,writeToDB ":""). (($hash->{ROLE} ne "Agent")?"sumValue:display,writeToDB,writeToDBSingle ":"").
(($hash->{ROLE} ne "Agent")?"averageValue:display,writeToDB ":""). (($hash->{ROLE} ne "Agent")?"averageValue:display,writeToDB,writeToDBSingle ":"").
(($hash->{ROLE} ne "Agent")?"changeValue ":""). (($hash->{ROLE} ne "Agent")?"changeValue ":"").
(($hash->{ROLE} ne "Agent")?"delDoublets:adviceDelete,delete ":""). (($hash->{ROLE} ne "Agent")?"delDoublets:adviceDelete,delete ":"").
(($hash->{ROLE} ne "Agent")?"delEntries:noArg ":""). (($hash->{ROLE} ne "Agent")?"delEntries:noArg ":"").
@ -1804,7 +1808,7 @@ sub DbRep_dbConnect($$) {
$dbpassword = $admpassword; $dbpassword = $admpassword;
} else { } else {
$err = "Can't use admin credentials for database access, see logfile !"; $err = "Can't use admin credentials for database access, see logfile !";
Log3 ($name, 2, "DbRep $name - ERROR - admin credentials are needed for database access, but can't use it"); Log3 ($name, 2, "DbRep $name - ERROR - admin credentials are needed for database operation, but are not set or can't read it");
return $err; return $err;
} }
} }
@ -2057,6 +2061,14 @@ sub DbRep_Main($$;$) {
} }
if ($opt =~ /reduceLog/) { if ($opt =~ /reduceLog/) {
my ($yyyy1, $mm1, $dd1, $hh1, $min1, $sec1) = ($runtime_string_first =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($runtime_string_next =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
my $nthants = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900);
my $othants = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900);
if($nthants >= $othants) {
ReadingsSingleUpdateValue ($hash, "state", "Error - Wrong time limits. The <nn> (days newer than) option must be greater than the <no> (older than) one !", 1);
return;
}
$hash->{HELPER}{RUNNING_REDUCELOG} = BlockingCall("DbRep_reduceLog", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "DbRep_reduceLogDone", $to, "DbRep_reduceLogAborted", $hash); $hash->{HELPER}{RUNNING_REDUCELOG} = BlockingCall("DbRep_reduceLog", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "DbRep_reduceLogDone", $to, "DbRep_reduceLogAborted", $hash);
ReadingsSingleUpdateValue ($hash, "state", "reduceLog database is running - be patient and see Logfile !", 1); ReadingsSingleUpdateValue ($hash, "state", "reduceLog database is running - be patient and see Logfile !", 1);
$hash->{HELPER}{RUNNING_REDUCELOG}{loglevel} = 5 if($hash->{HELPER}{RUNNING_REDUCELOG}); # Forum #77057 $hash->{HELPER}{RUNNING_REDUCELOG}{loglevel} = 5 if($hash->{HELPER}{RUNNING_REDUCELOG}); # Forum #77057
@ -6601,8 +6613,8 @@ sub DbRep_Index($) {
my $bst = [gettimeofday]; my $bst = [gettimeofday];
# Rechte Check MYSQL # Rechte Check MYSQL
if($cmdidx ne "list_all") { if($cmdidx ne "list_all" && $dbmodel =~ /MYSQL/) {
if($dbmodel =~ /MYSQL/ && $grants && $grants ne "ALL PRIVILEGES") { if($grants && $grants ne "ALL PRIVILEGES") {
# Rechte INDEX und ALTER benötigt # Rechte INDEX und ALTER benötigt
my $i = index($grants,"INDEX"); my $i = index($grants,"INDEX");
my $a = index($grants,"ALTER"); my $a = index($grants,"ALTER");
@ -6614,6 +6626,9 @@ sub DbRep_Index($) {
} }
} }
Log3 ($name, 2, "DbRep $name - user \"$dbuser\" doesn't have rights \"INDEX\" and \"ALTER\" as needed - try use adminCredentials automatically !")
if($p);
($err,$dbh) = DbRep_dbConnect($name,$p); ($err,$dbh) = DbRep_dbConnect($name,$p);
if ($err) { if ($err) {
$err = encode_base64($err,""); $err = encode_base64($err,"");
@ -8542,13 +8557,24 @@ sub DbRep_reduceLog($) {
my $dbmodel = $dbloghash->{MODEL}; my $dbmodel = $dbloghash->{MODEL};
my $dbpassword = $attr{"sec$dblogname"}{secret}; my $dbpassword = $attr{"sec$dblogname"}{secret};
my @a = @{$hash->{HELPER}{REDUCELOG}}; my @a = @{$hash->{HELPER}{REDUCELOG}};
my $rlpar = join(" ", @a);
my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0; my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0;
delete $hash->{HELPER}{REDUCELOG};
my ($ret,$row,$filter,$exclude,$c,$day,$hour,$lastHour,$updDate,$updHour,$average,$processingDay,$lastUpdH); my ($ret,$row,$filter,$exclude,$c,$day,$hour,$lastHour,$updDate,$updHour,$average,$processingDay,$lastUpdH);
my (%hourlyKnown,%averageHash,@excludeRegex,@dayRows,@averageUpd,@averageUpdD); my (%hourlyKnown,%averageHash,@excludeRegex,@dayRows,@averageUpd,@averageUpdD);
my ($startTime,$currentHour,$currentDay,$deletedCount,$updateCount,$sum,$rowCount,$excludeCount) = (time(),99,0,0,0,0,0,0); my ($startTime,$currentHour,$currentDay,$deletedCount,$updateCount,$sum,$rowCount,$excludeCount) = (time(),99,0,0,0,0,0,0);
my ($dbh,$err,$brt); my ($dbh,$err,$brt);
BlockingInformParent("DbRep_delHashValFromBlocking", [$name, "HELPER","REDUCELOG"], 1);
# ausfiltern von optionalen Zeitangaben, z.B. 700:750 -> Rest zur Einhaltung des ursprünglichen Formats nach @a schreiben
my @b;
foreach (@a) {
next if($_ =~ /\b(\d+(:\d+)?)\b/);
push @b, $_;
}
@a = @b;
Log3 ($name, 5, "DbRep $name -> Start DbLog_reduceLog"); Log3 ($name, 5, "DbRep $name -> Start DbLog_reduceLog");
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });}; eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });};
@ -9782,6 +9808,16 @@ sub DbRep_normRelTime($) {
my $fdopt = 0; # FullDay Option my $fdopt = 0; # FullDay Option
my ($y,$d,$h,$m,$s,$aval); my ($y,$d,$h,$m,$s,$aval);
# evtl. Relativzeiten bei "reduceLog" berücksichtigen
my @a = @{$hash->{HELPER}{REDUCELOG}} if($hash->{HELPER}{REDUCELOG});
foreach (@a) {
if($_ =~ /\b(\d+(:\d+)?)\b/) {
my ($od,$nd) = split(":",$1); # $od - Tage älter als , $nd - Tage neuer als
$toth = "d:$od" if($od);
$tdtn = "d:$nd" if($nd);
}
}
if($tdtn && $tdtn =~ /^\s*[ydhms]:(([\d]+.[\d]+)|[\d]+)\s*/) { if($tdtn && $tdtn =~ /^\s*[ydhms]:(([\d]+.[\d]+)|[\d]+)\s*/) {
$aval = $tdtn; $aval = $tdtn;
if($tdtn =~ /.*y:(([\d]+.[\d]+)|[\d]+).*/) { if($tdtn =~ /.*y:(([\d]+.[\d]+)|[\d]+).*/) {
@ -10707,7 +10743,7 @@ sub DbRep_OutputWriteToDB($$$$$) {
foreach my $row (@arr) { foreach my $row (@arr) {
my @a = split("#", $row); my @a = split("#", $row);
my $runtime_string = $a[0]; # Aggregations-Alias (nicht benötigt) my $runtime_string = $a[0]; # Aggregations-Alias (nicht benötigt)
$value = defined($a[1])?(looks_like_number($a[1])?sprintf("%.4f",$a[1]):$a[1]):undef; $value = defined($a[1])?(looks_like_number($a[1])?sprintf("%.4f",$a[1]):$a[1]):undef; # Version 8.32.2
$rsf = $a[2]; # Runtime String first - Datum / Zeit für DB-Speicherung $rsf = $a[2]; # Runtime String first - Datum / Zeit für DB-Speicherung
($date,$time) = split("_",$rsf); ($date,$time) = split("_",$rsf);
$time =~ s/-/:/g if($time); $time =~ s/-/:/g if($time);
@ -10738,7 +10774,7 @@ sub DbRep_OutputWriteToDB($$$$$) {
# Daten auf maximale Länge beschneiden (DbLog-Funktion !) # Daten auf maximale Länge beschneiden (DbLog-Funktion !)
($device,$type,$event,$reading,$value,$unit) = DbLog_cutCol($dbloghash,$device,$type,$event,$reading,$value,$unit); ($device,$type,$event,$reading,$value,$unit) = DbLog_cutCol($dbloghash,$device,$type,$event,$reading,$value,$unit);
if($i == 0) { if($i == 0) {
push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit"); push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/);
push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"); push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit");
} else { } else {
if ($aggr =~ /no|day|week|month|year/) { if ($aggr =~ /no|day|week|month|year/) {
@ -10750,7 +10786,7 @@ sub DbRep_OutputWriteToDB($$$$$) {
$t1 = fhemTimeLocal(01, 00, $hour, $mday, $mon-1, $year-1900); $t1 = fhemTimeLocal(01, 00, $hour, $mday, $mon-1, $year-1900);
($date,$time) = split(" ",FmtDateTime($t1)); ($date,$time) = split(" ",FmtDateTime($t1));
} }
push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit"); push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/);
push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit"); push(@row_array, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit");
} }
} }
@ -11186,6 +11222,22 @@ sub DbRep_numval ($){
return $val; return $val;
} }
####################################################################################################
# löscht einen Wert vom $hash des Hauptprozesses aus einem BlockingCall heraus
####################################################################################################
sub DbRep_delHashValFromBlocking($$;$) {
my ($name,$v1,$v2) = @_;
my $hash = $defs{$name};
if($v2) {
delete $hash->{$v1}{$v2};
} elsif ($v1) {
delete $hash->{$v1};
}
return 1;
}
################################################################ ################################################################
# sortiert eine Liste von Versionsnummern x.x.x # sortiert eine Liste von Versionsnummern x.x.x
# Schwartzian Transform and the GRT transform # Schwartzian Transform and the GRT transform
@ -11225,12 +11277,12 @@ sub DbRep_setVersionInfo($) {
if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) { if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) {
# META-Daten sind vorhanden # META-Daten sind vorhanden
$modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{SMAPortal}{META}} $modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{SMAPortal}{META}}
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 21169 2020-02-10 21:15:23Z DS_Starter $ im Kopf komplett! vorhanden ) if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 21429 2020-03-15 15:23:50Z DS_Starter $ im Kopf komplett! vorhanden )
$modules{$type}{META}{x_version} =~ s/1.1.1/$v/g; $modules{$type}{META}{x_version} =~ s/1.1.1/$v/g;
} else { } else {
$modules{$type}{META}{x_version} = $v; $modules{$type}{META}{x_version} = $v;
} }
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 21169 2020-02-10 21:15:23Z DS_Starter $ im Kopf komplett! vorhanden ) return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 21429 2020-03-15 15:23:50Z DS_Starter $ im Kopf komplett! vorhanden )
if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) { if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) {
# es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen # es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen
# mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden # mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden
@ -11735,21 +11787,27 @@ return;
</li> <br> </li> <br>
<li><b> averageValue [display | writeToDB]</b> <li><b> averageValue [display | writeToDB | writeToDBSingle]</b>
- calculates the average value of database column "VALUE" between period given by - calculates an average value of the database field "VALUE" in the time limits
timestamp-<a href="#DbRepattr">attributes</a> which are set. of the possible time.*-attributes. <br><br>
The reading to evaluate must be specified by attribute "reading". <br>
By attribute "averageCalcForm" the calculation variant for average determination will be configured.
Is no or the option "display" specified, the results are only displayed. Using The reading to be evaluated must be specified in the attribute <a href="#reading">reading</a>
option "writeToDB" the calculated results are stored in the database with a new reading must be specified.
name. <br> With the attribute <a href="#averageCalcForm">averageCalcForm</a> the calculation variant
The new readingname is built of a prefix and the original reading name, is used for Averaging defined. <br><br>
in which the original reading name can be replaced by the value of attribute "readingNameMap".
The prefix is made up of the creation function and the aggregation. <br> If none or the option <b>display</b> is specified, the results are only displayed. With
The timestamp of the new stored readings is deviated from aggregation period, the options <b>writeToDB</b> or <b>writeToDBSingle</b> the calculation results are written
unless no unique point of time of the result can be determined. with a new reading name into the database. <br>
The field "EVENT" will be filled with "calculated".<br><br> <b>writeToDB</b> writes one value each at the beginning and end of an evaluation period.
<b>writeToDBSingle</b> writes only one value at the end of an evaluation period. <br><br>
The new reading name is formed from a prefix and the original reading name,
where the original reading name can be replaced by the attribute "readingNameMap".
The prefix consists of the educational function and the aggregation. <br>
The timestamp of the new readings in the database is determined by the set aggregation period
if no clear time of the result can be determined.
The field "EVENT" is filled with "calculated". <br><br>
<ul> <ul>
<b>Example of building a new reading name from the original reading "totalpac":</b> <br> <b>Example of building a new reading name from the original reading "totalpac":</b> <br>
@ -12659,24 +12717,23 @@ return;
is operating in asynchronous mode to avoid FHEMWEB from blocking. <br><br> is operating in asynchronous mode to avoid FHEMWEB from blocking. <br><br>
</li> <br> </li> <br>
<li><b> reduceLog [average[=day]] </b> <br> <li><b> reduceLog [&lt;no&gt;[:&lt;nn&gt;]] [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading] </b> <br>
Reduces historical records within the limits given by the "time.*"-attributes to one record Reduces historical data sets. <br><br>
(the 1st) each hour per device & reading.
At least one of the "time.*"-attributes must be set (pls. see table below). <b>Method without option specification</b> <br><br>
Each of missing time limit will be calculated by the module itself in this case.
If no options are specified, the data will be stored within the time specified by the <b>time.*</b> attributes.
Time limits reduced to one entry (the first) per hour per Device & Reading.
At least one of the <b>time.*</b> attributes must be set (see table below).
In this case, the missing time limit is calculated by the module.
<br><br> <br><br>
With the optional argument 'average' not only the records will be reduced, but all numerical With the attributes <b>device</b> and <b>reading</b> the data records to be considered can be included
values of an hour will be reduced to a single average. or be excluded. Both restrictions reduce the selected data and reduce the
With option 'average=day' all numerical values of a day are reduced to a single average resource requirements.
(implies 'average'). <br><br> The read "reduceLogState" contains the execution result of the last reduceLog command. <br><br>
By setting attributes "device" and/or "reading" the records to be considered could be included Taking the above into account, the following attributes are relevant for this function: <br><br>
respectively excluded. Both containments delimit the selected data from database and may
reduce the system RAM load.
The reading "reduceLogState" contains the result of the last executed reducelog run. <br><br>
The relevant attributes for this function are: <br><br>
<ul> <ul>
<table> <table>
@ -12694,53 +12751,56 @@ return;
</ul> </ul>
<br> <br>
For compatibility reason the reducelog command can optionally be completed with supplements "EXCLUDE"
respectively "INCLUDE" to exclude and/or include device/reading combinations from reducelog: <br><br>
<ul>
"reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br>
</ul>
This declaration is evaluated as Regex and overwrites the settings made by attributes "device" and "reading",
which won't be considered in this case. <br><br>
<ul>
<b>Examples: </b><br><br> <b>Examples: </b><br><br>
<ul>
attr &lt;name&gt; timeOlderThan = d:200 <br> attr &lt;name&gt; timeOlderThan = d:200 <br>
set &lt;name&gt; reduceLog <br> set &lt;name&gt; reduceLog <br>
# Records older than 200 days are reduced to the first entry per hour of each device and reading. # Records older than 200 days are written to the first entry per hour per Device & Reading. <br>
<br>
<br> <br>
attr &lt;name&gt; timeDiffToNow = d:200 <br> attr &lt;name&gt; timeDiffToNow = d:200 <br>
set &lt;name&gt; reduceLog average=day <br> set &lt;name&gt; reduceLog average=day <br>
# Records newer than 200 days are reduced to a single average a day of each device and reading. # Records newer than 200 days are limited to one entry per day per Device & Reading. <br>
<br>
<br> <br>
attr &lt;name&gt; timeDiffToNow = d:30 <br> attr &lt;name&gt; timeDiffToNow = d:30 <br>
attr &lt;name&gt; device = TYPE=SONOSPLAYER EXCLUDE=Sonos_Kueche <br> attr &lt;name&gt; device = TYPE=SONOSPLAYER EXCLUDE=Sonos_Kueche <br>
attr &lt;name&gt; reading = room% EXCLUDE=roomNameAlias <br> attr &lt;name&gt; reading = room% EXCLUDE=roomNameAlias <br>
set &lt;name&gt; reduceLog <br> set &lt;name&gt; reduceLog <br>
# Records newer than 30 days which are contain devices from type SONOSPLAYER # Records newer than 30 days that are devices of type SONOSPLAYER
(except device "Sonos_Kueche"), the readings beginning with "room" (except "roomNameAlias"), (except Device "Sonos_Kitchen") and the readings start with "room" (except "roomNameAlias")
are reduced to the first entry per hour of each device and reading. <br> are reduced to the first entry per hour per Device & Reading. <br>
<br> <br>
attr &lt;name&gt; timeDiffToNow = d:10 <br> attr &lt;name&gt; timeDiffToNow = d:10 <br>
attr &lt;name&gt; timeOlderThan = d:5 <br> attr &lt;name&gt; timeOlderThan = d:5 <br>
attr &lt;name&gt; device = Luftdaten_remote <br> attr &lt;name&gt; device = Luftdaten_remote <br>
set &lt;name&gt; reduceLog average <br> set &lt;name&gt; reduceLog average <br>
# Records older than 5 and newer than 10 days and contain DEVICE "Luftdaten_remote" are # Records older than 5 and newer than 10 days and containing DEVICE "Luftdaten_remote
revised. Numerical values are reduced to the first entry per hour of each device and reading are adjusted. Numerical values of an hour are reduced to an average value <br>
<br>
<br> <br>
</ul> </ul>
<br>
<b>Method with option specification</b> <br><br>
Records older than <b>&lt;no&gt;</b> days and (optionally) newer than
<b>&lt;nn&gt;</b> days are considered.
Specifying <b>average</b> not only cleans up the database, but also
all numerical values of an hour are reduced to a single mean value.
With the option <b>average=day</b> all numerical values of a day are reduced to a single
Average value reduced (implies 'average'). <br><br>
The additions "EXCLUDE" and "INCLUDE" can be added to exclude device/reading combinations of reduceLog
or to include them. This specification is evaluated as regex and overwrites the setting of the attributes "device".
and "reading", which are not considered in this case. <br><br>
<b>Note:</b> <br> <b>Note:</b> <br>
Even though the function itself is non-blocking, you have to set the attached DbLog device into Although the function itself is designed non-blocking, the assigned DbLog device should
the asynchronous mode (attr asyncMode = 1) to avoid a blocking situation of FHEM !. <br> operated in asynchronous mode to avoid blocking of FHEMWEB (table lock). <br>
It is strongly recommended to check if the default INDEX 'Search_Idx' exists on the table It is also strongly recommended to use the standard INDEX 'Search_Idx' in the table 'history'.
'history'! <br><br> to put on ! <br>
The processing of this command may take an extremely long time (without INDEX). <br><br>
</li> <br> </li> <br>
<li><b> repairSQLite </b> - repairs a corrupted SQLite database. <br> <li><b> repairSQLite </b> - repairs a corrupted SQLite database. <br>
@ -12942,22 +13002,26 @@ return;
</li><br><br> </li><br><br>
<li><b> sumValue [display | writeToDB]</b> <li><b> sumValue [display | writeToDB | writeToDBSingle] </b>
- calculates the summary of database column "VALUE" between period given by - Calculates the total values of the database field "VALUE" in the time limits
<a href="#DbRepattr">attributes</a> "timestamp_begin", "timestamp_end" or of the possible time.*-attributes. <br><br>
"timeDiffToNow / timeOlderThan". The reading to evaluate must be defined using attribute
"reading". Using this function is mostly reasonable if value-differences of readings
are written to the database. <br>
Is no or the option "display" specified, the results are only displayed. Using The reading to be evaluated must be specified in the attribute <a href="#reading">reading</a>.
option "writeToDB" the calculation results are stored in the database with a new reading This function is useful if continuous value differences of a reading are written
name. <br> into the database. <br><br>
The new readingname is built of a prefix and the original reading name,
in which the original reading name can be replaced by the value of attribute "readingNameMap". If none or the option <b>display</b> is specified, the results are only displayed. With
The prefix is made up of the creation function and the aggregation. <br> the options <b>writeToDB</b> or <b>writeToDBSingle</b> the calculation results are written
The timestamp of the new stored readings is deviated from aggregation period, with a new reading name into the database. <br>
unless no unique point of time of the result can be determined. <b>writeToDB</b> writes one value each at the beginning and end of an evaluation period.
The field "EVENT" will be filled with "calculated".<br><br> <b>writeToDBSingle</b> writes only one value at the end of an evaluation period. <br><br>
The new reading name is formed from a prefix and the original reading name,
where the original reading name can be replaced by the attribute "readingNameMap".
The prefix consists of the educational function and the aggregation. <br>
The timestamp of the new reading in the database is determined by the set aggregation period
if no clear time of the result can be determined.
The field "EVENT" is filled with "calculated". <br><br>
<ul> <ul>
<b>Example of building a new reading name from the original reading "totalpac":</b> <br> <b>Example of building a new reading name from the original reading "totalpac":</b> <br>
@ -14229,15 +14293,21 @@ sub bdump {
</li> <br> </li> <br>
<li><b> averageValue [display | writeToDB]</b> <li><b> averageValue [display | writeToDB | writeToDBSingle]</b>
- berechnet einen Durchschnittswert des Datenbankfelds "VALUE" in den - berechnet einen Durchschnittswert des Datenbankfelds "VALUE" in den Zeitgrenzen
gegebenen Zeitgrenzen ( siehe <a href="#DbRepattr">Attribute</a>). der möglichen time.*-Attribute. <br><br>
Es muss das auszuwertende Reading über das <a href="#DbRepattr">Attribut</a> "reading"
angegeben sein. <br> Es muss das auszuwertende Reading im Attribut <a href="#reading">reading</a>
Mit dem Attribut "averageCalcForm" wird die Berechnungsvariante zur Mittelwertermittlung definiert. angegeben sein.
Ist keine oder die Option "display" angegeben, werden die Ergebnisse nur angezeigt. Mit Mit dem Attribut <a href="#averageCalcForm">averageCalcForm</a> wird die Berechnungsvariante zur
der Option "writeToDB" werden die Berechnungsergebnisse mit einem neuen Readingnamen Mittelwertermittlung definiert. <br><br>
in der Datenbank gespeichert. <br>
Ist keine oder die Option <b>display</b> angegeben, werden die Ergebnisse nur angezeigt. Mit
den Optionen <b>writeToDB</b> bzw. <b>writeToDBSingle</b> werden die Berechnungsergebnisse
mit einem neuen Readingnamen in der Datenbank gespeichert. <br>
<b>writeToDB</b> schreibt jeweils einen Wert am Anfang und am Ende einer Auswertungsperiode.
<b>writeToDBSingle</b> schreibt nur einen Wert am Ende einer Auswertungsperiode. <br><br>
Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet, Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet,
wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann. wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann.
Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen. <br> Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen. <br>
@ -15176,24 +15246,23 @@ sub bdump {
im asynchronen Modus betrieben werden um ein Blockieren von FHEMWEB zu vermeiden (Tabellen-Lock). <br><br> im asynchronen Modus betrieben werden um ein Blockieren von FHEMWEB zu vermeiden (Tabellen-Lock). <br><br>
</li> <br> </li> <br>
<li><b> reduceLog [average[=day]] </b> <br> <li><b> reduceLog [&lt;no&gt;[:&lt;nn&gt;]] [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading] </b> <br>
Reduziert historische Datensätze innerhalb der durch die "time.*"-Attribute bestimmten Reduziert historische Datensätze. <br><br>
Zeitgrenzen auf einen Eintrag (den ersten) pro Stunde je Device & Reading.
Es muss mindestens eines der "time.*"-Attribute gesetzt sein (siehe Tabelle unten). <b>Arbeitsweise ohne Optionsangabe</b> <br><br>
Sind keine Optionen angegeben, werden die Daten innerhalb der durch die <b>time.*</b>-Attribute bestimmten
Zeitgrenzen auf einen Eintrag (den ersten) pro Stunde je Device & Reading reduziert.
Es muss mindestens eines der <b>time.*</b>-Attribute gesetzt sein (siehe Tabelle unten).
Die jeweils fehlende Zeitabgrenzung wird in diesem Fall durch das Modul errechnet. Die jeweils fehlende Zeitabgrenzung wird in diesem Fall durch das Modul errechnet.
<br><br> <br><br>
Durch die optionale Angabe von 'average' wird nicht nur die Datenbank bereinigt, sondern Mit den Attributen <b>device</b> und <b>reading</b> können die zu berücksichtigenden Datensätze eingeschlossen
alle numerischen Werte einer Stunde werden auf einen einzigen Mittelwert reduziert.
Mit der Option 'average=day' werden alle numerischen Werte eines Tages auf einen einzigen
Mittelwert reduziert (impliziert 'average'). <br><br>
Mit den Attributen "device" und "reading" können die zu berücksichtigenden Datensätze eingeschlossen
bzw. ausgeschlossen werden. Beide Eingrenzungen reduzieren die selektierten Daten und verringern den bzw. ausgeschlossen werden. Beide Eingrenzungen reduzieren die selektierten Daten und verringern den
Ressourcenbedarf. Ressourcenbedarf.
Das Reading "reduceLogState" enthält das Ausführungsergebnis des letzten reduceLog-Befehls. <br><br> Das Reading "reduceLogState" enthält das Ausführungsergebnis des letzten reduceLog-Befehls. <br><br>
Die für diese Funktion relevanten Attribute sind: <br><br> Unter Berücksichtigung des oben genannten sind für diese Funktion folgende Attribute relevant: <br><br>
<ul> <ul>
<table> <table>
@ -15211,17 +15280,8 @@ sub bdump {
</ul> </ul>
<br> <br>
Aus Kompatibilitätsgründen kann der Set-Befehl optional durch die Zusätze "EXCLUDE" bzw. "INCLUDE"
direkt ergänzt werden um device/reading Kombinationen von reduceLog auszuschließen bzw. einzuschließen: <br><br>
<ul>
"reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br>
</ul>
Diese Angabe wird als Regex ausgewertet und überschreibt die Einstellung der Attribute "device" und "reading",
die in diesem Fall nicht beachtet werden. <br><br>
<ul>
<b>Beispiele: </b><br><br> <b>Beispiele: </b><br><br>
<ul>
attr &lt;name&gt; timeOlderThan = d:200 <br> attr &lt;name&gt; timeOlderThan = d:200 <br>
set &lt;name&gt; reduceLog <br> set &lt;name&gt; reduceLog <br>
# Datensätze die älter als 200 Tage sind, werden auf den ersten Eintrag pro Stunde je Device & Reading # Datensätze die älter als 200 Tage sind, werden auf den ersten Eintrag pro Stunde je Device & Reading
@ -15251,6 +15311,20 @@ sub bdump {
werden bereinigt. Numerische Werte einer Stunde werden auf einen Mittelwert reduziert <br> werden bereinigt. Numerische Werte einer Stunde werden auf einen Mittelwert reduziert <br>
<br> <br>
</ul> </ul>
<br>
<b>Arbeitsweise mit Optionsangabe</b> <br><br>
Es werden Datensätze berücksichtigt die älter sind als <b>&lt;no&gt;</b> Tage und (optional) neuer sind als
<b>&lt;nn&gt;</b> Tage.
Durch die Angabe von <b>average</b> wird nicht nur die Datenbank bereinigt, sondern
alle numerischen Werte einer Stunde werden auf einen einzigen Mittelwert reduziert.
Mit der Option <b>average=day</b> werden alle numerischen Werte eines Tages auf einen einzigen
Mittelwert reduziert (impliziert 'average'). <br><br>
Die Zusätze "EXCLUDE" bzw. "INCLUDE" können ergänzt werden um device/reading Kombinationen von reduceLog auszuschließen
bzw. einzuschließen. Diese Angabe wird als Regex ausgewertet und überschreibt die Einstellung der Attribute "device"
und "reading", die in diesem Fall nicht beachtet werden. <br><br>
<b>Hinweis:</b> <br> <b>Hinweis:</b> <br>
Obwohl die Funktion selbst non-blocking ausgelegt ist, sollte das zugeordnete DbLog-Device Obwohl die Funktion selbst non-blocking ausgelegt ist, sollte das zugeordnete DbLog-Device
@ -15466,16 +15540,20 @@ sub bdump {
</li><br><br> </li><br><br>
<li><b> sumValue [display | writeToDB]</b> <li><b> sumValue [display | writeToDB | writeToDBSingle]</b>
- Berechnet die Summenwerte des Datenbankfelds "VALUE" in den Zeitgrenzen - Berechnet die Summenwerte des Datenbankfelds "VALUE" in den Zeitgrenzen
(Attribute) "timestamp_begin", "timestamp_end" bzw. "timeDiffToNow / timeOlderThan". der möglichen time.*-Attribute. <br><br>
Es muss das auszuwertende Reading im <a href="#DbRepattr">Attribut</a> "reading"
angegeben sein. Diese Funktion ist sinnvoll wenn fortlaufend Wertedifferenzen eines Es muss das auszuwertende Reading im Attribut <a href="#reading">reading</a>
Readings in die Datenbank geschrieben werden. <br> angegeben sein. Diese Funktion ist sinnvoll wenn fortlaufend Wertedifferenzen eines
Readings in die Datenbank geschrieben werden. <br><br>
Ist keine oder die Option <b>display</b> angegeben, werden die Ergebnisse nur angezeigt. Mit
den Optionen <b>writeToDB</b> bzw. <b>writeToDBSingle</b> werden die Berechnungsergebnisse
mit einem neuen Readingnamen in der Datenbank gespeichert. <br>
<b>writeToDB</b> schreibt jeweils einen Wert am Anfang und am Ende einer Auswertungsperiode.
<b>writeToDBSingle</b> schreibt nur einen Wert am Ende einer Auswertungsperiode. <br><br>
Ist keine oder die Option "display" angegeben, werden die Ergebnisse nur angezeigt. Mit
der Option "writeToDB" werden die Berechnungsergebnisse mit einem neuen Readingnamen
in der Datenbank gespeichert. <br>
Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet, Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet,
wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann. wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann.
Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen. <br> Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen. <br>