2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-26 10:34:52 +00:00

93_DbLog:V3.8.4, cover userCommands, avoid crash (forum:#83973)

git-svn-id: https://svn.fhem.de/fhem/trunk@16108 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2018-02-07 20:59:56 +00:00
parent 035a14d4d8
commit 86adaae4ac
2 changed files with 211 additions and 178 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.
- bugfix: 93_DbLog:V3.8.4, cover userCommands, avoid crash (forum:#83973)
- feature: 51_MOBILEALERTS: Added directionInt for MA10660 - feature: 51_MOBILEALERTS: Added directionInt for MA10660
- changed: 50_MOBILEALERTSGW/51_MOBILEALERTS: Migrate to readingsDelete - changed: 50_MOBILEALERTSGW/51_MOBILEALERTS: Migrate to readingsDelete
- new: 98_freezemon: initial check-in - new: 98_freezemon: initial check-in

View File

@ -16,6 +16,7 @@
############################################################################################################################################ ############################################################################################################################################
# Versions History done by DS_Starter & DeeSPe: # Versions History done by DS_Starter & DeeSPe:
# #
# 3.8.4 07.02.2018 minor fixes of "$@", code review, eval for userCommand, DbLog_ExecSQL1 (forum:#83973)
# 3.8.3 03.02.2018 call execmemcache only syncInterval/2 if cacheLimit reached and DB is not reachable, fix handling of # 3.8.3 03.02.2018 call execmemcache only syncInterval/2 if cacheLimit reached and DB is not reachable, fix handling of
# "$@" in DbLog_PushAsync # "$@" in DbLog_PushAsync
# 3.8.2 31.01.2018 RaiseError => 1 in DbLog_ConnectPush, DbLog_ConnectNewDBH, configCheck improved # 3.8.2 31.01.2018 RaiseError => 1 in DbLog_ConnectPush, DbLog_ConnectNewDBH, configCheck improved
@ -79,8 +80,8 @@
# 2.16.8 06.05.2017 in valueFN $VALUE and $UNIT can now be set to '' or 0 # 2.16.8 06.05.2017 in valueFN $VALUE and $UNIT can now be set to '' or 0
# 2.16.7 20.04.2017 fix $now at addLog # 2.16.7 20.04.2017 fix $now at addLog
# 2.16.6 18.04.2017 AddLog set lasttime, lastvalue of dev_name, dev_reading # 2.16.6 18.04.2017 AddLog set lasttime, lastvalue of dev_name, dev_reading
# 2.16.5 16.04.2017 checkUsePK changed again, new attribute noSupportPK # 2.16.5 16.04.2017 DbLog_checkUsePK changed again, new attribute noSupportPK
# 2.16.4 15.04.2017 commandref completed, checkUsePK changed (@usepkh = "", @usepkc = "") # 2.16.4 15.04.2017 commandref completed, DbLog_checkUsePK changed (@usepkh = "", @usepkc = "")
# 2.16.3 07.04.2017 evaluate reading in DbLog_AddLog as regular expression # 2.16.3 07.04.2017 evaluate reading in DbLog_AddLog as regular expression
# 2.16.2 06.04.2017 sub DbLog_cutCol for cutting fields to maximum length, return to "$lv = "" if(!$lv);" because # 2.16.2 06.04.2017 sub DbLog_cutCol for cutting fields to maximum length, return to "$lv = "" if(!$lv);" because
# of problems with MinIntervall, DbLogType-Logging in database cycle verbose 5, make $TIMESTAMP # of problems with MinIntervall, DbLogType-Logging in database cycle verbose 5, make $TIMESTAMP
@ -122,14 +123,14 @@
# for SQLite databases # for SQLite databases
# 2.11.1 30.01.2017 output to central logfile enhanced for DbLog_Push # 2.11.1 30.01.2017 output to central logfile enhanced for DbLog_Push
# 2.11 28.01.2017 DbLog_connect substituted by DbLog_connectPush completely # 2.11 28.01.2017 DbLog_connect substituted by DbLog_connectPush completely
# 2.10.8 27.01.2017 setinternalcols delayed at fhem start # 2.10.8 27.01.2017 DbLog_setinternalcols delayed at fhem start
# 2.10.7 25.01.2017 $hash->{HELPER}{COLSET} in setinternalcols, DbLog_Push changed due to # 2.10.7 25.01.2017 $hash->{HELPER}{COLSET} in DbLog_setinternalcols, DbLog_Push changed due to
# issue Turning on AutoCommit failed # issue Turning on AutoCommit failed
# 2.10.6 24.01.2017 DbLog_connect changed "connect_cashed" to "connect", DbLog_Get, chartQuery now uses # 2.10.6 24.01.2017 DbLog_connect changed "connect_cashed" to "connect", DbLog_Get, chartQuery now uses
# DbLog_ConnectNewDBH, Attr asyncMode changed -> delete reading cacheusage reliable if mode was switched # DbLog_ConnectNewDBH, Attr asyncMode changed -> delete reading cacheusage reliable if mode was switched
# 2.10.5 23.01.2017 count, userCommand, deleteOldDays now uses DbLog_ConnectNewDBH # 2.10.5 23.01.2017 count, userCommand, deleteOldDays now uses DbLog_ConnectNewDBH
# DbLog_Push line 1107 changed # DbLog_Push line 1107 changed
# 2.10.4 22.01.2017 new sub setinternalcols, new attributes colEvent, colReading, colValue # 2.10.4 22.01.2017 new sub DbLog_setinternalcols, new attributes colEvent, colReading, colValue
# 2.10.3 21.01.2017 query of cacheEvents changed, attr timeout adjustable # 2.10.3 21.01.2017 query of cacheEvents changed, attr timeout adjustable
# 2.10.2 19.01.2017 ReduceLog now uses DbLog_ConnectNewDBH -> makes start of ReduceLog stable # 2.10.2 19.01.2017 ReduceLog now uses DbLog_ConnectNewDBH -> makes start of ReduceLog stable
# 2.10.1 19.01.2017 commandref edited, cache events don't get lost even if other errors than "db not available" occure # 2.10.1 19.01.2017 commandref edited, cache events don't get lost even if other errors than "db not available" occure
@ -185,7 +186,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.8.3"; my $DbLogVersion = "3.8.4";
my %columns = ("DEVICE" => 64, my %columns = ("DEVICE" => 64,
"TYPE" => 64, "TYPE" => 64,
@ -300,7 +301,7 @@ sub DbLog_Define($@)
} }
# set used COLUMNS # set used COLUMNS
InternalTimer(gettimeofday()+2, "setinternalcols", $hash, 0); InternalTimer(gettimeofday()+2, "DbLog_setinternalcols", $hash, 0);
readingsSingleUpdate($hash, 'state', 'waiting for connection', 1); readingsSingleUpdate($hash, 'state', 'waiting for connection', 1);
DbLog_ConnectPush($hash); DbLog_ConnectPush($hash);
@ -382,7 +383,7 @@ sub DbLog_Attr(@) {
if ($cmd eq "set" && $aVal) { if ($cmd eq "set" && $aVal) {
unless ($aVal =~ /^[0-9]+$/) { return " The Value of $aName is not valid. Use only figures 0-9 !";} unless ($aVal =~ /^[0-9]+$/) { return " The Value of $aName is not valid. Use only figures 0-9 !";}
} }
InternalTimer(gettimeofday()+0.5, "setinternalcols", $hash, 0); InternalTimer(gettimeofday()+0.5, "DbLog_setinternalcols", $hash, 0);
} }
if($aName eq "asyncMode") { if($aName eq "asyncMode") {
@ -570,7 +571,7 @@ sub DbLog_Set($@) {
my $ts = (split(" ",FmtDateTime(gettimeofday()+$a[2])))[1]; my $ts = (split(" ",FmtDateTime(gettimeofday()+$a[2])))[1];
Log3($name, 2, "DbLog $name: Connection closed until $ts ($a[2] seconds)."); Log3($name, 2, "DbLog $name: Connection closed until $ts ($a[2] seconds).");
readingsSingleUpdate($hash, "state", "closed until $ts ($a[2] seconds)", 1); readingsSingleUpdate($hash, "state", "closed until $ts ($a[2] seconds)", 1);
InternalTimer(gettimeofday()+$a[2], "reopen", $hash, 0); InternalTimer(gettimeofday()+$a[2], "DbLog_reopen", $hash, 0);
} }
} }
elsif ($a[1] eq 'rereadcfg') { elsif ($a[1] eq 'rereadcfg') {
@ -739,7 +740,6 @@ sub DbLog_Set($@) {
return; return;
} else { } else {
Log3($name, 4, "DbLog $name: Records count requested."); Log3($name, 4, "DbLog $name: Records count requested.");
my $c = $dbh->selectrow_array('SELECT count(*) FROM history'); my $c = $dbh->selectrow_array('SELECT count(*) FROM history');
readingsSingleUpdate($hash, 'countHistory', $c ,1); readingsSingleUpdate($hash, 'countHistory', $c ,1);
$c = $dbh->selectrow_array('SELECT count(*) FROM current'); $c = $dbh->selectrow_array('SELECT count(*) FROM current');
@ -814,8 +814,16 @@ sub DbLog_Set($@) {
shift(@cmd); shift(@cmd); shift(@cmd); shift(@cmd);
$sql = join(" ",@cmd); $sql = join(" ",@cmd);
readingsSingleUpdate($hash, 'userCommand', $sql, 1); readingsSingleUpdate($hash, 'userCommand', $sql, 1);
$c = $dbh->selectrow_array($sql); $dbh->{RaiseError} = 1;
my $res = (defined($c))?$c:"no result"; $dbh->{PrintError} = 0;
my $error;
eval { $c = $dbh->selectrow_array($sql); };
if($@) {
$error = $@;
Log3($name, 1, "DbLog $name: DBLog_Set - $error");
}
my $res = $error?$error:(defined($c))?$c:"no result";
Log3($name, 4, "DbLog $name: DBLog_Set - userCommand - result: $res"); Log3($name, 4, "DbLog $name: DBLog_Set - userCommand - result: $res");
readingsSingleUpdate($hash, 'userCommandResult', $res ,1); readingsSingleUpdate($hash, 'userCommandResult', $res ,1);
$dbh->disconnect(); $dbh->disconnect();
@ -1377,6 +1385,11 @@ sub DbLog_Log($$) {
my $error = DbLog_Push($hash, $vb4show, @row_array); my $error = DbLog_Push($hash, $vb4show, @row_array);
Log3 $name, 5, "DbLog $name -> DbLog_Push Returncode: $error" if($vb4show); Log3 $name, 5, "DbLog $name -> DbLog_Push Returncode: $error" if($vb4show);
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;
# Notify-Routine Laufzeit ermitteln # Notify-Routine Laufzeit ermitteln
$net = tv_interval($nst); $net = tv_interval($nst);
} }
@ -1424,6 +1437,9 @@ sub DbLog_Push(@) {
} }
} }
$dbh->{RaiseError} = 1;
$dbh->{PrintError} = 0;
my ($useac,$useta) = DbLog_commitMode($hash); my ($useac,$useta) = DbLog_commitMode($hash);
my $ac = ($dbh->{AutoCommit})?"ON":"OFF"; my $ac = ($dbh->{AutoCommit})?"ON":"OFF";
my $tm = ($useta)?"ON":"OFF"; my $tm = ($useta)?"ON":"OFF";
@ -1437,7 +1453,7 @@ sub DbLog_Push(@) {
# 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);
if (!$supk) { if (!$supk) {
($usepkh,$usepkc,$pkh,$pkc) = checkUsePK($hash,$dbh); ($usepkh,$usepkc,$pkh,$pkc) = DbLog_checkUsePK($hash,$dbh);
} else { } else {
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key usage suppressed by attribute noSupportPK"; Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key usage suppressed by attribute noSupportPK";
} }
@ -1667,7 +1683,8 @@ sub DbLog_Push(@) {
if ($errorh) { if ($errorh) {
$error = $errorh; $error = $errorh;
} }
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 1;
$dbh->disconnect if ($nh); $dbh->disconnect if ($nh);
return Encode::encode_utf8($error); return Encode::encode_utf8($error);
@ -1840,7 +1857,7 @@ sub DbLog_PushAsync(@) {
# 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);
if (!$supk) { if (!$supk) {
($usepkh,$usepkc,$pkh,$pkc) = checkUsePK($hash,$dbh); ($usepkh,$usepkc,$pkh,$pkc) = DbLog_checkUsePK($hash,$dbh);
} else { } else {
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key usage suppressed by attribute noSupportPK"; Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key usage suppressed by attribute noSupportPK";
} }
@ -2266,6 +2283,11 @@ sub DbLog_ConnectPush($;$$) {
return 0 if(IsDisabled($name)); return 0 if(IsDisabled($name));
if($init_done != 1) {
InternalTimer(gettimeofday()+5, "DbLog_ConnectPush", $hash, 0);
return;
}
Log3 $hash->{NAME}, 3, "DbLog $name - Creating Push-Handle to database $dbconn with user $dbuser" if(!$get); Log3 $hash->{NAME}, 3, "DbLog $name - Creating Push-Handle to database $dbconn with user $dbuser" if(!$get);
my ($useac,$useta) = DbLog_commitMode($hash); my ($useac,$useta) = DbLog_commitMode($hash);
@ -2279,7 +2301,7 @@ sub DbLog_ConnectPush($;$$) {
} }
if($@) { if($@) {
Log3 $hash->{NAME}, 3, "DbLog $name - Error: $@"; Log3 $hash->{NAME}, 2, "DbLog $name - Error: $@";
} }
if(!$dbhp) { if(!$dbhp) {
@ -2291,11 +2313,14 @@ sub DbLog_ConnectPush($;$$) {
readingsSingleUpdate($hash, "state", $state, $evt); readingsSingleUpdate($hash, "state", $state, $evt);
$hash->{HELPER}{OLDSTATE} = $state; $hash->{HELPER}{OLDSTATE} = $state;
InternalTimer(time+5, 'DbLog_ConnectPush', $hash, 0); InternalTimer(gettimeofday()+5, 'DbLog_ConnectPush', $hash, 0);
Log3 $hash->{NAME}, 4, "DbLog $name - Waiting for database connection"; Log3 $hash->{NAME}, 4, "DbLog $name - Waiting for database connection";
return 0; return 0;
} }
$dbhp->{RaiseError} = 0;
$dbhp->{PrintError} = 1;
Log3 $hash->{NAME}, 3, "DbLog $name - Push-Handle to db $dbconn created" if(!$get); Log3 $hash->{NAME}, 3, "DbLog $name - Push-Handle to db $dbconn created" if(!$get);
Log3 $hash->{NAME}, 3, "DbLog $name - UTF8 support enabled" if($utf8 && $hash->{MODEL} eq "MYSQL" && !$get); Log3 $hash->{NAME}, 3, "DbLog $name - UTF8 support enabled" if($utf8 && $hash->{MODEL} eq "MYSQL" && !$get);
readingsSingleUpdate($hash, 'state', 'connected', 1) if(!$get); readingsSingleUpdate($hash, 'state', 'connected', 1) if(!$get);
@ -2343,6 +2368,8 @@ sub DbLog_ConnectNewDBH($) {
} }
if($dbh) { if($dbh) {
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 1;
return $dbh; return $dbh;
} else { } else {
return 0; return 0;
@ -2384,10 +2411,12 @@ sub DbLog_ExecSQL($$)
sub DbLog_ExecSQL1($$$) sub DbLog_ExecSQL1($$$)
{ {
my ($hash,$dbh,$sql)= @_; my ($hash,$dbh,$sql)= @_;
$dbh->{RaiseError} = 1;
my $sth = $dbh->do($sql); $dbh->{PrintError} = 0;
if(!$sth) { my $sth;
Log3 $hash->{NAME}, 2, "DBLog error: " . $DBI::errstr; eval { $sth = $dbh->do($sql); };
if($@) {
Log3 $hash->{NAME}, 2, "DBLog error: $@";
return 0; return 0;
} }
return $sth; return $sth;
@ -4039,7 +4068,6 @@ sub DbLog_reduceLogNbl($) {
# Server default # Server default
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1 });}; eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1 });};
} }
if ($@) { if ($@) {
my $err = encode_base64($@,""); my $err = encode_base64($@,"");
Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@");
@ -4447,11 +4475,6 @@ sub DbLog_deldaysNbl($) {
# Server default # Server default
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1 });}; eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1 });};
} }
my $ac = ($dbh->{AutoCommit})?"ON":"OFF";
my $tm = ($useta)?"ON":"OFF";
Log3 $hash->{NAME}, 4, "DbLog $name -> AutoCommit mode: $ac, Transaction mode: $tm";
if ($@) { if ($@) {
$error = encode_base64($@,""); $error = encode_base64($@,"");
Log3 ($name, 2, "DbLog $name - Error: $@"); Log3 ($name, 2, "DbLog $name - Error: $@");
@ -4459,6 +4482,10 @@ sub DbLog_deldaysNbl($) {
return "$name|0|0|$error"; return "$name|0|0|$error";
} }
my $ac = ($dbh->{AutoCommit})?"ON":"OFF";
my $tm = ($useta)?"ON":"OFF";
Log3 $hash->{NAME}, 4, "DbLog $name -> AutoCommit mode: $ac, Transaction mode: $tm";
$cmd = "delete from history where TIMESTAMP < "; $cmd = "delete from history where TIMESTAMP < ";
if ($hash->{MODEL} eq 'SQLITE') { if ($hash->{MODEL} eq 'SQLITE') {
$cmd .= "datetime('now', '-$days days')"; $cmd .= "datetime('now', '-$days days')";
@ -4541,6 +4568,162 @@ sub DbLog_deldaysNbl_done($) {
return; return;
} }
################################################################
# benutzte DB-Feldlängen in Helper und Internals setzen
################################################################
sub DbLog_setinternalcols ($){
my ($hash)= @_;
my $name = $hash->{NAME};
$hash->{HELPER}{DEVICECOL} = $columns{DEVICE};
$hash->{HELPER}{TYPECOL} = $columns{TYPE};
$hash->{HELPER}{EVENTCOL} = AttrVal($name, "colEvent", $columns{EVENT});
$hash->{HELPER}{READINGCOL} = AttrVal($name, "colReading", $columns{READING});
$hash->{HELPER}{VALUECOL} = AttrVal($name, "colValue", $columns{VALUE});
$hash->{HELPER}{UNITCOL} = $columns{UNIT};
$hash->{COLUMNS} = "field length used for Device: $hash->{HELPER}{DEVICECOL}, Type: $hash->{HELPER}{TYPECOL}, Event: $hash->{HELPER}{EVENTCOL}, Reading: $hash->{HELPER}{READINGCOL}, Value: $hash->{HELPER}{VALUECOL}, Unit: $hash->{HELPER}{UNITCOL} ";
# Statusbit "Columns sind gesetzt"
$hash->{HELPER}{COLSET} = 1;
return;
}
################################################################
# reopen DB-Connection nach Ablauf set ... reopen [n] seconds
################################################################
sub DbLog_reopen ($){
my ($hash) = @_;
my $name = $hash->{NAME};
my $async = AttrVal($name, "asyncMode", undef);
RemoveInternalTimer($hash, "DbLog_reopen");
if(DbLog_ConnectPush($hash)) {
# Statusbit "Kein Schreiben in DB erlauben" löschen
my $delay = delete $hash->{HELPER}{REOPEN_RUNS};
Log3($name, 2, "DbLog $name: Database connection reopened (it was $delay seconds closed).") if($delay);
readingsSingleUpdate($hash, "state", "reopened", 1);
$hash->{HELPER}{OLDSTATE} = "reopened";
DbLog_execmemcache($hash) if($async);
} else {
InternalTimer(gettimeofday()+30, "DbLog_reopen", $hash, 0);
}
return;
}
################################################################
# check ob primary key genutzt wird
################################################################
sub DbLog_checkUsePK ($$){
my ($hash,$dbh) = @_;
my $name = $hash->{NAME};
my $dbconn = $hash->{dbconn};
my $upkh = 0;
my $upkc = 0;
my (@pkh,@pkc);
my $db = (split("=",(split(";",$dbconn))[0]))[1];
eval {@pkh = $dbh->primary_key( undef, undef, 'history' );};
eval {@pkc = $dbh->primary_key( undef, undef, 'current' );};
my $pkh = (!@pkh || @pkh eq "")?"none":join(",",@pkh);
my $pkc = (!@pkc || @pkc eq "")?"none":join(",",@pkc);
$pkh =~ tr/"//d;
$pkc =~ tr/"//d;
$upkh = 1 if(@pkh && @pkh ne "none");
$upkc = 1 if(@pkc && @pkc ne "none");
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key used in $db.history: $pkh";
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key used in $db.current: $pkc";
return ($upkh,$upkc,$pkh,$pkc);
}
################################################################
# Routine für FHEMWEB Detailanzeige
################################################################
sub DbLog_fhemwebFn($$$$) {
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my $ret;
my $newIdx=1;
while($defs{"SVG_${d}_$newIdx"}) {
$newIdx++;
}
my $name = "SVG_${d}_$newIdx";
$ret .= FW_pH("cmd=define $name SVG $d:templateDB:HISTORY;".
"set $name copyGplotFile&detail=$name",
"<div class=\"dval\">Create SVG plot from DbLog</div>", 0, "dval", 1);
return $ret;
}
################################################################
# Dropdown-Menü cuurent-Tabelle SVG-Editor
################################################################
sub DbLog_sampleDataFn($$$$$) {
my ($dlName, $dlog, $max, $conf, $wName) = @_;
my $desc = "Device:Reading";
my @htmlArr;
my @example;
my @colregs;
my $counter;
my $currentPresent = AttrVal($dlName,'DbLogType','History');
my $dbhf = DbLog_ConnectNewDBH($defs{$dlName});
return if(!$dbhf);
# check presence of table current
# avoids fhem from crash if table 'current' is not present and attr DbLogType is set to /Current/
my $prescurr = eval {$dbhf->selectrow_array("select count(*) from current");} || 0;
Log3($dlName, 5, "DbLog $dlName: Table current present : $prescurr (0 = not present or no content)");
if($currentPresent =~ m/Current|SampleFill/ && $prescurr) {
# Table Current present, use it for sample data
my $query = "select device,reading from current where device <> '' group by device,reading";
my $sth = $dbhf->prepare( $query );
$sth->execute();
while (my @line = $sth->fetchrow_array()) {
$counter++;
push (@example, join (" ",@line)) if($counter <= 8); # show max 8 examples
push (@colregs, "$line[0]:$line[1]"); # push all eventTypes to selection list
}
$dbhf->disconnect();
my $cols = join(",", sort { "\L$a" cmp "\L$b" } @colregs);
$max = 8 if($max > 8);
for(my $r=0; $r < $max; $r++) {
my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4);
my $ret = "";
$ret .= SVG_sel("par_${r}_0", $cols, "$f[0]:$f[1]");
# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented
# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function
# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp
push @htmlArr, $ret;
}
} else {
# Table Current not present, so create an empty input field
push @example, "No sample data due to missing table 'Current'";
$max = 8 if($max > 8);
for(my $r=0; $r < $max; $r++) {
my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4);
my $ret = "";
no warnings 'uninitialized'; # Forum:74690, bug unitialized
$ret .= SVG_txt("par_${r}_0", "", "$f[0]:$f[1]:$f[2]:$f[3]", 20);
use warnings;
# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented
# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function
# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp
push @htmlArr, $ret;
}
}
return ($desc, \@htmlArr, join("<br>", @example));
}
################################################################ ################################################################
# #
# Charting Specific functions start here # Charting Specific functions start here
@ -4831,85 +5014,6 @@ sub chartQuery($@) {
return $jsonstring; return $jsonstring;
} }
#########################
sub DbLog_fhemwebFn($$$$) {
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my $ret;
my $newIdx=1;
while($defs{"SVG_${d}_$newIdx"}) {
$newIdx++;
}
my $name = "SVG_${d}_$newIdx";
$ret .= FW_pH("cmd=define $name SVG $d:templateDB:HISTORY;".
"set $name copyGplotFile&detail=$name",
"<div class=\"dval\">Create SVG plot from DbLog</div>", 0, "dval", 1);
return $ret;
}
sub DbLog_sampleDataFn($$$$$) {
my ($dlName, $dlog, $max, $conf, $wName) = @_;
my $desc = "Device:Reading";
my @htmlArr;
my @example;
my @colregs;
my $counter;
my $currentPresent = AttrVal($dlName,'DbLogType','History');
my $dbhf = DbLog_ConnectNewDBH($defs{$dlName});
return if(!$dbhf);
# check presence of table current
# avoids fhem from crash if table 'current' is not present and attr DbLogType is set to /Current/
my $prescurr = eval {$dbhf->selectrow_array("select count(*) from current");} || 0;
Log3($dlName, 5, "DbLog $dlName: Table current present : $prescurr (0 = not present or no content)");
if($currentPresent =~ m/Current|SampleFill/ && $prescurr) {
# Table Current present, use it for sample data
my $query = "select device,reading from current where device <> '' group by device,reading";
my $sth = $dbhf->prepare( $query );
$sth->execute();
while (my @line = $sth->fetchrow_array()) {
$counter++;
push (@example, join (" ",@line)) if($counter <= 8); # show max 8 examples
push (@colregs, "$line[0]:$line[1]"); # push all eventTypes to selection list
}
$dbhf->disconnect();
my $cols = join(",", sort { "\L$a" cmp "\L$b" } @colregs);
$max = 8 if($max > 8);
for(my $r=0; $r < $max; $r++) {
my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4);
my $ret = "";
$ret .= SVG_sel("par_${r}_0", $cols, "$f[0]:$f[1]");
# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented
# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function
# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp
push @htmlArr, $ret;
}
} else {
# Table Current not present, so create an empty input field
push @example, "No sample data due to missing table 'Current'";
$max = 8 if($max > 8);
for(my $r=0; $r < $max; $r++) {
my @f = split(":", ($dlog->[$r] ? $dlog->[$r] : ":::"), 4);
my $ret = "";
no warnings 'uninitialized'; # Forum:74690, bug unitialized
$ret .= SVG_txt("par_${r}_0", "", "$f[0]:$f[1]:$f[2]:$f[3]", 20);
use warnings;
# $ret .= SVG_txt("par_${r}_2", "", $f[2], 1); # Default not yet implemented
# $ret .= SVG_txt("par_${r}_3", "", $f[3], 3); # Function
# $ret .= SVG_txt("par_${r}_4", "", $f[4], 3); # RegExp
push @htmlArr, $ret;
}
}
return ($desc, \@htmlArr, join("<br>", @example));
}
# #
# get <dbLog> ReadingsVal <device> <reading> <default> # get <dbLog> ReadingsVal <device> <reading> <default>
# get <dbLog> ReadingsTimestamp <device> <reading> <default> # get <dbLog> ReadingsTimestamp <device> <reading> <default>
@ -4938,78 +5042,6 @@ sub dbReadings($@) {
return "Syntax error: $a[1]"; return "Syntax error: $a[1]";
} }
################################################################
# benutzte DB-Feldlängen in Helper und Internals setzen
################################################################
sub setinternalcols ($){
my ($hash)= @_;
my $name = $hash->{NAME};
$hash->{HELPER}{DEVICECOL} = $columns{DEVICE};
$hash->{HELPER}{TYPECOL} = $columns{TYPE};
$hash->{HELPER}{EVENTCOL} = AttrVal($name, "colEvent", $columns{EVENT});
$hash->{HELPER}{READINGCOL} = AttrVal($name, "colReading", $columns{READING});
$hash->{HELPER}{VALUECOL} = AttrVal($name, "colValue", $columns{VALUE});
$hash->{HELPER}{UNITCOL} = $columns{UNIT};
$hash->{COLUMNS} = "field length used for Device: $hash->{HELPER}{DEVICECOL}, Type: $hash->{HELPER}{TYPECOL}, Event: $hash->{HELPER}{EVENTCOL}, Reading: $hash->{HELPER}{READINGCOL}, Value: $hash->{HELPER}{VALUECOL}, Unit: $hash->{HELPER}{UNITCOL} ";
# Statusbit "Columns sind gesetzt"
$hash->{HELPER}{COLSET} = 1;
return;
}
################################################################
# reopen DB-Connection nach Ablauf set ... reopen [n] seconds
################################################################
sub reopen ($){
my ($hash) = @_;
my $name = $hash->{NAME};
my $async = AttrVal($name, "asyncMode", undef);
RemoveInternalTimer($hash, "reopen");
if(DbLog_ConnectPush($hash)) {
# Statusbit "Kein Schreiben in DB erlauben" löschen
my $delay = delete $hash->{HELPER}{REOPEN_RUNS};
Log3($name, 2, "DbLog $name: Database connection reopened (it was $delay seconds closed).") if($delay);
readingsSingleUpdate($hash, "state", "reopened", 1);
$hash->{HELPER}{OLDSTATE} = "reopened";
DbLog_execmemcache($hash) if($async);
} else {
InternalTimer(gettimeofday()+30, "reopen", $hash, 0);
}
return;
}
################################################################
# check ob primary key genutzt wird
################################################################
sub checkUsePK ($$){
my ($hash,$dbh) = @_;
my $name = $hash->{NAME};
my $dbconn = $hash->{dbconn};
my $upkh = 0;
my $upkc = 0;
my (@pkh,@pkc);
my $db = (split("=",(split(";",$dbconn))[0]))[1];
eval {@pkh = $dbh->primary_key( undef, undef, 'history' );};
eval {@pkc = $dbh->primary_key( undef, undef, 'current' );};
my $pkh = (!@pkh || @pkh eq "")?"none":join(",",@pkh);
my $pkc = (!@pkc || @pkc eq "")?"none":join(",",@pkc);
$pkh =~ tr/"//d;
$pkc =~ tr/"//d;
$upkh = 1 if(@pkh && @pkh ne "none");
$upkc = 1 if(@pkc && @pkc ne "none");
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key used in $db.history: $pkh";
Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key used in $db.current: $pkc";
return ($upkh,$upkc,$pkh,$pkc);
}
1; 1;
=pod =pod