From 86adaae4ac1d4e2ce98597dac6d1722cf944c8d6 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Wed, 7 Feb 2018 20:59:56 +0000 Subject: [PATCH] 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 --- fhem/CHANGED | 1 + fhem/FHEM/93_DbLog.pm | 388 +++++++++++++++++++++++------------------- 2 files changed, 211 insertions(+), 178 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index b3b964a55..17fceac94 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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. + - bugfix: 93_DbLog:V3.8.4, cover userCommands, avoid crash (forum:#83973) - feature: 51_MOBILEALERTS: Added directionInt for MA10660 - changed: 50_MOBILEALERTSGW/51_MOBILEALERTS: Migrate to readingsDelete - new: 98_freezemon: initial check-in diff --git a/fhem/FHEM/93_DbLog.pm b/fhem/FHEM/93_DbLog.pm index f6e821400..5648f2ae7 100644 --- a/fhem/FHEM/93_DbLog.pm +++ b/fhem/FHEM/93_DbLog.pm @@ -16,6 +16,7 @@ ############################################################################################################################################ # 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 # "$@" in DbLog_PushAsync # 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.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.5 16.04.2017 checkUsePK changed again, new attribute noSupportPK -# 2.16.4 15.04.2017 commandref completed, checkUsePK changed (@usepkh = "", @usepkc = "") +# 2.16.5 16.04.2017 DbLog_checkUsePK changed again, new attribute noSupportPK +# 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.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 @@ -122,14 +123,14 @@ # for SQLite databases # 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.10.8 27.01.2017 setinternalcols delayed at fhem start -# 2.10.7 25.01.2017 $hash->{HELPER}{COLSET} in setinternalcols, DbLog_Push changed due to +# 2.10.8 27.01.2017 DbLog_setinternalcols delayed at fhem start +# 2.10.7 25.01.2017 $hash->{HELPER}{COLSET} in DbLog_setinternalcols, DbLog_Push changed due to # issue Turning on AutoCommit failed # 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 # 2.10.5 23.01.2017 count, userCommand, deleteOldDays now uses DbLog_ConnectNewDBH # 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.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 @@ -185,7 +186,7 @@ use Blocking; use Time::HiRes qw(gettimeofday tv_interval); use Encode qw(encode_utf8); -my $DbLogVersion = "3.8.3"; +my $DbLogVersion = "3.8.4"; my %columns = ("DEVICE" => 64, "TYPE" => 64, @@ -300,7 +301,7 @@ sub DbLog_Define($@) } # set used COLUMNS - InternalTimer(gettimeofday()+2, "setinternalcols", $hash, 0); + InternalTimer(gettimeofday()+2, "DbLog_setinternalcols", $hash, 0); readingsSingleUpdate($hash, 'state', 'waiting for connection', 1); DbLog_ConnectPush($hash); @@ -382,7 +383,7 @@ sub DbLog_Attr(@) { if ($cmd eq "set" && $aVal) { 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") { @@ -570,7 +571,7 @@ sub DbLog_Set($@) { my $ts = (split(" ",FmtDateTime(gettimeofday()+$a[2])))[1]; Log3($name, 2, "DbLog $name: Connection closed until $ts ($a[2] seconds)."); 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') { @@ -739,7 +740,6 @@ sub DbLog_Set($@) { return; } else { Log3($name, 4, "DbLog $name: Records count requested."); - my $c = $dbh->selectrow_array('SELECT count(*) FROM history'); readingsSingleUpdate($hash, 'countHistory', $c ,1); $c = $dbh->selectrow_array('SELECT count(*) FROM current'); @@ -814,8 +814,16 @@ sub DbLog_Set($@) { shift(@cmd); shift(@cmd); $sql = join(" ",@cmd); readingsSingleUpdate($hash, 'userCommand', $sql, 1); - $c = $dbh->selectrow_array($sql); - my $res = (defined($c))?$c:"no result"; + $dbh->{RaiseError} = 1; + $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"); readingsSingleUpdate($hash, 'userCommandResult', $res ,1); $dbh->disconnect(); @@ -1376,6 +1384,11 @@ sub DbLog_Log($$) { return if($hash->{HELPER}{REOPEN_RUNS}); my $error = DbLog_Push($hash, $vb4show, @row_array); 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 $net = tv_interval($nst); @@ -1424,6 +1437,9 @@ sub DbLog_Push(@) { } } + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 0; + my ($useac,$useta) = DbLog_commitMode($hash); my $ac = ($dbh->{AutoCommit})?"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 my ($usepkh,$usepkc,$pkh,$pkc); if (!$supk) { - ($usepkh,$usepkc,$pkh,$pkc) = checkUsePK($hash,$dbh); + ($usepkh,$usepkc,$pkh,$pkc) = DbLog_checkUsePK($hash,$dbh); } else { Log3 $hash->{NAME}, 5, "DbLog $name -> Primary Key usage suppressed by attribute noSupportPK"; } @@ -1667,7 +1683,8 @@ sub DbLog_Push(@) { if ($errorh) { $error = $errorh; } - + $dbh->{RaiseError} = 0; + $dbh->{PrintError} = 1; $dbh->disconnect if ($nh); 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 my ($usepkh,$usepkc,$pkh,$pkc); if (!$supk) { - ($usepkh,$usepkc,$pkh,$pkc) = checkUsePK($hash,$dbh); + ($usepkh,$usepkc,$pkh,$pkc) = DbLog_checkUsePK($hash,$dbh); } else { 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)); + 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); my ($useac,$useta) = DbLog_commitMode($hash); @@ -2279,7 +2301,7 @@ sub DbLog_ConnectPush($;$$) { } if($@) { - Log3 $hash->{NAME}, 3, "DbLog $name - Error: $@"; + Log3 $hash->{NAME}, 2, "DbLog $name - Error: $@"; } if(!$dbhp) { @@ -2291,10 +2313,13 @@ sub DbLog_ConnectPush($;$$) { readingsSingleUpdate($hash, "state", $state, $evt); $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"; 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 - UTF8 support enabled" if($utf8 && $hash->{MODEL} eq "MYSQL" && !$get); @@ -2343,6 +2368,8 @@ sub DbLog_ConnectNewDBH($) { } if($dbh) { + $dbh->{RaiseError} = 0; + $dbh->{PrintError} = 1; return $dbh; } else { return 0; @@ -2384,10 +2411,12 @@ sub DbLog_ExecSQL($$) sub DbLog_ExecSQL1($$$) { my ($hash,$dbh,$sql)= @_; - - my $sth = $dbh->do($sql); - if(!$sth) { - Log3 $hash->{NAME}, 2, "DBLog error: " . $DBI::errstr; + $dbh->{RaiseError} = 1; + $dbh->{PrintError} = 0; + my $sth; + eval { $sth = $dbh->do($sql); }; + if($@) { + Log3 $hash->{NAME}, 2, "DBLog error: $@"; return 0; } return $sth; @@ -4039,7 +4068,6 @@ sub DbLog_reduceLogNbl($) { # Server default eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1 });}; } - if ($@) { my $err = encode_base64($@,""); Log3 ($name, 2, "DbLog $name -> DbLog_reduceLogNbl - $@"); @@ -4447,11 +4475,6 @@ sub DbLog_deldaysNbl($) { # Server default 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 ($@) { $error = encode_base64($@,""); Log3 ($name, 2, "DbLog $name - Error: $@"); @@ -4459,6 +4482,10 @@ sub DbLog_deldaysNbl($) { 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 < "; if ($hash->{MODEL} eq 'SQLITE') { $cmd .= "datetime('now', '-$days days')"; @@ -4541,6 +4568,162 @@ sub DbLog_deldaysNbl_done($) { 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", + "
Create SVG plot from DbLog
", 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("
", @example)); +} + ################################################################ # # Charting Specific functions start here @@ -4831,85 +5014,6 @@ sub chartQuery($@) { 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", - "
Create SVG plot from DbLog
", 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("
", @example)); -} - # # get ReadingsVal # get ReadingsTimestamp @@ -4938,78 +5042,6 @@ sub dbReadings($@) { 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; =pod