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:
parent
035a14d4d8
commit
86adaae4ac
@ -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
|
||||||
|
@ -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();
|
||||||
@ -1376,6 +1384,11 @@ sub DbLog_Log($$) {
|
|||||||
return if($hash->{HELPER}{REOPEN_RUNS});
|
return if($hash->{HELPER}{REOPEN_RUNS});
|
||||||
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,10 +2313,13 @@ 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);
|
||||||
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user