From 66a3870237a4e2a4b86601f4593809e54f75f402 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Wed, 7 Nov 2018 21:32:53 +0000 Subject: [PATCH] 93_DbRep: V8.8.0, attribute valueFilter applied to more functions, new attribute 'fastStart' git-svn-id: https://svn.fhem.de/fhem/trunk@17703 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/93_DbRep.pm | 773 ++++++++++++++++++++++++++++++------------ 2 files changed, 552 insertions(+), 223 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 8183278e6..9a3422170 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 93_DbRep: V8.8.0, attribute valueFilter applied to more functions, + new attribute 'fastStart'. (see 'get ... versionNotes') - feature: 00_10_MQTT2_CLIENT added (Forum #92888) - bugfix: 46_Aqicn: fix commandref, change to packages - bugfix: 88_HMCCU: fixed set toggle command diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm index c4edad9a3..cc76642b1 100644 --- a/fhem/FHEM/93_DbRep.pm +++ b/fhem/FHEM/93_DbRep.pm @@ -57,17 +57,19 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch'; # Versions History intern our %DbRep_vNotesIntern = ( + "8.8.0" => "06.11.2018 first connect routine switched to DbRep_Main, get COLSET from DBLOG-instance, attribute 'fastStart' added ", + "8.7.0" => "04.11.2018 attribute valueFilter applied to functions based on 'SELECT', 'UPDATE', 'DELETE' and 'valueFilter' generally applied to field 'VALUE' ", "8.6.0" => "29.10.2018 reduceLog use attributes device/reading (can be overwritten by set-options) ", "8.5.0" => "27.10.2018 versionNotes revised, EXCLUDE of reading/device possible (DbRep_specsForSql changed) ", "8.4.0" => "22.10.2018 countEntries separately for every reading if attribute \"countEntriesDetail\" is set, ". "versionNotes changed to support en/de, get dbValue as textfield-long ", "8.3.0" => "17.10.2018 reduceLog from DbLog integrated into DbRep, textField-long as default for sqlCmd, both attributes timeOlderThan and timeDiffToNow can be set at same time", "8.2.3" => "07.10.2018 check availability of DbLog-device at definition time of DbRep-device ", - "8.2.2" => "07.10.2018 DbRep_getMinTs changed, fix don't get the real min timestamp in rare cases ", + "8.2.2" => "07.10.2018 DbRep_getInitData changed, fix don't get the real min timestamp in rare cases ", "8.2.1" => "07.10.2018 \$hash->{dbloghash}{HELPER}{REOPEN_RUNS_UNTIL} contains time until DB is closed ", "8.2.0" => "05.10.2018 direct help for attributes ", "8.1.0" => "02.10.2018 new get versionNotes command ", - "8.0.1" => "20.09.2018 DbRep_getMinTs improved", + "8.0.1" => "20.09.2018 DbRep_getInitData improved", "8.0.0" => "11.09.2018 get filesize in DbRep_WriteToDumpFile corrected, restoreMySQL for clientSide dumps, minor fixes ", "7.20.0" => "04.09.2018 deviceRename can operate a Device name with blank, e.g. 'current balance' as old device name ", "7.19.0" => "25.08.2018 attribute 'valueFilter' to filter datasets in fetchrows ", @@ -121,6 +123,12 @@ our %DbRep_vNotesIntern = ( # Versions History extern: our %DbRep_vNotesExtern = ( + "8.8.0" => "06.11.2018 new attribute 'fastStart'. Usually every DbRep-device is making a short connect to its database when " + ."FHEM is restarted. When this attribute is set, the initial connect is done when the DbRep-device is doing its " + ."first task. ", + "8.7.0" => "04.11.2018 attribute valueFilter applied to functions 'averageValue, changeValue, countEntries, delEntries, " + ."delSeqDoublets, diffValue, exportToFile, fetchrows, maxValue, minValue, reduceLog, sumValue, syncStandby' ," + ." 'valueFilter' generally applied to database field 'VALUE' ", "8.6.0" => "29.10.2018 reduceLog use attributes device/reading (can be overwritten by set-options) ", "8.5.0" => "27.10.2018 devices and readings can be excluded by EXCLUDE-option in attributes \$reading/\$device ", "8.4.0" => "22.10.2018 New attribute \"countEntriesDetail\". Function countEntries creates number of datasets for every ". @@ -232,6 +240,10 @@ our %DbRep_vNotesExtern = ( # Hint Hash en our %DbRep_vHintsExt_en = ( + "4" => "The attribute 'valueFilter' can specify a REGEXP expression that is used for additional field selection as described in set-function. " + ."If you need more assistance please to the manual of your used database. For example the overview about REGEXP for " + ."MariaDB refer to Regular Expressions " + ."Overview. ", "3" => "Features and restrictions of complex device specifications (devspec) ", "2" => "Rules of german weather service for calculation of average temperatures. ", "1" => "Some helpful FHEM-Wiki Entries." @@ -239,6 +251,10 @@ our %DbRep_vHintsExt_en = ( # Hint Hash de our %DbRep_vHintsExt_de = ( + "4" => "Im Attribut 'valueFilter' können REGEXP zur erweiterten Feldselektion angegeben werden. Welche Felder berücksichtigt " + ."werden, ist in der jeweiligen set-Funktion beschrieben. Für weitere Hilfe bitte die REGEXP-Dokumentation ihrer " + ."verwendeten Datenbank konsultieren. Ein Überblick über REGEXP mit MariaDB ist zum Beispiel hier verfügbar:\n" + ."Regular Expressions Overview. ", "3" => "Merkmale und Restriktionen von komplexen Geräte-Spezifikationen (devspec) ", "2" => "Regularien des deutschen Wetterdienstes zur Berechnung von Durchschnittstemperaturen. ", "1" => "Hilfreiche Hinweise zu DbRep im FHEM-Wiki." @@ -285,6 +301,7 @@ sub DbRep_Initialize($) { "executeBeforeProc ". "executeAfterProc ". "expimpfile ". + "fastStart:1,0 ". "fetchRoute:ascent,descent ". "fetchMarkDuplicates:red,blue,brown,green,orange ". "ftpDebug:1,0 ". @@ -356,8 +373,9 @@ sub DbRep_Define($@) { $hash->{ROLE} = AttrVal($name, "role", "Client"); $hash->{MODEL} = $hash->{ROLE}; $hash->{HELPER}{DBLOGDEVICE} = $a[2]; + $hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen $hash->{VERSION} = (reverse sort(keys %DbRep_vNotesIntern))[0]; - $hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten + $hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten my $dbconn = $defs{$a[2]}{dbconn}; $hash->{DATABASE} = (split(/;|=/, $dbconn))[1]; $hash->{UTF8} = defined($defs{$a[2]}{UTF8})?$defs{$a[2]}{UTF8}:0; @@ -368,11 +386,11 @@ sub DbRep_Define($@) { Log3 ($name, 4, "DbRep $name - history sql commandlist read from file ".$attr{global}{modpath}."/FHEM/FhemUtils/cacheDbRep"); } - RemoveInternalTimer($hash); - InternalTimer(gettimeofday()+int(rand(45)), 'DbRep_firstconnect', $hash, 0); - Log3 ($name, 4, "DbRep $name - initialized"); ReadingsSingleUpdateValue ($hash, 'state', 'initialized', 1); + + RemoveInternalTimer($hash); + InternalTimer(gettimeofday()+int(rand(45)), 'DbRep_firstconnect', "$name||onBoot|", 0); return undef; } @@ -850,7 +868,7 @@ sub DbRep_Get($@) { $hash->{LASTCMD} = $prop?"$opt $prop":"$opt"; return "The operation \"$opt\" isn't available with database type $dbmodel" if ($dbmodel ne 'MYSQL'); ReadingsSingleUpdateValue ($hash, "state", "running", 1); - DbRep_delread($hash); # Readings löschen die nicht in der Ausnahmeliste (Attr readingPreventFromDel) stehen + DbRep_delread($hash); # Readings löschen die nicht in der Ausnahmeliste (Attr readingPreventFromDel) stehen $hash->{HELPER}{RUNNING_PID} = BlockingCall("dbmeta_DoParse", "$name|$opt", "dbmeta_ParseDone", $to, "DbRep_ParseAborted", $hash); } elsif ($opt eq "svrinfo") { @@ -871,8 +889,10 @@ sub DbRep_Get($@) { return "Dump is running - try again later !" if($hash->{HELPER}{RUNNING_BACKUP_CLIENT}); $hash->{LASTCMD} = $prop?"$opt $prop":"$opt"; DbRep_delread($hash); - ReadingsSingleUpdateValue ($hash, "state", "running", 1); - DbRep_firstconnect($hash); + ReadingsSingleUpdateValue ($hash, "state", "running", 1); + $hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen + $prop = $prop?$prop:''; + DbRep_firstconnect("$name|$opt|$prop|"); } elsif ($opt =~ /dbValue/) { return "get \"$opt\" needs at least an argument" if ( @a < 3 ); @@ -999,6 +1019,7 @@ sub DbRep_Attr($$$$) { executeBeforeProc executeAfterProc expimpfile + fastStart ftpUse ftpUser ftpUseSSL @@ -1030,10 +1051,7 @@ sub DbRep_Attr($$$$) { $do = 0 if($cmd eq "del"); my $val = ($do == 1 ? "disabled" : "initialized"); ReadingsSingleUpdateValue ($hash, "state", $val, 1); - if ($do == 0) { - RemoveInternalTimer($hash); - InternalTimer(time+5, 'DbRep_firstconnect', $hash, 0); - } else { + if ($do == 1) { my $dbh = $hash->{DBH}; $dbh->disconnect() if($dbh); } @@ -1330,22 +1348,38 @@ return undef; # Verbindung zur DB aufbauen und den Timestamp des ältesten # Datensatzes ermitteln ################################################################################### -sub DbRep_firstconnect($) { - my ($hash) = @_; - my $name = $hash->{NAME}; - my $to = "120"; - my $dbloghash = $hash->{dbloghash}; - my $dbconn = $dbloghash->{dbconn}; - my $dbuser = $dbloghash->{dbuser}; - +sub DbRep_firstconnect(@) { + my ($string) = @_; + my ($name,$opt,$prop,$fret) = split("\\|", $string); + my $hash = $defs{$name}; + my $to = "120"; + my $dbloghash = $hash->{dbloghash}; + my $dbconn = $dbloghash->{dbconn}; + my $dbuser = $dbloghash->{dbuser}; + RemoveInternalTimer($hash, "DbRep_firstconnect"); return if(IsDisabled($name)); + if ($init_done == 1) { + if (AttrVal($name, "fastStart", 0) && $prop eq "onBoot" ) { + $hash->{LASTCMD} = "initial database connect stopped due to attribute 'fastStart'"; + return; + } + # DB Struktur aus DbLog Instanz übernehmen + $hash->{HELPER}{DBREPCOL}{COLSET} = $dbloghash->{HELPER}{COLSET}; + $hash->{HELPER}{DBREPCOL}{DEVICECOL} = $dbloghash->{HELPER}{DEVICECOL}; + $hash->{HELPER}{DBREPCOL}{EVENTCOL} = $dbloghash->{HELPER}{EVENTCOL}; + $hash->{HELPER}{DBREPCOL}{READINGCOL} = $dbloghash->{HELPER}{READINGCOL}; + $hash->{HELPER}{DBREPCOL}{TYPECOL} = $dbloghash->{HELPER}{TYPECOL}; + $hash->{HELPER}{DBREPCOL}{UNITCOL} = $dbloghash->{HELPER}{UNITCOL}; + $hash->{HELPER}{DBREPCOL}{VALUECOL} = $dbloghash->{HELPER}{VALUECOL}; + + # DB Strukturelemente abrufen Log3 ($name, 3, "DbRep $name - Connectiontest to database $dbconn with user $dbuser") if($hash->{LASTCMD} ne "minTimestamp"); - $hash->{HELPER}{RUNNING_PID} = BlockingCall("DbRep_getMinTs", "$name", "DbRep_getMinTsDone", $to, "DbRep_getMinTsAborted", $hash); + $hash->{HELPER}{RUNNING_PID} = BlockingCall("DbRep_getInitData", "$name|$opt|$prop|$fret", "DbRep_getInitDataDone", $to, "DbRep_getInitDataAborted", $hash); $hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057 } else { - InternalTimer(time+1, "DbRep_firstconnect", $hash, 0); + InternalTimer(time+1, "DbRep_firstconnect", "$name|$opt|$prop|$fret", 0); } return; @@ -1354,8 +1388,9 @@ return; #################################################################################################### # den ältesten Datensatz (Timestamp) in der DB bestimmen #################################################################################################### -sub DbRep_getMinTs($) { - my ($name) = @_; +sub DbRep_getInitData($) { + my ($string) = @_; + my ($name,$opt,$prop,$fret) = split("\\|", $string); my $hash = $defs{$name}; my $dbloghash = $hash->{dbloghash}; my $dbconn = $dbloghash->{dbconn}; @@ -1379,8 +1414,6 @@ sub DbRep_getMinTs($) { my $st = [gettimeofday]; eval { $mints = $dbh->selectrow_array("SELECT min(TIMESTAMP) FROM history;"); }; - # eval { $mints = $dbh->selectrow_array("select TIMESTAMP from history limit 1;"); }; - # eval { $mints = $dbh->selectrow_array("select TIMESTAMP from history order by TIMESTAMP limit 1;"); }; $dbh->disconnect; @@ -1392,58 +1425,63 @@ sub DbRep_getMinTs($) { # Background-Laufzeit ermitteln my $brt = tv_interval($bst); - $rt = $rt.",".$brt; + $rt = $rt.",".$brt; + no warnings 'uninitialized'; - return "$name|$mints|$rt|0"; +return "$name|$mints|$rt|0|$opt|$prop|$fret"; } #################################################################################################### # Auswertungsroutine den ältesten Datensatz (Timestamp) in der DB bestimmen #################################################################################################### -sub DbRep_getMinTsDone($) { - my ($string) = @_; - my @a = split("\\|",$string); - my $hash = $defs{$a[0]}; - my $name = $hash->{NAME}; - my $mints = decode_base64($a[1]); - my $bt = $a[2]; - my ($rt,$brt) = split(",", $bt); - my $err = $a[3]?decode_base64($a[3]):undef; +sub DbRep_getInitDataDone($) { + my ($string) = @_; + my @a = split("\\|",$string); + my $hash = $defs{$a[0]}; + my $name = $hash->{NAME}; + my $mints = decode_base64($a[1]); + my $bt = $a[2]; + my ($rt,$brt) = split(",", $bt); + my $err = $a[3]?decode_base64($a[3]):undef; + my $opt = $a[4]; + my $prop = $a[5]; + my $fret = \&{$a[6]} if($a[6]); my $dblogdevice = $hash->{HELPER}{DBLOGDEVICE}; $hash->{dbloghash} = $defs{$dblogdevice}; my $dbconn = $hash->{dbloghash}{dbconn}; - if ($err) { + if ($err) { readingsBeginUpdate($hash); ReadingsBulkUpdateValue ($hash, "errortext", $err); ReadingsBulkUpdateValue ($hash, "state", "disconnected"); readingsEndUpdate($hash, 1); delete($hash->{HELPER}{RUNNING_PID}); Log3 ($name, 2, "DbRep $name - DB connect failed. Make sure credentials of database $hash->{DATABASE} are valid and database is reachable."); - return; + + } else { + my $state = ($hash->{LASTCMD} eq "minTimestamp")?"done":"connected"; + $state = "invalid timestamp \"$mints\" found in database - please delete it" if($mints =~ /^0000-00-00.*$/); + + readingsBeginUpdate($hash); + ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints) if($hash->{LASTCMD} eq "minTimestamp"); + ReadingsBulkUpdateTimeState($hash,$brt,$rt,$state); + readingsEndUpdate($hash, 1); + + Log3 ($name, 3, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} ne "minTimestamp"); + + $hash->{HELPER}{MINTS} = $mints; } - my $state = ($hash->{LASTCMD} eq "minTimestamp")?"done":"connected"; - $state = "invalid timestamp \"$mints\" found in database - please delete it" if($mints =~ /^0000-00-00.*$/); - - readingsBeginUpdate($hash); - ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints) if($hash->{LASTCMD} eq "minTimestamp"); - ReadingsBulkUpdateTimeState($hash,$brt,$rt,$state); - readingsEndUpdate($hash, 1); - - Log3 ($name, 4, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} ne "minTimestamp"); - - $hash->{HELPER}{MINTS} = $mints; - delete($hash->{HELPER}{RUNNING_PID}); - -return; + +return if(!$fret); +return &$fret($hash,$opt,$prop); } #################################################################################################### # Abbruchroutine den ältesten Datensatz (Timestamp) in der DB bestimmen #################################################################################################### -sub DbRep_getMinTsAborted(@) { +sub DbRep_getInitDataAborted(@) { my ($hash,$cause) = @_; my $name = $hash->{NAME}; @@ -1552,6 +1590,16 @@ sub DbRep_Main($$;$) { BlockingKill($hash->{HELPER}{RUNNING_PID}); } + # initiale Datenermittlung wie minimal Timestamp, Datenbankstrukturen, ... + if(!$hash->{HELPER}{MINTS} or !$hash->{HELPER}{DBREPCOL}{COLSET}) { + my $dbname = $hash->{DATABASE}; + Log3 ($name, 3, "DbRep $name - get initial structure information of database \"$dbname\", remaining attempts: ".$hash->{HELPER}{IDRETRIES}); + $prop = $prop?$prop:''; + DbRep_firstconnect("$name|$opt|$prop|DbRep_Main") if($hash->{HELPER}{IDRETRIES} > 0); + $hash->{HELPER}{IDRETRIES}--; + return; + } + ReadingsSingleUpdateValue ($hash, "state", "running", 1); # only for this block because of warnings if details of readings are not set @@ -2570,6 +2618,7 @@ sub count_DoParse($) { my $dblogname = $dbloghash->{NAME}; my $dbpassword = $attr{"sec$dblogname"}{secret}; my $ced = AttrVal($name,"countEntriesDetail",0); + my $vf = AttrVal($name,"valueFilter",""); my ($dbh,$sql,$sth,$err); # Background-Startzeit @@ -4278,7 +4327,7 @@ sub change_Push($) { } #################################################################################################### -# nichtblockierendes DB deviceRename / readingRename +# nichtblockierendes DB changeValue (Field VALUE) #################################################################################################### sub changeval_Push($) { my ($string) = @_; @@ -4537,7 +4586,6 @@ sub fetchrows_DoParse($) { my $limit = AttrVal($name, "limit", 1000); my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0; my $fetchroute = AttrVal($name, "fetchRoute", "descent"); - my $valfilter = AttrVal($name, "valueFilter", undef); # nur Anzeige von Datensätzen die "valueFilter" enthalten $fetchroute = ($fetchroute eq "descent")?"DESC":"ASC"; my ($err,$dbh,$sth,$sql,$rowlist,$nrows); @@ -4579,16 +4627,6 @@ sub fetchrows_DoParse($) { no warnings 'uninitialized'; my @row_array = map { $_->[0]."_ESC_".$_->[1]."_ESC_".($_->[2] =~ s/ /_ESC_/r)."_ESC_".$_->[3]."_ESC_".$_->[4]."\n" } @{$sth->fetchall_arrayref()}; - - # eventuell gesetzten Datensatz-Filter anwenden - if($valfilter) { - my @fiarr; - foreach my $row (@row_array) { - next if($row !~ /$valfilter/); - push @fiarr,$row; - } - @row_array = @fiarr; - } use warnings; $nrows = $#row_array+1; # Anzahl der Ergebniselemente @@ -4649,7 +4687,7 @@ sub fetchrows_ParseDone($) { my @row_array = split("\\|", $rowlist); s/_E#S#C_/\|/g for @row_array; # escaped Pipe return to "|" - Log3 ($name, 5, "DbRep $name - row_array decoded: @row_array"); + Log3 ($name, 5, "DbRep $name - row_array decoded:\n @row_array"); # Readingaufbereitung readingsBeginUpdate($hash); @@ -8069,9 +8107,10 @@ return; #################################################################################################### sub DbRep_createSelectSql($$$$$$$$) { my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_; - my $name = $hash->{NAME}; - my $dbmodel = $hash->{dbloghash}{MODEL}; - my $sql; + my $name = $hash->{NAME}; + my $dbmodel = $hash->{dbloghash}{MODEL}; + my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter + my ($sql,$vf); my $tnfull = 0; my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$device,$reading); @@ -8080,6 +8119,14 @@ sub DbRep_createSelectSql($$$$$$$$) { $tnfull = 1; } + if(defined $valfilter) { + if ($dbmodel eq "POSTGRESQL") { + $vf = "VALUE ~ '$valfilter' AND "; + } else { + $vf = "VALUE REGEXP '$valfilter' AND "; + } + } + $sql = "SELECT $selspec FROM $table where "; # included devices $sql .= "DEVICE LIKE '$idevs' AND " if($idanz <= 1 && $idevs !~ m(^%$) && $idevs =~ m(\%)); @@ -8097,13 +8144,16 @@ sub DbRep_createSelectSql($$$$$$$$) { $sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); $sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); $sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); + # add valueFilter + $sql .= $vf if(defined $vf); + # Timestamp Filter if (($tf && $tn)) { $sql .= "TIMESTAMP >= $tf AND TIMESTAMP ".($tnfull?"<=":"<")." $tn "; } else { if ($dbmodel eq "POSTGRESQL") { $sql .= "true "; } else { - $sql .= "1 "; + $sql .= "1 "; } } $sql .= "$addon;"; @@ -8118,7 +8168,8 @@ sub DbRep_createUpdateSql($$$$$$$$) { my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_; my $name = $hash->{NAME}; my $dbmodel = $hash->{dbloghash}{MODEL}; - my $sql; + my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter + my ($sql,$vf); my $tnfull = 0; my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$device,$reading); @@ -8126,6 +8177,14 @@ sub DbRep_createUpdateSql($$$$$$$$) { if($tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) { $tnfull = 1; } + + if(defined $valfilter) { + if ($dbmodel eq "POSTGRESQL") { + $vf = "VALUE ~ '$valfilter' AND "; + } else { + $vf = "VALUE REGEXP '$valfilter' AND "; + } + } $sql = "UPDATE $table SET $selspec AND "; # included devices @@ -8144,6 +8203,9 @@ sub DbRep_createUpdateSql($$$$$$$$) { $sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); $sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); $sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); + # add valueFilter + $sql .= $vf if(defined $vf); + # Timestamp Filter if (($tf && $tn)) { $sql .= "TIMESTAMP >= $tf AND TIMESTAMP ".($tnfull?"<=":"<")." $tn "; } else { @@ -8165,7 +8227,8 @@ sub DbRep_createDeleteSql($$$$$$$) { my ($hash,$table,$device,$reading,$tf,$tn,$addon) = @_; my $name = $hash->{NAME}; my $dbmodel = $hash->{dbloghash}{MODEL}; - my $sql; + my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter + my ($sql,$vf); my $tnfull = 0; if($table eq "current") { @@ -8179,6 +8242,14 @@ sub DbRep_createDeleteSql($$$$$$$) { $tnfull = 1; } + if(defined $valfilter) { + if ($dbmodel eq "POSTGRESQL") { + $vf = "VALUE ~ '$valfilter' AND "; + } else { + $vf = "VALUE REGEXP '$valfilter' AND "; + } + } + $sql = "delete FROM $table where "; # included devices $sql .= "DEVICE LIKE '$idevs' AND " if($idanz <= 1 && $idevs !~ m(^%$) && $idevs =~ m(\%)); @@ -8196,6 +8267,9 @@ sub DbRep_createDeleteSql($$$$$$$) { $sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); $sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); $sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); + # add valueFilter + $sql .= $vf if(defined $vf); + # Timestamp Filter if ($tf && $tn) { $sql .= "TIMESTAMP >= '$tf' AND TIMESTAMP ".($tnfull?"<=":"<")." '$tn' $addon;"; } else { @@ -10042,6 +10116,24 @@ return; avgam_day_totalpac
# <creation function>_<aggregation>_<original reading>
+
+ + Summarized the relevant attributes to control this function are:

