2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-16 10:46:03 +00:00

93_DbRep: new averageValue option writeToDBSingleStart

git-svn-id: https://svn.fhem.de/fhem/trunk@27047 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2023-01-13 20:58:50 +00:00
parent 68213ef818
commit a389b426e4
2 changed files with 478 additions and 332 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: new averageValue option writeToDBSingleStart
- bugfix: 72_FRITZBOX: Fehlerbereinigungen u.a. "," Reading - bugfix: 72_FRITZBOX: Fehlerbereinigungen u.a. "," Reading
- change: 49_SSCamSTRM: change behavior of hideDisplayName, - change: 49_SSCamSTRM: change behavior of hideDisplayName,
hideDisplayNameFTUI if device is disabled hideDisplayNameFTUI if device is disabled

View File

@ -59,7 +59,8 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
my %DbRep_vNotesIntern = ( my %DbRep_vNotesIntern = (
"8.51.1" => "01.01.2023 write TYPE uppercase with writeToDB option, Commandref edited, fix add SQL Cache History ". "8.51.2" => "13.01.2023 rewrite sub DbRep_OutputWriteToDB, new averageValue option writeToDBSingleStart ",
"8.51.1" => "11.01.2023 write TYPE uppercase with writeToDB option, Commandref edited, fix add SQL Cache History ".
"set PRAGMA auto_vacuum = FULL when execute SQLite vacuum command", "set PRAGMA auto_vacuum = FULL when execute SQLite vacuum command",
"8.51.0" => "02.01.2023 online formatting of sqlCmd, sqlCmdHistory, sqlSpecial, Commandref edited, get dbValue removed ". "8.51.0" => "02.01.2023 online formatting of sqlCmd, sqlCmdHistory, sqlSpecial, Commandref edited, get dbValue removed ".
"sqlCmdBlocking customized like sqlCmd, bugfix avgTimeWeightMean ", "sqlCmdBlocking customized like sqlCmd, bugfix avgTimeWeightMean ",
@ -641,7 +642,7 @@ sub DbRep_Set {
(($hash->{ROLE} ne "Agent") ? "tableCurrentPurge:noArg " : ""). (($hash->{ROLE} ne "Agent") ? "tableCurrentPurge:noArg " : "").
(($hash->{ROLE} ne "Agent") ? "countEntries:history,current " : ""). (($hash->{ROLE} ne "Agent") ? "countEntries:history,current " : "").
(($hash->{ROLE} ne "Agent") ? "sumValue:display,writeToDB,writeToDBSingle,writeToDBInTime " : ""). (($hash->{ROLE} ne "Agent") ? "sumValue:display,writeToDB,writeToDBSingle,writeToDBInTime " : "").
(($hash->{ROLE} ne "Agent") ? "averageValue:display,writeToDB,writeToDBSingle,writeToDBInTime " : ""). (($hash->{ROLE} ne "Agent") ? "averageValue:display,writeToDB,writeToDBSingle,writeToDBSingleStart,writeToDBInTime " : "").
(($hash->{ROLE} ne "Agent") ? "delSeqDoublets:adviceRemain,adviceDelete,delete " : ""). (($hash->{ROLE} ne "Agent") ? "delSeqDoublets:adviceRemain,adviceDelete,delete " : "").
(($hash->{ROLE} ne "Agent" && $dbmodel =~ /MYSQL/) ? "dumpMySQL:clientSide,serverSide " : ""). (($hash->{ROLE} ne "Agent" && $dbmodel =~ /MYSQL/) ? "dumpMySQL:clientSide,serverSide " : "").
(($hash->{ROLE} ne "Agent" && $dbmodel =~ /SQLITE/) ? "dumpSQLite:noArg " : ""). (($hash->{ROLE} ne "Agent" && $dbmodel =~ /SQLITE/) ? "dumpSQLite:noArg " : "").
@ -3518,25 +3519,31 @@ sub DbRep_averval {
} }
my $aval = (DbRep_checktimeaggr($hash))[2]; my $aval = (DbRep_checktimeaggr($hash))[2];
if($aval eq "hour") { if($aval eq "hour") {
@rsf = split(/[ :]/,$runtime_string_first); @rsf = split /[ :]/,$runtime_string_first;
@rsn = split(/[ :]/,$runtime_string_next); @rsn = split /[ :]/,$runtime_string_next;
$arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."|"; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."|";
} }
elsif ($aval eq "minute") { elsif ($aval eq "minute") {
@rsf = split(/[ :]/,$runtime_string_first); @rsf = split /[ :]/,$runtime_string_first;
@rsn = split(/[ :]/,$runtime_string_next); @rsn = split /[ :]/,$runtime_string_next;
$arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."-".$rsf[2]."|"; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."_".$rsf[1]."-".$rsf[2]."|";
} }
else { else {
@rsf = split(" ",$runtime_string_first); @rsf = split " ",$runtime_string_first;
@rsn = split(" ",$runtime_string_next); @rsn = split " ",$runtime_string_next;
$arrstr .= $runtime_string."#".$sum."#".$rsf[0]."|"; $arrstr .= $runtime_string."#".$sum."#".$rsf[0]."|";
} }
@wsf = split(" ",$runtime_string_first); #@wsf = split " ",$runtime_string_first;
@wsn = split(" ",$runtime_string_next); #@wsn = split " ",$runtime_string_next;
$wrstr .= $runtime_string."#".$sum."#".$wsf[0]."_".$wsf[1]."#".$wsn[0]."_".$wsn[1]."|"; # Kombi zum Rückschreiben in die DB
$runtime_string_first =~ s/\s/_/xs;
$runtime_string_next =~ s/\s/_/xs;
#$wrstr .= $runtime_string."#".$sum."#".$wsf[0]."_".$wsf[1]."#".$wsn[0]."_".$wsn[1]."|"; # Kombi zum Rückschreiben in die DB
$wrstr .= $runtime_string."#".$sum."#".$runtime_string_first."#".$runtime_string_next."|"; # Kombi zum Rückschreiben in die DB
} }
} }
@ -4352,7 +4359,7 @@ sub DbRep_diffval {
$runtime_string = encode_base64($runtime_string,""); $runtime_string = encode_base64($runtime_string,"");
if($dbmodel eq "OLDMYSQLVER") { # Forum: https://forum.fhem.de/index.php/topic,130697.0.html if($dbmodel eq "OLDMYSQLVER") { # Forum: https://forum.fhem.de/index.php/topic,130697.0.html
$err = DbRep_dbhDo ($name, $dbh, "set \@V:= 0, \@diff:= 0, \@diffTotal:= 0, \@RB:= 1;"); # @\RB = Resetbit wenn neues Selektionsintervall beginnt ($err, undef) = DbRep_dbhDo ($name, $dbh, "set \@V:= 0, \@diff:= 0, \@diffTotal:= 0, \@RB:= 1;"); # @\RB = Resetbit wenn neues Selektionsintervall beginnt
return "$name|$err" if ($err); return "$name|$err" if ($err);
} }
@ -4969,13 +4976,13 @@ sub DbRep_insert {
my ($sth,$sql,$irow); my ($sth,$sql,$irow);
# insert into $table mit/ohne primary key # insert into $table mit/ohne primary key
if ($usepkh && $dbloghash->{MODEL} eq 'MYSQL') { if ($usepkh && $dbmodel eq 'MYSQL') {
$sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; $sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)";
} }
elsif ($usepkh && $dbloghash->{MODEL} eq 'SQLITE') { elsif ($usepkh && $dbmodel eq 'SQLITE') {
$sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"; $sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)";
} }
elsif ($usepkh && $dbloghash->{MODEL} eq 'POSTGRESQL') { elsif ($usepkh && $dbmodel eq 'POSTGRESQL') {
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"; $sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING";
} }
else { else {
@ -6883,7 +6890,7 @@ sub _DbRep_setSessAttrVars {
$pm = ltrim($pm).';'; $pm = ltrim($pm).';';
$pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";"
my $err = DbRep_dbhDo ($name, $dbh, $pm, "Set VARIABLE or PRAGMA: $pm"); (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Set VARIABLE or PRAGMA: $pm");
return $err if ($err); return $err if ($err);
} }
} }
@ -6913,7 +6920,7 @@ sub _DbRep_setSessVars {
$pm = ltrim($pm).';'; $pm = ltrim($pm).';';
$pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";"
my $err = DbRep_dbhDo ($name, $dbh, $pm, "Set SQL session variable: $pm"); (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Set SQL session variable: $pm");
return $err if ($err); return $err if ($err);
} }
} }
@ -6943,7 +6950,7 @@ sub _DbRep_setSessPragma {
$pm = ltrim($pm).';'; $pm = ltrim($pm).';';
$pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";"
my $err = DbRep_dbhDo ($name, $dbh, $pm, "Exec PRAGMA Statement: $pm"); (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Exec PRAGMA Statement: $pm");
return $err if ($err); return $err if ($err);
} }
} }
@ -6975,7 +6982,7 @@ sub _DbRep_execSessPrepare {
$pm = ltrim($pm).';'; $pm = ltrim($pm).';';
$pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";" $pm =~ s/ESC_ESC_ESC/;/gx; # wiederherstellen von escapeten ";" -> umwandeln von ";;" in ";"
my $err = DbRep_dbhDo ($name, $dbh, $pm, "Exec PREPARE statement: $pm"); (my $err, undef) = DbRep_dbhDo ($name, $dbh, $pm, "Exec PREPARE statement: $pm");
return $err if ($err); return $err if ($err);
} }
} }
@ -7214,7 +7221,7 @@ sub DbRep_dbmeta {
# due to incompatible changes made in MyQL 5.7.5, see http://johnemb.blogspot.de/2014/09/adding-or-removing-individual-sql-modes.html # due to incompatible changes made in MyQL 5.7.5, see http://johnemb.blogspot.de/2014/09/adding-or-removing-individual-sql-modes.html
if($dbmodel eq "MYSQL") { if($dbmodel eq "MYSQL") {
$err = DbRep_dbhDo ($name, $dbh, "SET sql_mode=(SELECT REPLACE(\@\@sql_mode,'ONLY_FULL_GROUP_BY',''));"); ($err, undef) = DbRep_dbhDo ($name, $dbh, "SET sql_mode=(SELECT REPLACE(\@\@sql_mode,'ONLY_FULL_GROUP_BY',''));");
return "$name|$err" if ($err); return "$name|$err" if ($err);
} }
@ -11000,6 +11007,43 @@ sub DbRep_resolveDevspecs {
return ($devs,$devswc); return ($devs,$devswc);
} }
######################################################################################
# Erstelle Insert SQL-Schema für Tabelle mit/ohne primary key
######################################################################################
sub DbRep_createInsertSQLscheme {
my $table = shift;
my $dbmodel = shift;
my $usepkh = shift;
my $sql;
if ($usepkh && $dbmodel eq 'MYSQL') {
$sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)";
}
elsif ($usepkh && $dbmodel eq 'SQLITE') {
$sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)";
}
elsif ($usepkh && $dbmodel eq 'POSTGRESQL') {
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING";
}
else {
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)";
}
return $sql;
}
######################################################################################
# Erstelle Update SQL-Schema für Tabelle
######################################################################################
sub DbRep_createUpdateSQLscheme {
my $table = shift;
my $sql = "UPDATE $table SET TIMESTAMP=?, DEVICE=?, READING=?, TYPE=?, EVENT=?, VALUE=?, UNIT=? WHERE TIMESTAMP=? AND DEVICE=? AND READING=?";
return $sql;
}
###################################################################################### ######################################################################################
# Connect zur Datenbank herstellen # Connect zur Datenbank herstellen
# #
@ -11147,7 +11191,7 @@ return ($err, $sth, $result);
} }
#################################################################################################### ####################################################################################################
# einfaches Sdbh->do, return ERROR-String wenn Fehler # einfaches Sdbh->do, return ERROR-String wenn Fehler bzw. die Anzahl der betroffenen Zeilen
#################################################################################################### ####################################################################################################
sub DbRep_dbhDo { sub DbRep_dbhDo {
my $name = shift; my $name = shift;
@ -11156,19 +11200,79 @@ sub DbRep_dbhDo {
my $info = shift // "simple do statement: $sql"; my $info = shift // "simple do statement: $sql";
my $err = q{}; my $err = q{};
my $rv = q{};
my $sth;
Log3 ($name, 4, "DbRep $name - $info"); Log3 ($name, 4, "DbRep $name - $info");
eval{ $dbh->do($sql); eval{ $rv = $dbh->do($sql);
1;
} }
or do { $err = encode_base64($@,""); or do { $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@"); Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->disconnect; $dbh->disconnect;
}; };
return $err; return ($err, $rv);
}
####################################################################################################
# führt ein sth execute prepared Insert aus
# return ERROR oder die Anzahl der betroffenen Zeilen
####################################################################################################
sub DbRep_execInsertPrepared {
my $paref = shift;
my $name = $paref->{name};
my $sth = $paref->{sth};
my $timestamp = $paref->{timestamp};
my $device = $paref->{device};
my $type = $paref->{type};
my $event = $paref->{event};
my $reading = $paref->{reading};
my $value = $paref->{value};
my $unit = $paref->{unit};
my $err = q{};
my $rv = q{};
eval{ $rv = $sth->execute($timestamp, $device, $type, $event, $reading, $value, $unit);
}
or do { $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@");
};
$rv = 0 if($rv eq "0E0");
return ($err, $rv);
}
####################################################################################################
# führt ein sth execute prepared Update aus
# return ERROR oder die Anzahl der betroffenen Zeilen
####################################################################################################
sub DbRep_execUpdatePrepared {
my $paref = shift;
my $name = $paref->{name};
my $sth = $paref->{sth};
my $timestamp = $paref->{timestamp};
my $device = $paref->{device};
my $type = $paref->{type};
my $event = $paref->{event};
my $reading = $paref->{reading};
my $value = $paref->{value};
my $unit = $paref->{unit};
my $err = q{};
my $rv = q{};
eval{ $rv = $sth->execute($timestamp, $device, $reading, $type, $event, $value, $unit, $timestamp, $device, $reading);
}
or do { $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - ERROR - $@");
};
$rv = 0 if($rv eq "0E0");
return ($err, $rv);
} }
#################################################################################################### ####################################################################################################
@ -12695,31 +12799,32 @@ return \%ncp;
# Funktionsergebnisse in Datenbank schreiben # Funktionsergebnisse in Datenbank schreiben
#################################################################################################### ####################################################################################################
sub DbRep_OutputWriteToDB { sub DbRep_OutputWriteToDB {
my ($name,$device,$reading,$wrstr,$optxt) = @_; my $name = shift;
my $device = shift;
my $reading = shift;
my $wrstr = shift;
my $optxt = shift; # Operation Kürzel
my $hash = $defs{$name}; my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}}; my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME}; my $dblogname = $dbloghash->{NAME};
my $dbmodel = $dbloghash->{MODEL}; my $DbLogType = AttrVal ($dblogname, 'DbLogType', 'History');
my $DbLogType = AttrVal($dblogname, "DbLogType", "History"); my $supk = AttrVal ($dblogname, 'noSupportPK', 0);
my $supk = AttrVal($dblogname, "noSupportPK", 0);
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = $hash->{UTF8} // 0;
$device =~ s/[^A-Za-z\/\d_\.-]/\//g; $device =~ s/[^A-Za-z\/\d_\.-]/\//g;
$reading =~ s/[^A-Za-z\/\d_\.-]/\//g; $reading =~ s/[^A-Za-z\/\d_\.-]/\//g;
my $type = "calculated"; my $type = 'calculated';
my $event = "calculated"; my $event = 'calculated';
my $unit = ""; my $unit = qq{};
my $wrt = 0; my $wrt = 0;
my $irowdone = 0; my $irowdone = 0;
my $ndp = AttrVal($name, "numDecimalPlaces", $dbrep_defdecplaces); my $ndp = AttrVal ($name, 'numDecimalPlaces', $dbrep_defdecplaces);
my ($dbh,$sth_ih,$sth_uh,$sth_ic,$sth_uc,$err,$value,$date,$time,$hour,$minute,$ndate,$ntime,$rsf,$rsn,@row_array); my ($dbh,$err,$value,$date,$time,$hour,$minute,$ndate,$ntime,$rsf,$rsn,@wr_arr);
my ($timestamp,$year,$mon,$mday,$t1,$corr); my ($timestamp,$year,$mon,$mday,$t1,$corr);
if(!$dbloghash->{HELPER}{COLSET}) { if(!$dbloghash->{HELPER}{COLSET}) {
$err = "No result of \"$hash->{LASTCMD}\" to database written. Cause: column width in \"$hash->{DEF}\" isn't set"; $err = qq(No result of "$hash->{LASTCMD}" to database written. Cause: column width in "$hash->{DEF}" isn't set);
Log3 ($name, 2, "DbRep $name - ERROR - $err"); Log3 ($name, 2, "DbRep $name - ERROR - $err");
@ -12731,51 +12836,46 @@ sub DbRep_OutputWriteToDB {
no warnings 'uninitialized'; no warnings 'uninitialized';
my $aggr = (DbRep_checktimeaggr ($hash))[2]; my $aggr = (DbRep_checktimeaggr ($hash))[2];
$reading = $optxt."_".$aggr."_".AttrVal($name, "readingNameMap", $reading); $reading = $optxt."_".$aggr."_".AttrVal ($name, 'readingNameMap', $reading);
$type = uc($defs{$device}{TYPE}) if($defs{$device}); # $type vom Device übernehmen $type = uc($defs{$device}{TYPE}) if($defs{$device}); # $type vom Device übernehmen
if($optxt =~ /avg|sum/) { if($optxt =~ /avg|sum/) {
my @arr = split("\\|", $wrstr); my @arr = split "\\|", $wrstr;
my $ele = $#arr; # Nr des letzten Elements my $ele = $#arr; # Nr des letzten Elements
my $i = 0; my $i = 0;
for my $row (@arr) { for 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("%.${ndp}f",$a[1]) : undef) : undef; # in Version 8.40.0 geändert $value = defined($a[1]) ? (looks_like_number($a[1]) ? sprintf("%.${ndp}f",$a[1]) : undef) : undef; # in Version 8.40.0 geändert
$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);
$rsn = $a[3]; # Runtime String next - Datum / Zeit für DB-Speicherung $rsn = $a[3]; # Runtime String next - Datum / Zeit für DB-Speicherung
($ndate,$ntime) = split("_",$rsn); ($ndate,$ntime) = split "_", $rsn;
$ntime =~ s/-/:/g if($ntime); $ntime =~ s/-/:/g if($ntime);
if($aggr =~ /no|day|week|month|year/) { if($aggr =~ /no|day|week|month|year/) {
$time = "00:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920 $time = "00:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920
$ntime = "23:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); $ntime = "23:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/);
($year,$mon,$mday) = split("-", $ndate);
$corr = ($i != $ele) ? 86400 : 0; ($year,$mon,$mday) = split "-", $ndate;
$corr = $i != $ele ? 86400 : 0;
$t1 = fhemTimeLocal(59, 59, 23, $mday, $mon-1, $year-1900)-$corr; $t1 = fhemTimeLocal(59, 59, 23, $mday, $mon-1, $year-1900)-$corr;
($ndate,undef) = split(" ",FmtDateTime($t1)); ($ndate,undef) = split " ", FmtDateTime($t1);
} }
elsif ($aggr =~ /minute|hour/) { elsif ($aggr =~ /minute|hour/) {
($hour,$minute) = split ":", $time; ($hour,$minute) = split ":", $time;
if($aggr eq "minute") { if($aggr eq "minute") {
$time = "$hour:$minute:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920 $time = "$hour:$minute:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920
$ntime = "$hour:$minute:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); $ntime = "$hour:$minute:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/);
} }
if($aggr eq "hour") { if($aggr eq "hour") {
$time = "$hour:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920 $time = "$hour:00:01" if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/); # https://forum.fhem.de/index.php/topic,105787.msg1013920.html#msg1013920
$ntime = "$hour:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single)*?\b/); $ntime = "$hour:59:59" if($ntime !~ /^(\d{2}):(\d{2}):(\d{2})$/ || $hash->{LASTCMD} =~ /\bwriteToDB(Single(Start)?)*?\b/);
}
if ($ntime eq "23:59:59") {
($year,$mon,$mday) = split("-", $ndate);
$t1 = fhemTimeLocal(59, 59, 23, $mday, $mon-1, $year-1900)-86400;
($ndate,undef) = split(" ",FmtDateTime($t1));
} }
} }
@ -12783,23 +12883,23 @@ sub DbRep_OutputWriteToDB {
($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") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); push @wr_arr, "$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 @wr_arr, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit" if($hash->{LASTCMD} !~ /\bwriteToDBSingleStart\b/);
} }
else { else {
if ($aggr =~ /no|day|week|month|year/) { if ($aggr =~ /no|day|week|month|year/) {
($year,$mon,$mday) = split("-", $date); ($year,$mon,$mday) = split "-", $date;
$t1 = fhemTimeLocal(01, 00, 00, $mday, $mon-1, $year-1900); $t1 = fhemTimeLocal(01, 00, 00, $mday, $mon-1, $year-1900);
($date,$time) = split(" ",FmtDateTime($t1)); ($date,$time) = split " ", FmtDateTime($t1);
} }
elsif ($aggr =~ /hour/) { elsif ($aggr =~ /hour/) {
($year,$mon,$mday) = split("-", $date); ($year,$mon,$mday) = split "-", $date;
$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") if($hash->{LASTCMD} !~ /\bwriteToDBSingle\b/); push @wr_arr, "$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 @wr_arr, "$ndate $ntime|$device|$type|$event|$reading|$value|$unit" if($hash->{LASTCMD} !~ /\bwriteToDBSingleStart\b/);
} }
} }
$i++; $i++;
@ -12807,14 +12907,14 @@ sub DbRep_OutputWriteToDB {
} }
if($optxt =~ /min|max|diff/) { if($optxt =~ /min|max|diff/) {
my %rh = split("§", $wrstr); my %rh = split "§", $wrstr;
for my $key (sort(keys(%rh))) { for my $key (sort(keys(%rh))) {
my @k = split("\\|",$rh{$key}); my @k = split "\\|", $rh{$key};
$value = defined($k[1]) ? sprintf("%.${ndp}f",$k[1]) : undef; $value = defined($k[1]) ? sprintf("%.${ndp}f",$k[1]) : undef;
$rsf = $k[2]; # Datum / Zeit für DB-Speicherung $rsf = $k[2]; # Datum / Zeit für DB-Speicherung
($date,$time) = split("_",$rsf); ($date,$time) = split "_", $rsf;
$time =~ s/-/:/g if($time); $time =~ s/-/:/g if($time);
if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/) { if($time !~ /^(\d{2}):(\d{2}):(\d{2})$/) {
@ -12830,22 +12930,20 @@ sub DbRep_OutputWriteToDB {
} }
if ($value) { if ($value) {
($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);
push(@row_array, "$date $time|$device|$type|$event|$reading|$value|$unit"); push @wr_arr, "$date $time|$device|$type|$event|$reading|$value|$unit";
} }
} }
} }
if (@row_array) { # Schreibzyklus aktivieren return ($err,$wrt,$irowdone) if(!@wr_arr);
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, mysql_enable_utf8 => $utf8 });};
if ($@) {
$err = $@;
Log3 ($name, 2, "DbRep $name - ERROR - $@"); #Log3 ($name, 2, "DbRep $name - data for write: \n". Dumper @wr_arr);
#return;
$err = encode_base64($err,""); # Schreibzyklus
##################
return ($err,$wrt,$irowdone); ($err, $dbh, my $dbmodel) = DbRep_dbConnect ($name, 0);
} return ($err,$wrt,$irowdone) if ($err);
# check ob PK verwendet wird, @usepkx?Anzahl der Felder im PK:0 wenn kein PK, $pkx?Namen der Felder:none wenn kein PK # check ob PK verwendet wird, @usepkx?Anzahl der Felder im PK:0 wenn kein PK, $pkx?Namen der Felder:none wenn kein PK
my ($usepkh,$usepkc,$pkh,$pkc); my ($usepkh,$usepkc,$pkh,$pkc);
@ -12854,64 +12952,36 @@ sub DbRep_OutputWriteToDB {
($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbloghash,$dbh); ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbloghash,$dbh);
} }
else { else {
Log3 ($hash->{NAME}, 5, "DbRep $name -> Primary Key usage suppressed by attribute noSupportPK in DbLog \"$dblogname\""); Log3 ($name, 5, "DbRep $name -> Primary Key usage suppressed by attribute noSupportPK in DbLog >$dblogname<");
} }
if (lc($DbLogType) =~ m(history)) { # INSERT history mit/ohne primary key my $sql = DbRep_createInsertSQLscheme ('history', $dbmodel, $usepkh);
if ($usepkh && $dbloghash->{MODEL} eq 'MYSQL') { ($err, my $sth_ih) = DbRep_prepareOnly ($name, $dbh, $sql);
eval { $sth_ih = $dbh->prepare_cached("INSERT IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; return ($err,$wrt,$irowdone) if ($err);
}
elsif ($usepkh && $dbloghash->{MODEL} eq 'SQLITE') {
eval { $sth_ih = $dbh->prepare_cached("INSERT OR IGNORE INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); };
}
elsif ($usepkh && $dbloghash->{MODEL} eq 'POSTGRESQL') {
eval { $sth_ih = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); };
}
else {
eval { $sth_ih = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); };
}
if ($@) {
$err = $@;
Log3 ($name, 2, "DbRep $name - ERROR - $@");
$err = encode_base64($err,"");
return ($err,$wrt,$irowdone);
}
}
if (lc($DbLogType) =~ m(current) ) { # INSERT current mit/ohne primary key $sql = DbRep_createUpdateSQLscheme ('history');
if ($usepkc && $hash->{MODEL} eq 'MYSQL') { ($err, my $sth_uh) = DbRep_prepareOnly ($name, $dbh, $sql);
eval { $sth_ic = $dbh->prepare("INSERT IGNORE INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); }; return ($err,$wrt,$irowdone) if ($err);
}
elsif ($usepkc && $hash->{MODEL} eq 'SQLITE') {
eval { $sth_ic = $dbh->prepare("INSERT OR IGNORE INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); };
}
elsif ($usepkc && $hash->{MODEL} eq 'POSTGRESQL') {
eval { $sth_ic = $dbh->prepare("INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING"); };
}
else {
# old behavior
eval { $sth_ic = $dbh->prepare("INSERT INTO current (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); };
}
if ($@) {
$err = $@;
Log3 ($name, 2, "DbRep $name - ERROR - $@");
$err = encode_base64($err,"");
return ($err,$wrt,$irowdone);
}
}
eval { $dbh->begin_work() if($dbh->{AutoCommit}); }; $sql = DbRep_createInsertSQLscheme ('current', $dbmodel, $usepkc);
if ($@) { ($err, my $sth_ic) = DbRep_prepareOnly ($name, $dbh, $sql);
Log3($name, 2, "DbRep $name - ERROR - $@"); return ($err,$wrt,$irowdone) if ($err);
}
$sql = DbRep_createUpdateSQLscheme ('current');
($err, my $sth_uc) = DbRep_prepareOnly ($name, $dbh, $sql);
return ($err,$wrt,$irowdone) if ($err);
$err = DbRep_beginDatabaseTransaction ($name, $dbh);
return ($err,$wrt,$irowdone) if ($err);
my $wst = [gettimeofday]; # SQL-Startzeit my $wst = [gettimeofday]; # SQL-Startzeit
my $ihs = 0; my $ihs = 0;
my $uhs = 0; my $uhs = 0;
for my $row (@row_array) { for my $row (@wr_arr) {
my @a = split("\\|",$row); my @a = split "\\|", $row;
$timestamp = $a[0]; $timestamp = $a[0];
$device = $a[1]; $device = $a[1];
$type = $a[2]; $type = $a[2];
@ -12920,52 +12990,94 @@ sub DbRep_OutputWriteToDB {
$value = $a[5]; $value = $a[5];
$unit = $a[6]; $unit = $a[6];
eval { # update oder insert history
if (lc($DbLogType) =~ m(history) ) { if (lc($DbLogType) =~ m(history) ) {
my $rv_uh = $dbh->do("UPDATE history SET TIMESTAMP=\"$timestamp\", DEVICE=\"$device\", READING=\"$reading\", TYPE=\"$type\", EVENT=\"$event\", VALUE=\"$value\", UNIT=\"$unit\" WHERE TIMESTAMP=\"$timestamp\" AND DEVICE=\"$device\" AND READING=\"$reading\""); ($err, my $rv_uh) = DbRep_execUpdatePrepared ( { name => $name,
sth => $sth_uh,
timestamp => $timestamp,
device => $device,
type => $type,
event => $event,
reading => $reading,
value => $value,
unit => $unit
}
);
if ($err) {
$dbh->disconnect;
return ($err,$wrt,$irowdone);
}
$uhs += $rv_uh if($rv_uh); $uhs += $rv_uh if($rv_uh);
Log3 ($hash->{NAME}, 4, "DbRep $name - UPDATE history: $row, RESULT: $rv_uh"); Log3 ($name, 4, "DbRep $name - UPDATE history: $row, RESULT: $rv_uh");
if ($rv_uh == 0) { if ($rv_uh == 0) {
my $rv_ih = $sth_ih->execute($timestamp,$device,$type,$event,$reading,$value,$unit); ($err, my $rv_ih) = DbRep_execInsertPrepared ( { name => $name,
sth => $sth_ih,
timestamp => $timestamp,
device => $device,
type => $type,
event => $event,
reading => $reading,
value => $value,
unit => $unit
}
);
if ($err) {
$dbh->disconnect;
return ($err,$wrt,$irowdone);
}
$ihs += $rv_ih if($rv_ih); $ihs += $rv_ih if($rv_ih);
Log3 $hash->{NAME}, 4, "DbRep $name - INSERT history: $row, RESULT: $rv_ih";
Log3 ($name, 4, "DbRep $name - INSERT history: $row, RESULT: $rv_ih");
} }
} }
if (lc($DbLogType) =~ m(current) ) { # update oder insert current if (lc($DbLogType) =~ m(current) ) {
my $rv_uc = $dbh->do("UPDATE current SET TIMESTAMP=\"$timestamp\", DEVICE=\"$device\", READING=\"$reading\", TYPE=\"$type\", EVENT=\"$event\", VALUE=\"$value\", UNIT=\"$unit\" WHERE DEVICE=\"$device\" AND READING=\"$reading\""); ($err, my $rv_uc) = DbRep_execUpdatePrepared ( { name => $name,
sth => $sth_uc,
timestamp => $timestamp,
device => $device,
type => $type,
event => $event,
reading => $reading,
value => $value,
unit => $unit
}
);
if ($err) {
$dbh->disconnect;
return ($err,$wrt,$irowdone);
}
if ($rv_uc == 0) { if ($rv_uc == 0) {
$sth_ic->execute($timestamp,$device,$type,$event,$reading,$value,$unit); ($err, undef) = DbRep_execInsertPrepared ( { name => $name,
sth => $sth_ic,
timestamp => $timestamp,
device => $device,
type => $type,
event => $event,
reading => $reading,
value => $value,
unit => $unit
} }
);
} }
};
if ($@) {
$err = $@;
Log3 ($name, 2, "DbRep $name - ERROR - $@");
$dbh->rollback;
$dbh->disconnect;
$err = encode_base64($err,"");
return ($err,$wrt,0);
} }
} }
eval {$dbh->commit() if(!$dbh->{AutoCommit});}; $err = DbRep_commitOnly ($name, $dbh);
return ($err,$wrt,$irowdone) if ($err);
$dbh->disconnect; $dbh->disconnect;
Log3 ($hash->{NAME}, 3, "DbRep $name - number of lines updated in \"$dblogname\": $uhs"); Log3 ($name, 3, "DbRep $name - number of lines updated in >$dblogname<: $uhs");
Log3 ($hash->{NAME}, 3, "DbRep $name - number of lines inserted into \"$dblogname\": $ihs"); Log3 ($name, 3, "DbRep $name - number of lines inserted into >$dblogname<: $ihs");
$irowdone = $ihs + $uhs; $irowdone = $ihs + $uhs;
$wrt = tv_interval($wst); # SQL-Laufzeit ermitteln $wrt = tv_interval($wst); # SQL-Laufzeit ermitteln
}
return ($err,$wrt,$irowdone); return ($err,$wrt,$irowdone);
} }
@ -13805,8 +13917,9 @@ return;
</li> <br> </li> <br>
<li><b> averageValue [display | writeToDB | writeToDBSingle | writeToDBInTime]</b> <li><b> averageValue [display | writeToDB | writeToDBSingle | writeToDBSingleStart | writeToDBInTime]</b> <br><br>
- calculates an average value of the database field "VALUE" in the time limits
Calculates an average value of the database field "VALUE" in the time limits
of the possible time.*-attributes. <br><br> of the possible time.*-attributes. <br><br>
The reading to be evaluated must be specified in the attribute <a href="#DbRep-attr-reading">reading</a> The reading to be evaluated must be specified in the attribute <a href="#DbRep-attr-reading">reading</a>
@ -13815,14 +13928,16 @@ return;
is used for Averaging defined. <br><br> is used for Averaging defined. <br><br>
If none or the option <b>display</b> is specified, the results are only displayed. With If none or the option <b>display</b> is specified, the results are only displayed. With
the options <b>writeToDB</b>, <b>writeToDBSingle</b> or <b>writeToDBInTime</b> the calculation results are written the options <b>writeToDB</b>, <b>writeToDBSingle</b>, <b>writeToDBSingleStart</b> or <b>writeToDBInTime</b> the
with a new reading name into the database. <br><br> calculation results are written with a new reading name into the database.
<br><br>
<ul> <ul>
<table> <table>
<colgroup> <col width=10%> <col width=90%> </colgroup> <colgroup> <col width=10%> <col width=90%> </colgroup>
<tr><td> <b>writeToDB</b> </td><td>: writes one value each with the time stamps XX:XX:01 and XX:XX:59 within the respective evaluation period </td></tr> <tr><td> <b>writeToDB</b> </td><td>: writes one value each with the time stamps XX:XX:01 and XX:XX:59 within the respective evaluation period </td></tr>
<tr><td> <b>writeToDBSingle</b> </td><td>: writes only one value with the time stamp XX:XX:59 at the end of an evaluation period </td></tr> <tr><td> <b>writeToDBSingle</b> </td><td>: writes only one value with the time stamp XX:XX:59 at the end of an evaluation period </td></tr>
<tr><td> <b>writeToDBSingleStart</b> </td><td>: writes only one value with the time stamp XX:XX:01 at the begin of an evaluation period </td></tr>
<tr><td> <b>writeToDBInTime</b> </td><td>: writes a value at the beginning and end of the time limits of an evaluation period </td></tr> <tr><td> <b>writeToDBInTime</b> </td><td>: writes a value at the beginning and end of the time limits of an evaluation period </td></tr>
</table> </table>
</ul> </ul>
@ -15264,7 +15379,7 @@ return;
<br> <br>
<br> <br>
The relevant attributes to control this function are: <br><br> The following attributes are relevant for this function: <br><br>
<ul> <ul>
<table> <table>
@ -15278,20 +15393,35 @@ return;
</li> </li>
<li><b> vacuum </b> - optimize tables in the connected database (SQLite, PostgreSQL). <br> <a id="DbRep-set-vacuum"></a>
Before and after an optimization it is possible to execute a FHEM command. <li><b> vacuum </b> <br><br>
(please see attributes <a href="#DbRep-attr-executeBeforeProc">executeBeforeProc</a>, <a href="#DbRep-attr-executeAfterProc">executeAfterProc</a>)
<br><br> Optimizes the tables in the connected database (SQLite, PostgreSQL). <br>
Especially for SQLite databases it is strongly recommended to temporarily close the connection of the relevant DbLog
device to the database (see DbLog reopen command).
<br>
<br>
The following attributes are relevant for this function: <br><br>
<ul> <ul>
<b>Note:</b> <br> <table>
Even though the function itself is designed non-blocking, make sure the assigned DbLog-device <colgroup> <col width=5%> <col width=95%> </colgroup>
is operating in asynchronous mode to avoid FHEM from blocking. <br><br> <tr><td> <b>executeBeforeProc</b> </td><td>: execution of FHEM command (or Perl-routine) before operation </td></tr>
<tr><td> <b>executeAfterProc</b> </td><td>: execution of FHEM command (or Perl-routine) after operation </td></tr>
</table>
</ul>
<br>
<br>
<b>Hinweis:</b> <br>
When the vacuum command is executed, the PRAGMA <b>auto_vacuum = FULL</b> is automatically applied to SQLite databases.
</li> </li>
</ul><br> <br>
<br> <br>
</ul></ul> </ul>
</ul>
<b>For all evaluation variants (except sqlCmd,deviceRename,readingRename) applies: </b> <br> <b>For all evaluation variants (except sqlCmd,deviceRename,readingRename) applies: </b> <br>
In addition to the needed reading the device can be complemented to restrict the datasets for reporting / function. In addition to the needed reading the device can be complemented to restrict the datasets for reporting / function.
@ -16666,24 +16796,25 @@ return;
</li> <br> </li> <br>
<li><b> averageValue [display | writeToDB | writeToDBSingle | writeToDBInTime]</b> <li><b> averageValue [display | writeToDB | writeToDBSingle | writeToDBSingleStart | writeToDBInTime]</b> <br><br>
- berechnet einen Durchschnittswert des Datenbankfelds "VALUE" in den Zeitgrenzen
Berechnet einen Durchschnittswert des Datenbankfelds "VALUE" in den Zeitgrenzen
der möglichen time.*-Attribute. <br><br> der möglichen time.*-Attribute. <br><br>
</li>
Es muss das auszuwertende Reading im Attribut <a href="#DbRep-attr-reading">reading</a> Es muss das auszuwertende Reading im Attribut <a href="#DbRep-attr-reading">reading</a>
angegeben sein. angegeben sein.
Mit dem Attribut <a href="#DbRep-attr-averageCalcForm">averageCalcForm</a> wird die Berechnungsvariante zur Mit dem Attribut <a href="#DbRep-attr-averageCalcForm">averageCalcForm</a> wird die Berechnungsvariante zur
Mittelwertermittlung definiert. <br> Mittelwertermittlung definiert. <br>
Ist keine oder die Option <b>display</b> angegeben, werden die Ergebnisse nur angezeigt. Mit Ist keine oder die Option <b>display</b> angegeben, werden die Ergebnisse nur angezeigt. Mit
den Optionen <b>writeToDB</b>, <b>writeToDBSingle</b> bzw. <b>writeToDBInTime</b> werden die Berechnungsergebnisse den Optionen <b>writeToDB</b>, <b>writeToDBSingle</b>, <b>writeToDBSingleStart</b> bzw. <b>writeToDBInTime</b>
mit einem neuen Readingnamen in der Datenbank gespeichert. <br><br> werden die Berechnungsergebnisse mit einem neuen Readingnamen in der Datenbank gespeichert. <br><br>
<ul> <ul>
<table> <table>
<colgroup> <col width=10%> <col width=90%> </colgroup> <colgroup> <col width=10%> <col width=90%> </colgroup>
<tr><td> <b>writeToDB</b> </td><td>: schreibt jeweils einen Wert mit den Zeitstempeln XX:XX:01 und XX:XX:59 innerhalb der jeweiligen Auswertungsperiode </td></tr> <tr><td> <b>writeToDB</b> </td><td>: schreibt jeweils einen Wert mit den Zeitstempeln XX:XX:01 und XX:XX:59 innerhalb der jeweiligen Auswertungsperiode </td></tr>
<tr><td> <b>writeToDBSingle</b> </td><td>: schreibt nur einen Wert mit dem Zeitstempel XX:XX:59 am Ende einer Auswertungsperiode </td></tr> <tr><td> <b>writeToDBSingle</b> </td><td>: schreibt nur einen Wert mit dem Zeitstempel XX:XX:59 am Ende einer Auswertungsperiode </td></tr>
<tr><td> <b>writeToDBSingleStart</b> </td><td>: schreibt nur einen Wert mit dem Zeitstempel XX:XX:01 am Beginn einer Auswertungsperiode </td></tr>
<tr><td> <b>writeToDBInTime</b> </td><td>: schreibt jeweils einen Wert am Anfang und am Ende der Zeitgrenzen einer Auswertungsperiode </td></tr> <tr><td> <b>writeToDBInTime</b> </td><td>: schreibt jeweils einen Wert am Anfang und am Ende der Zeitgrenzen einer Auswertungsperiode </td></tr>
</table> </table>
</ul> </ul>
@ -16722,9 +16853,9 @@ return;
<br> <br>
<br> <br>
</li>
<br> <br>
<li><b> cancelDump </b> - bricht einen laufenden Datenbankdump ab. </li> <br> <li><b> cancelDump </b> - bricht einen laufenden Datenbankdump ab. </li> <br>
<a id="DbRep-set-changeValue"></a> <a id="DbRep-set-changeValue"></a>
@ -18169,21 +18300,35 @@ return;
</li> </li>
<a id="DbRep-set-vacuum"></a> <a id="DbRep-set-vacuum"></a>
<li><b> vacuum </b> - optimiert die Tabellen in der angeschlossenen Datenbank (SQLite, PostgreSQL). <br> <li><b> vacuum </b> <br><br>
Vor und nach der Optimierung kann ein FHEM-Kommando ausgeführt werden.
(siehe Attribute <a href="#DbRep-attr-executeBeforeProc">executeBeforeProc</a>, Optimiert die Tabellen in der angeschlossenen Datenbank (SQLite, PostgreSQL). <br>
<a href="#DbRep-attr-executeAfterProc">executeAfterProc</a>) Insbesondere für SQLite Datenbanken ist unbedingt empfehlenswert die Verbindung des relevanten DbLog-Devices zur
<br><br> Datenbank vorübergehend zu schließen (siehe DbLog reopen Kommando).
<br>
<br>
Für diese Funktion sind folgende Attribute relevant: <br><br>
<ul> <ul>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> <b>executeBeforeProc</b> </td><td>: ausführen FHEM Kommando (oder Perl-Routine) vor Start des Befehls </td></tr>
<tr><td> <b>executeAfterProc</b> </td><td>: ausführen FHEM Kommando (oder Perl-Routine) nach Ende des Befehls </td></tr>
</table>
</ul>
<br>
<br>
<b>Hinweis:</b> <br> <b>Hinweis:</b> <br>
Obwohl die Funktion selbst non-blocking ausgelegt ist, muß das zugeordnete DbLog-Device Bei der Ausführung des vacuum Kommandos wird bei SQLite Datenbanken automatisch das PRAGMA <b>auto_vacuum = FULL</b>
im asynchronen Modus betrieben werden um ein Blockieren von FHEM zu vermeiden. <br><br> angewendet.
</li> </li>
</ul><br> <br>
<br> <br>
</ul></ul> </ul>
</ul>
<b>Für alle Auswertungsvarianten (Ausnahme sqlCmd,deviceRename,readingRename) gilt: </b> <br> <b>Für alle Auswertungsvarianten (Ausnahme sqlCmd,deviceRename,readingRename) gilt: </b> <br>
Zusätzlich zu dem auszuwertenden Reading kann das Device mit angegeben werden um das Reporting nach diesen Kriterien einzuschränken. Zusätzlich zu dem auszuwertenden Reading kann das Device mit angegeben werden um das Reporting nach diesen Kriterien einzuschränken.