93_DbLog: V3.6.2, new attribute "exportCacheAppend", minor fix in Log verbose 5

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@15851 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2018-01-11 22:22:44 +00:00
parent c47c926817
commit e71fe53d77
2 changed files with 88 additions and 33 deletions

View File

@ -1,5 +1,7 @@
# 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.
- change: 93_DbLog: V3.6.2, new attribute "exportCacheAppend", minor fix in
Log verbose 5
- bugfix: 82_LGTV_WebOS: fix wrong paired reading and more - bugfix: 82_LGTV_WebOS: fix wrong paired reading and more
- change: 98_dewpoint: Use NOTIFYDEV - change: 98_dewpoint: Use NOTIFYDEV
- bugfix: 93_DbRep: syntax error if perl version < 5.20 - bugfix: 93_DbRep: syntax error if perl version < 5.20

View File

@ -10,12 +10,15 @@
# #
# reduceLog() created by Claudiu Schuster (rapster) # reduceLog() created by Claudiu Schuster (rapster)
# #
# redesigned 2016/2017 by DS_Starter with credits by # redesigned 2016-2018 by DS_Starter with credits by
# JoeAllb, DeeSpe # JoeAllb, DeeSpe
# #
############################################################################################################################################ ############################################################################################################################################
# Versions History done by DS_Starter & DeeSPe: # Versions History done by DS_Starter & DeeSPe:
# #
# 3.6.2 07.01.2018 new attribute "exportCacheAppend", change function exportCache to respect attr exportCacheAppend,
# fix DbLog_execmemcache verbose 5 message
# 3.6.1 04.01.2018 change SQLite PRAGMA from NORMAL to FULL (Default Value of SQLite)
# 3.6.0 20.12.2017 check global blockingCallMax in configCheck, configCheck now available for SQLITE # 3.6.0 20.12.2017 check global blockingCallMax in configCheck, configCheck now available for SQLITE
# 3.5.0 18.12.2017 importCacheFile, addCacheLine uses useCharfilter option, filter only $event by charfilter # 3.5.0 18.12.2017 importCacheFile, addCacheLine uses useCharfilter option, filter only $event by charfilter
# 3.4.0 10.12.2017 avoid print out {RUNNING_PID} by "list device" # 3.4.0 10.12.2017 avoid print out {RUNNING_PID} by "list device"
@ -172,7 +175,7 @@ use Blocking;
use Time::HiRes qw(gettimeofday tv_interval); use Time::HiRes qw(gettimeofday tv_interval);
use Encode qw(encode_utf8); use Encode qw(encode_utf8);
my $DbLogVersion = "3.6.0"; my $DbLogVersion = "3.6.2";
my %columns = ("DEVICE" => 64, my %columns = ("DEVICE" => 64,
"TYPE" => 64, "TYPE" => 64,
@ -209,6 +212,7 @@ sub DbLog_Initialize($)
"verbose4Devs ". "verbose4Devs ".
"excludeDevs ". "excludeDevs ".
"expimpdir ". "expimpdir ".
"exportCacheAppend:1,0 ".
"syncInterval ". "syncInterval ".
"noNotifyDev:1,0 ". "noNotifyDev:1,0 ".
"showproctime:1,0 ". "showproctime:1,0 ".
@ -610,29 +614,45 @@ sub DbLog_Set($@) {
elsif ($a[1] eq 'exportCache') { elsif ($a[1] eq 'exportCache') {
my $cln; my $cln;
my $crows = 0; my $crows = 0;
my $outfile; my ($out,$outfile,$error);
my $now = strftime('%Y-%m-%d_%H-%M-%S',localtime); my $now = strftime('%Y-%m-%d_%H-%M-%S',localtime);
# return wenn "reopen" mit Ablaufzeit gestartet ist oder disabled, nicht im asynch-Mode # return wenn "reopen" mit Ablaufzeit gestartet ist oder disabled, nicht im asynch-Mode
return if(IsDisabled($name) || $hash->{HELPER}{REOPEN_RUNS}); return if(IsDisabled($name) || $hash->{HELPER}{REOPEN_RUNS});
return if (!AttrVal($name, "asyncMode", undef)); return if(!AttrVal($name, "asyncMode", undef));
if(@logs && AttrVal($name, "exportCacheAppend", 0)) {
# exportiertes Cachefile existiert und es soll an das neueste angehängt werden
$outfile = $dir.pop(@logs);
$out = ">>$outfile";
} else {
$outfile = $dir."cache_".$name."_".$now; $outfile = $dir."cache_".$name."_".$now;
$out = ">$outfile";
if (open(FH, ">$outfile")) { }
if(open(FH, $out)) {
binmode (FH); binmode (FH);
} else { } else {
readingsSingleUpdate($hash, "lastCachefile", $outfile." - Error - ".$!, 1); readingsSingleUpdate($hash, "lastCachefile", $outfile." - Error - ".$!, 1);
return "could not open ".$outfile.": ".$!; $error = "could not open ".$outfile.": ".$!;
} }
if(!$error) {
foreach my $key (sort(keys%{$hash->{cache}{".memcache"}})) { foreach my $key (sort(keys%{$hash->{cache}{".memcache"}})) {
$cln = $hash->{cache}{".memcache"}{$key}."\n"; $cln = $hash->{cache}{".memcache"}{$key}."\n";
print FH $cln ; print FH $cln ;
$crows++; $crows++;
} }
close(FH); close(FH);
readingsSingleUpdate($hash, "lastCachefile", $outfile." export successful", 1); readingsSingleUpdate($hash, "lastCachefile", $outfile." (".$crows." cache rows exported)", 1);
readingsSingleUpdate($hash, "state", $crows." cache rows exported to ".$outfile, 1); }
# readingsSingleUpdate($hash, "state", $crows." cache rows exported to ".$outfile, 1);
my $state = $error?$error:(IsDisabled($name))?"disabled":"connected";
my $evt = ($state eq $hash->{HELPER}{OLDSTATE})?0:1;
readingsSingleUpdate($hash, "state", $state, $evt);
$hash->{HELPER}{OLDSTATE} = $state;
Log3($name, 3, "DbLog $name: $crows cache rows exported to $outfile."); Log3($name, 3, "DbLog $name: $crows cache rows exported to $outfile.");
if ($a[-1] =~ m/^purgecache/i) { if ($a[-1] =~ m/^purgecache/i) {
@ -1709,7 +1729,7 @@ sub DbLog_execmemcache ($) {
Log3 $name, 4, "DbLog $name -> DbLogType is: $DbLogType"; Log3 $name, 4, "DbLog $name -> DbLogType is: $DbLogType";
foreach my $key (sort(keys%{$hash->{cache}{".memcache"}})) { foreach my $key (sort(keys%{$hash->{cache}{".memcache"}})) {
Log3 $hash->{NAME}, 5, 'DbLog $name -> MemCache contains: $hash->{cache}{".memcache"}{$key}'; Log3 $hash->{NAME}, 5, "DbLog $name -> MemCache contains: ".$hash->{cache}{".memcache"}{$key};
push(@row_array, delete($hash->{cache}{".memcache"}{$key})); push(@row_array, delete($hash->{cache}{".memcache"}{$key}));
} }
@ -2258,7 +2278,9 @@ sub DbLog_ConnectPush($;$$) {
if ($hash->{MODEL} eq "SQLITE") { if ($hash->{MODEL} eq "SQLITE") {
$dbhp->do("PRAGMA temp_store=MEMORY"); $dbhp->do("PRAGMA temp_store=MEMORY");
$dbhp->do("PRAGMA synchronous=NORMAL"); $dbhp->do("PRAGMA synchronous=FULL"); # For maximum reliability and for robustness against database corruption,
# SQLite should always be run with its default synchronous setting of FULL.
# https://sqlite.org/howtocorrupt.html
$dbhp->do("PRAGMA journal_mode=WAL"); $dbhp->do("PRAGMA journal_mode=WAL");
$dbhp->do("PRAGMA cache_size=4000"); $dbhp->do("PRAGMA cache_size=4000");
} }
@ -3134,7 +3156,7 @@ sub DbLog_configcheck($) {
@six_rdg = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Search_Idx' and Column_name='READING'"); @six_rdg = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Search_Idx' and Column_name='READING'");
@six_tsp = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Search_Idx' and Column_name='TIMESTAMP'"); @six_tsp = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Search_Idx' and Column_name='TIMESTAMP'");
if (@six_dev && @six_rdg && @six_tsp) { if (@six_dev && @six_rdg && @six_tsp) {
$check .= "Index 'Search_Idx' exists and contains the recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>"; $check .= "Index 'Search_Idx' exists and contains recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!@six_dev); $check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!@six_dev);
@ -3161,7 +3183,7 @@ sub DbLog_configcheck($) {
$idef_rdg = 1 if($idef =~ /reading/); $idef_rdg = 1 if($idef =~ /reading/);
$idef_tsp = 1 if($idef =~ /timestamp/); $idef_tsp = 1 if($idef =~ /timestamp/);
if ($idef_dev && $idef_rdg && $idef_tsp) { if ($idef_dev && $idef_rdg && $idef_tsp) {
$check .= "Index 'Search_Idx' exists and contains the recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>"; $check .= "Index 'Search_Idx' exists and contains recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!$idef_dev); $check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!$idef_dev);
@ -3188,7 +3210,7 @@ sub DbLog_configcheck($) {
$idef_rdg = 1 if(lc($idef) =~ /reading/); $idef_rdg = 1 if(lc($idef) =~ /reading/);
$idef_tsp = 1 if(lc($idef) =~ /timestamp/); $idef_tsp = 1 if(lc($idef) =~ /timestamp/);
if ($idef_dev && $idef_rdg && $idef_tsp) { if ($idef_dev && $idef_rdg && $idef_tsp) {
$check .= "Index 'Search_Idx' exists and contains the recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>"; $check .= "Index 'Search_Idx' exists and contains recommended fields 'DEVICE', 'READING', 'TIMESTAMP'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!$idef_dev); $check .= "Index 'Search_Idx' exists but doesn't contain recommended field 'DEVICE'. <br>" if (!$idef_dev);
@ -3238,7 +3260,7 @@ sub DbLog_configcheck($) {
@dix_tsp = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Report_Idx' and Column_name='TIMESTAMP'"); @dix_tsp = DbLog_sqlget($hash,"SHOW INDEX FROM history where Key_name='Report_Idx' and Column_name='TIMESTAMP'");
if (@dix_rdg && @dix_tsp) { if (@dix_rdg && @dix_tsp) {
$check .= "You use at least one DbRep-device assigned to $name. "; $check .= "You use at least one DbRep-device assigned to $name. ";
$check .= "Index 'Report_Idx' exists and contains the recommended fields 'TIMESTAMP', 'READING'. <br>"; $check .= "Index 'Report_Idx' exists and contains recommended fields 'TIMESTAMP', 'READING'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "You use at least one DbRep-device assigned to $name. "; $check .= "You use at least one DbRep-device assigned to $name. ";
@ -3264,7 +3286,7 @@ sub DbLog_configcheck($) {
$irep_rdg = 1 if($irep =~ /reading/); $irep_rdg = 1 if($irep =~ /reading/);
$irep_tsp = 1 if($irep =~ /timestamp/); $irep_tsp = 1 if($irep =~ /timestamp/);
if ($irep_rdg && $irep_tsp) { if ($irep_rdg && $irep_tsp) {
$check .= "Index 'Report_Idx' exists and contains the recommended fields 'TIMESTAMP', 'READING'. <br>"; $check .= "Index 'Report_Idx' exists and contains recommended fields 'TIMESTAMP', 'READING'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "Index 'Report_Idx' exists but doesn't contain recommended field 'READING'. <br>" if (!$irep_rdg); $check .= "Index 'Report_Idx' exists but doesn't contain recommended field 'READING'. <br>" if (!$irep_rdg);
@ -3289,7 +3311,7 @@ sub DbLog_configcheck($) {
$irep_rdg = 1 if(lc($irep) =~ /reading/); $irep_rdg = 1 if(lc($irep) =~ /reading/);
$irep_tsp = 1 if(lc($irep) =~ /timestamp/); $irep_tsp = 1 if(lc($irep) =~ /timestamp/);
if ($irep_rdg && $irep_tsp) { if ($irep_rdg && $irep_tsp) {
$check .= "Index 'Report_Idx' exists and contains the recommended fields 'TIMESTAMP', 'READING'. <br>"; $check .= "Index 'Report_Idx' exists and contains recommended fields 'TIMESTAMP', 'READING'. <br>";
$rec = "settings o.k."; $rec = "settings o.k.";
} else { } else {
$check .= "Index 'Report_Idx' exists but doesn't contain recommended field 'READING'. <br>" if (!$irep_rdg); $check .= "Index 'Report_Idx' exists but doesn't contain recommended field 'READING'. <br>" if (!$irep_rdg);
@ -4716,7 +4738,6 @@ sub DbLog_fhemwebFn($$$$) {
$ret .= FW_pH("cmd=define $name SVG $d:templateDB:HISTORY;". $ret .= FW_pH("cmd=define $name SVG $d:templateDB:HISTORY;".
"set $name copyGplotFile&detail=$name", "set $name copyGplotFile&detail=$name",
"<div class=\"dval\">Create SVG plot from DbLog</div>", 0, "dval", 1); "<div class=\"dval\">Create SVG plot from DbLog</div>", 0, "dval", 1);
return $ret; return $ret;
} }
@ -5134,7 +5155,10 @@ sub checkUsePK ($$){
present timestmp, e.g. "cache_LogDB_2017-03-23_22-13-55". <br> present timestmp, e.g. "cache_LogDB_2017-03-23_22-13-55". <br>
There are two options possible, "nopurge" respectively "purgeCache". The option determines whether the cache content There are two options possible, "nopurge" respectively "purgeCache". The option determines whether the cache content
will be deleted after export or not. will be deleted after export or not.
Using option "nopurge" (default) the cache content will be preserved. </ul><br> Using option "nopurge" (default) the cache content will be preserved. <br>
The <a href="#DbLogattr">attribute</a> "exportCacheAppend" defines, whether every export process creates a new export file
(default) or the cache content is appended to an existing (newest) export file.
</ul><br>
<code>set &lt;name&gt; importCachefile &lt;file&gt; </code><br><br> <code>set &lt;name&gt; importCachefile &lt;file&gt; </code><br><br>
<ul>Imports an textfile into the database which has been written by the "exportCache" function. <ul>Imports an textfile into the database which has been written by the "exportCache" function.
@ -5644,6 +5668,19 @@ sub checkUsePK ($$){
</ul> </ul>
<br> <br>
<ul><b>exportCacheAppend</b>
<ul>
<code>
attr &lt;device&gt; exportCacheAppend [1|0]
</code><br>
If set, the export of cache ("set &lt;device&gt; exportCache") appends the content to the newest available
export file. If there is no exististing export file, it will be new created. <br>
If the attribute not set, every export process creates a new export file . (default)<br/>
</ul>
</ul>
<br>
<ul><b>noNotifyDev</b> <ul><b>noNotifyDev</b>
<ul> <ul>
<code> <code>
@ -6069,11 +6106,14 @@ sub checkUsePK ($$){
<code>set &lt;name&gt; exportCache [nopurge | purgeCache] </code><br><br> <code>set &lt;name&gt; exportCache [nopurge | purgeCache] </code><br><br>
<ul>Wenn DbLog im asynchronen Modus betrieben wird, kann der Cache mit diesem Befehl in ein Textfile geschrieben <ul>Wenn DbLog im asynchronen Modus betrieben wird, kann der Cache mit diesem Befehl in ein Textfile geschrieben
werden. Das File wird per Default in dem Verzeichnis (global->modpath)/log/ erstellt. Das Zielverzeichnis kann mit werden. Das File wird per Default in dem Verzeichnis (global->modpath)/log/ erstellt. Das Zielverzeichnis kann mit
dem <a href="#DbLogattr">Attribut</a> expimpdir geändert werden. <br> dem <a href="#DbLogattr">Attribut</a> "expimpdir" geändert werden. <br>
Der Name des Files wird automatisch generiert und enthält den Präfix "cache_", gefolgt von dem DbLog-Devicenamen und Der Name des Files wird automatisch generiert und enthält den Präfix "cache_", gefolgt von dem DbLog-Devicenamen und
dem aktuellen Zeitstempel, z.B. "cache_LogDB_2017-03-23_22-13-55". <br> dem aktuellen Zeitstempel, z.B. "cache_LogDB_2017-03-23_22-13-55". <br>
Mit den Optionen "nopurge" bzw. "purgeCache" wird festgelegt, ob der Cacheinhalt nach dem Export gelöscht werden Mit den Optionen "nopurge" bzw. "purgeCache" wird festgelegt, ob der Cacheinhalt nach dem Export gelöscht werden
soll oder nicht. Mit "nopurge" (default) bleibt der Cacheinhalt erhalten. </ul><br> soll oder nicht. Mit "nopurge" (default) bleibt der Cacheinhalt erhalten. <br>
Das <a href="#DbLogattr">Attribut</a> "exportCacheAppend" bestimmt dabei, ob mit jedem Exportvorgang ein neues Exportfile
angelegt wird (default) oder der Cacheinhalt an das bestehende (neueste) Exportfile angehängt wird.
</ul><br>
<code>set &lt;name&gt; importCachefile &lt;file&gt; </code><br><br> <code>set &lt;name&gt; importCachefile &lt;file&gt; </code><br><br>
<ul>Importiert ein mit "exportCache" geschriebenes File in die Datenbank. <ul>Importiert ein mit "exportCache" geschriebenes File in die Datenbank.
@ -6638,13 +6678,15 @@ sub checkUsePK ($$){
</ul> </ul>
<br> <br>
<ul><b>shutdownWait</b> <ul><b>exportCacheAppend</b>
<ul> <ul>
<code> <code>
attr &lt;device&gt; shutdownWait <n> attr &lt;device&gt; exportCacheAppend [1|0]
</code><br> </code><br>
FHEM wartet während des shutdowns fuer n Sekunden, um die Datenbank korrekt zu beenden<br/> Wenn gesetzt, wird beim Export des Cache ("set &lt;device&gt; exportCache") der Cacheinhalt an das neueste bereits vorhandene
Exportfile angehängt. Ist noch kein Exportfile vorhanden, wird es neu angelegt. <br>
Ist das Attribut nicht gesetzt, wird bei jedem Exportvorgang ein neues Exportfile angelegt. (default)<br/>
</ul> </ul>
</ul> </ul>
<br> <br>
@ -6671,6 +6713,17 @@ sub checkUsePK ($$){
</ul> </ul>
<br> <br>
<ul><b>shutdownWait</b>
<ul>
<code>
attr &lt;device&gt; shutdownWait <n>
</code><br>
FHEM wartet während des shutdowns fuer n Sekunden, um die Datenbank korrekt zu beenden<br/>
</ul>
</ul>
<br>
<ul><b>showproctime</b> <ul><b>showproctime</b>
<ul> <ul>
<code>attr &lt;device&gt; showproctime [1|0] <code>attr &lt;device&gt; showproctime [1|0]