+ + +
+
+ +
  • cancelDump - stops a running database dump.

  • @@ -10092,11 +10184,12 @@ return;
    @@ -10122,11 +10215,12 @@ return;
    @@ -10155,7 +10249,8 @@ return; allowDeletion : unlock the delete function device : include or exclude <device> from selection - reading : include or exclude <reading> from selection time.* : a number of attributes to limit selection by time + reading : include or exclude <reading> from selection + time.* : a number of attributes to limit selection by time executeBeforeProc : execute a FHEM command (or perl-routine) before start of delEntries executeAfterProc : execute a FHEM command (or perl-routine) after delEntries is finished @@ -10231,6 +10326,25 @@ return; 2017-11-25_23-58-09__eg.az.fridge_Pwr__power 51.73
    +
    + + Summarized the relevant attributes to control this function are:

    + +
    @@ -10263,7 +10377,7 @@ return; The difference will be generated from the first available dataset (VALUE-Field) to the last available dataset between the specified time linits/aggregation, in which a balanced difference value of the previous aggregation period will be transfered to the following aggregation period in case this period contains a value.
    - An possible counter overrun (restart with value "0") will be considered (compare attribute "diffAccept").

    + A possible counter overrun (restart with value "0") will be considered (compare attribute "diffAccept").

    If only one dataset will be found within the evalution period, the difference can be calculated only in combination with the balanced difference of the previous aggregation period. In this case a logical inaccuracy according the assignment of the difference to the particular aggregation period @@ -10294,6 +10408,25 @@ return; diff_day_totalpac
    # <creation function>_<aggregation>_<original reading>
    +
    + + Summarized the relevant attributes to control this function are:

    + + +
    +
    +
    @@ -10530,14 +10663,16 @@ return;
    @@ -10583,13 +10718,13 @@ return;
    @@ -10676,6 +10811,22 @@ return; max_day_totalpac
    # <creation function>_<aggregation>_<original reading>
    +
    + + Summarized the relevant attributes to control this function are:

    + + +
  • minValue [display | writeToDB] @@ -10700,6 +10851,22 @@ return; min_day_totalpac
    # <creation function>_<aggregation>_<original reading>
    +
    + + Summarized the relevant attributes to control this function are:

    + + +

  • optimizeTables - optimize tables in the connected database (MySQL).
    @@ -10754,14 +10921,15 @@ return;
    @@ -10990,9 +11158,24 @@ return; Example of building a new reading name from the original reading "totalpac":
    sum_day_totalpac
    # <creation function>_<aggregation>_<original reading>
    -


  • + + Summarized the relevant attributes to control this function are:

    + + + +
  • syncStandby <DbLog-Device Standby> - datasets of the connected database (source) are transmitted into another database @@ -11009,17 +11192,18 @@ return; The relevant attributes to control the syncStandby function are:

    - -
    -
    + +

  • tableCurrentFillup - the current-table will be filled u with an extract of the history-table. @@ -11445,6 +11629,15 @@ sub bdump { Filelog.


    + +
  • fastStart - Usually every DbRep device is making a short connect to its database when FHEM is started to + retrieve some important informations and the reading "state" switches to "connected" on success. + If this attrbute is set, the initial database connection is executed not till then the + DbRep device is processing its first command.
    + While the reading "state" is remaining in state "initialized" after FHEM-start. + This approach my be helpful if a lot of DbRep devices are defined. +

  • +
  • fetchMarkDuplicates - Highlighting of multiple occuring datasets in result of "fetchrows" command

  • @@ -11851,10 +12044,11 @@ sub bdump {

    -
  • valueFilter - Regular expression to filter datasets within particular functions. The regex is +
  • valueFilter - Regular expression (REGEXP) to filter datasets within particular functions. The REGEXP is applied to a particular field or to the whole selected dataset (inclusive Device, Reading and so on). - Please consider the explanations within the set-commands.

  • + Please consider the explanations within the set-commands. Further information is available + with command "get <name> versionNotes 4".
    @@ -12069,7 +12263,7 @@ sub bdump { IO::Uncompress::Gunzip
    Blocking (FHEM-Modul)

    - Aus Performancegründen sollten zusätzlich folgender Index erstellt werden:
    + Aus Performancegründen sollte zusätzlich folgender Index erstellt werden:
    CREATE INDEX Report_Idx ON `history` (TIMESTAMP, READING) USING BTREE; @@ -12120,9 +12314,28 @@ sub bdump { +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    +
    + +
  • cancelDump - bricht einen laufenden Datenbankdump ab.

  • @@ -12171,11 +12384,13 @@ sub bdump {
    @@ -12202,11 +12417,14 @@ sub bdump {
    @@ -12222,29 +12440,31 @@ sub bdump { beide Timestamps gesetzt -> gelöscht werden DB-Einträge zwischen diesen Zeitpunkten
    "timeOlderThan" gesetzt -> gelöscht werden DB-Einträge älter als aktuelle Zeit minus "timeOlderThan"
    "timeDiffToNow" gesetzt -> gelöscht werden DB-Einträge ab aktueller Zeit minus "timeDiffToNow" bis jetzt
    - +
    + Aus Sicherheitsgründen muss das Attribut "allowDeletion" gesetzt sein um die Löschfunktion freizuschalten.

    Die zur Steuerung von delEntries relevanten Attribute:

    - -
    -
    + +

    -
  • delSeqDoublets [adviceRemain | adviceDelete | delete] - zeigt bzw. löscht aufeinander folgende identische Datensätze. Dazu wird Device,Reading und Value ausgewertet. Nicht gelöscht werden der erste und der letzte Datensatz @@ -12311,10 +12531,28 @@ sub bdump { 2017-11-25_23-58-09__eg.az.fridge_Pwr__power 51.73
    +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    +
  • -
    -
    +
  • deviceRename <old_name>,<new_name> - benennt den Namen eines Device innerhalb der angeschlossenen Datenbank (Internal DATABASE) um. @@ -12370,9 +12608,27 @@ sub bdump { +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    + +

  • dumpMySQL [clientSide | serverSide] - erstellt einen Dump der angeschlossenen MySQL-Datenbank.
    @@ -12601,17 +12857,20 @@ sub bdump { exportiert werden sollen und vermeidet den "died prematurely" Abbruchfehler.

    Die für diese Funktion relevanten Attribute sind:

    - + +

  • @@ -12659,12 +12918,13 @@ sub bdump {
    @@ -12756,8 +13016,27 @@ sub bdump { Beispiel neuer Readingname gebildet aus dem Originalreading "totalpac":
    max_day_totalpac
    # <Bildungsfunktion>_<Aggregation>_<Originalreading>
    + +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    +
    - +
  • minValue [display | writeToDB] - berechnet den Minimalwert des Datenbankfelds "VALUE" in den Zeitgrenzen @@ -12783,8 +13062,26 @@ sub bdump { Beispiel neuer Readingname gebildet aus dem Originalreading "totalpac":
    min_day_totalpac
    # <Bildungsfunktion>_<Aggregation>_<Originalreading>
    -

  • - + +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    + +
  • optimizeTables - optimiert die Tabellen in der angeschlossenen Datenbank (MySQL).
    Vor und nach der Optimierung kann ein FHEM-Kommando ausgeführt werden. @@ -12838,20 +13135,21 @@ sub bdump { Die für diese Funktion relevanten Attribute sind:

    - -
    + +
    Aus Kompatibilitätsgründen kann der Befehl optional durch die Zusätze "EXCLUDE" bzw. "INCLUDE" ergänzt werden um device/reading Kombinationen von reduceLog auszuschließen bzw. einzuschließen:

    @@ -13063,28 +13361,45 @@ sub bdump {
  • sumValue [display | writeToDB] - Berechnet die Summenwerte des Datenbankfelds "VALUE" in den Zeitgrenzen - (Attribute) "timestamp_begin", "timestamp_end" bzw. "timeDiffToNow / timeOlderThan". - Es muss das auszuwertende Reading im Attribut "reading" - angegeben sein. Diese Funktion ist sinnvoll wenn fortlaufend Wertedifferenzen eines - Readings in die Datenbank geschrieben werden.
    + (Attribute) "timestamp_begin", "timestamp_end" bzw. "timeDiffToNow / timeOlderThan". + Es muss das auszuwertende Reading im Attribut "reading" + angegeben sein. Diese Funktion ist sinnvoll wenn fortlaufend Wertedifferenzen eines + Readings in die Datenbank geschrieben werden.
    - 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.
    - Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet, - wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann. - Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen.
    - Der Timestamp der neuen Readings in der Datenbank wird von der eingestellten Aggregationsperiode - abgeleitet, sofern kein eindeutiger Zeitpunkt des Ergebnisses bestimmt werden kann. - Das Feld "EVENT" wird mit "calculated" gefüllt.

    + 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.
    + Der neue Readingname wird aus einem Präfix und dem originalen Readingnamen gebildet, + wobei der originale Readingname durch das Attribut "readingNameMap" ersetzt werden kann. + Der Präfix setzt sich aus der Bildungsfunktion und der Aggregation zusammen.
    + Der Timestamp der neuen Readings in der Datenbank wird von der eingestellten Aggregationsperiode + abgeleitet, sofern kein eindeutiger Zeitpunkt des Ergebnisses bestimmt werden kann. + Das Feld "EVENT" wird mit "calculated" gefüllt.

    - -
    + +
    + + Zusammengefasst sind die zur Steuerung dieser Funktion relevanten Attribute:

    + + +
    + +

  • syncStandby <DbLog-Device Standby> - Es werden die Datensätze aus der angeschlossenen Datenbank (Quelle) direkt in eine weitere @@ -13101,17 +13416,19 @@ sub bdump { Die zur Steuerung der syncStandby Funktion relevanten Attribute sind:

    - -
    -
    -

  • + +
    + +
  • tableCurrentFillup - Die current-Tabelle wird mit einem Extrakt der history-Tabelle aufgefüllt. Die Attribute zur Zeiteinschränkung bzw. device, reading werden ausgewertet. @@ -13530,7 +13847,16 @@ sub bdump { Zur POSIX Wildcardverwendung siehe auch die Erläuterungen zu Filelog.

    - + + +
  • fastStart - Normalerweise verbindet sich jedes DbRep-Device beim FHEM-Start kurz mit seiner Datenbank um + benötigte Informationen abzurufen und das Reading "state" springt bei Erfolg auf "connected". + Ist dieses Attribut gesetzt, erfolgt die initiale Datenbankverbindung erst dann wenn das + DbRep-Device sein erstes Kommando ausführt.
    + Das Reading "state" verbleibt nach FHEM-Start solange im Status "initialized". Diese Einstellung + kann hilfreich sein wenn viele DbRep-Devices definiert sind. +

  • +
  • fetchMarkDuplicates - Markierung von mehrfach vorkommenden Datensätzen im Ergebnis des "fetchrows" Kommandos

  • @@ -13947,10 +14273,11 @@ sub bdump {
    -
  • valueFilter - Regulärer Ausdruck zur Filterung von Datensätzen innerhalb bestimmter Funktionen. Der - Regex wird auf ein bestimmtes Feld oder den gesamten selektierten Datensatz (inkl. Device, +
  • valueFilter - Regulärer Ausdruck (REGEXP) zur Filterung von Datensätzen innerhalb bestimmter Funktionen. + Der REGEXP wird auf ein bestimmtes Feld oder den gesamten selektierten Datensatz (inkl. Device, Reading usw.) angewendet. - Bitte beachten sie die Erläuterungen zu den entsprechenden Set-Kommandos.

  • + Bitte beachten sie die Erläuterungen zu den entsprechenden Set-Kommandos. Weitere Informationen + sind mit "get <name> versionNotes 4" verfügbar.