mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
93_DbRep: contrib 8.8.0
git-svn-id: https://svn.fhem.de/fhem/trunk@17690 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
f6c93a301c
commit
52bd5b9717
@ -57,6 +57,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
our %DbRep_vNotesIntern = (
|
our %DbRep_vNotesIntern = (
|
||||||
|
"8.8.0" => "05.11.2018 first connect routine switched to DbRep_Main, get COLSET from DBLOG-instance",
|
||||||
"8.7.0" => "04.11.2018 attribute valueFilter applied to functions based on 'SELECT', 'UPDATE', 'DELETE' and 'valueFilter' generally applied to field 'VALUE' ",
|
"8.7.0" => "04.11.2018 attribute valueFilter applied to functions based on 'SELECT', 'UPDATE', 'DELETE' and 'valueFilter' generally applied to field 'VALUE' ",
|
||||||
"8.6.0" => "29.10.2018 reduceLog use attributes device/reading (can be overwritten by set-options) ",
|
"8.6.0" => "29.10.2018 reduceLog use attributes device/reading (can be overwritten by set-options) ",
|
||||||
"8.5.0" => "27.10.2018 versionNotes revised, EXCLUDE of reading/device possible (DbRep_specsForSql changed) ",
|
"8.5.0" => "27.10.2018 versionNotes revised, EXCLUDE of reading/device possible (DbRep_specsForSql changed) ",
|
||||||
@ -64,11 +65,11 @@ our %DbRep_vNotesIntern = (
|
|||||||
"versionNotes changed to support en/de, get dbValue as textfield-long ",
|
"versionNotes changed to support en/de, get dbValue as textfield-long ",
|
||||||
"8.3.0" => "17.10.2018 reduceLog from DbLog integrated into DbRep, textField-long as default for sqlCmd, both attributes timeOlderThan and timeDiffToNow can be set at same time",
|
"8.3.0" => "17.10.2018 reduceLog from DbLog integrated into DbRep, textField-long as default for sqlCmd, both attributes timeOlderThan and timeDiffToNow can be set at same time",
|
||||||
"8.2.3" => "07.10.2018 check availability of DbLog-device at definition time of DbRep-device ",
|
"8.2.3" => "07.10.2018 check availability of DbLog-device at definition time of DbRep-device ",
|
||||||
"8.2.2" => "07.10.2018 DbRep_getMinTs changed, fix don't get the real min timestamp in rare cases ",
|
"8.2.2" => "07.10.2018 DbRep_getInitData changed, fix don't get the real min timestamp in rare cases ",
|
||||||
"8.2.1" => "07.10.2018 \$hash->{dbloghash}{HELPER}{REOPEN_RUNS_UNTIL} contains time until DB is closed ",
|
"8.2.1" => "07.10.2018 \$hash->{dbloghash}{HELPER}{REOPEN_RUNS_UNTIL} contains time until DB is closed ",
|
||||||
"8.2.0" => "05.10.2018 direct help for attributes ",
|
"8.2.0" => "05.10.2018 direct help for attributes ",
|
||||||
"8.1.0" => "02.10.2018 new get versionNotes command ",
|
"8.1.0" => "02.10.2018 new get versionNotes command ",
|
||||||
"8.0.1" => "20.09.2018 DbRep_getMinTs improved",
|
"8.0.1" => "20.09.2018 DbRep_getInitData improved",
|
||||||
"8.0.0" => "11.09.2018 get filesize in DbRep_WriteToDumpFile corrected, restoreMySQL for clientSide dumps, minor fixes ",
|
"8.0.0" => "11.09.2018 get filesize in DbRep_WriteToDumpFile corrected, restoreMySQL for clientSide dumps, minor fixes ",
|
||||||
"7.20.0" => "04.09.2018 deviceRename can operate a Device name with blank, e.g. 'current balance' as old device name ",
|
"7.20.0" => "04.09.2018 deviceRename can operate a Device name with blank, e.g. 'current balance' as old device name ",
|
||||||
"7.19.0" => "25.08.2018 attribute 'valueFilter' to filter datasets in fetchrows ",
|
"7.19.0" => "25.08.2018 attribute 'valueFilter' to filter datasets in fetchrows ",
|
||||||
@ -368,8 +369,9 @@ sub DbRep_Define($@) {
|
|||||||
$hash->{ROLE} = AttrVal($name, "role", "Client");
|
$hash->{ROLE} = AttrVal($name, "role", "Client");
|
||||||
$hash->{MODEL} = $hash->{ROLE};
|
$hash->{MODEL} = $hash->{ROLE};
|
||||||
$hash->{HELPER}{DBLOGDEVICE} = $a[2];
|
$hash->{HELPER}{DBLOGDEVICE} = $a[2];
|
||||||
|
$hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen
|
||||||
$hash->{VERSION} = (reverse sort(keys %DbRep_vNotesIntern))[0];
|
$hash->{VERSION} = (reverse sort(keys %DbRep_vNotesIntern))[0];
|
||||||
$hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten
|
$hash->{NOTIFYDEV} = "global,".$name; # nur Events dieser Devices an DbRep_Notify weiterleiten
|
||||||
my $dbconn = $defs{$a[2]}{dbconn};
|
my $dbconn = $defs{$a[2]}{dbconn};
|
||||||
$hash->{DATABASE} = (split(/;|=/, $dbconn))[1];
|
$hash->{DATABASE} = (split(/;|=/, $dbconn))[1];
|
||||||
$hash->{UTF8} = defined($defs{$a[2]}{UTF8})?$defs{$a[2]}{UTF8}:0;
|
$hash->{UTF8} = defined($defs{$a[2]}{UTF8})?$defs{$a[2]}{UTF8}:0;
|
||||||
@ -381,7 +383,7 @@ sub DbRep_Define($@) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveInternalTimer($hash);
|
RemoveInternalTimer($hash);
|
||||||
InternalTimer(gettimeofday()+int(rand(45)), 'DbRep_firstconnect', $hash, 0);
|
InternalTimer(gettimeofday()+int(rand(45)), 'DbRep_firstconnect', "$name|||", 0);
|
||||||
|
|
||||||
Log3 ($name, 4, "DbRep $name - initialized");
|
Log3 ($name, 4, "DbRep $name - initialized");
|
||||||
ReadingsSingleUpdateValue ($hash, 'state', 'initialized', 1);
|
ReadingsSingleUpdateValue ($hash, 'state', 'initialized', 1);
|
||||||
@ -862,7 +864,7 @@ sub DbRep_Get($@) {
|
|||||||
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
|
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
|
||||||
return "The operation \"$opt\" isn't available with database type $dbmodel" if ($dbmodel ne 'MYSQL');
|
return "The operation \"$opt\" isn't available with database type $dbmodel" if ($dbmodel ne 'MYSQL');
|
||||||
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
||||||
DbRep_delread($hash); # Readings löschen die nicht in der Ausnahmeliste (Attr readingPreventFromDel) stehen
|
DbRep_delread($hash); # Readings löschen die nicht in der Ausnahmeliste (Attr readingPreventFromDel) stehen
|
||||||
$hash->{HELPER}{RUNNING_PID} = BlockingCall("dbmeta_DoParse", "$name|$opt", "dbmeta_ParseDone", $to, "DbRep_ParseAborted", $hash);
|
$hash->{HELPER}{RUNNING_PID} = BlockingCall("dbmeta_DoParse", "$name|$opt", "dbmeta_ParseDone", $to, "DbRep_ParseAborted", $hash);
|
||||||
|
|
||||||
} elsif ($opt eq "svrinfo") {
|
} elsif ($opt eq "svrinfo") {
|
||||||
@ -884,7 +886,9 @@ sub DbRep_Get($@) {
|
|||||||
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
|
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
|
||||||
DbRep_delread($hash);
|
DbRep_delread($hash);
|
||||||
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
||||||
DbRep_firstconnect($hash);
|
$hash->{HELPER}{IDRETRIES} = 3; # Anzahl wie oft versucht wird initiale Daten zu holen
|
||||||
|
$prop = $prop?$prop:'';
|
||||||
|
DbRep_firstconnect("$name|$opt|$prop|");
|
||||||
|
|
||||||
} elsif ($opt =~ /dbValue/) {
|
} elsif ($opt =~ /dbValue/) {
|
||||||
return "get \"$opt\" needs at least an argument" if ( @a < 3 );
|
return "get \"$opt\" needs at least an argument" if ( @a < 3 );
|
||||||
@ -1044,7 +1048,7 @@ sub DbRep_Attr($$$$) {
|
|||||||
ReadingsSingleUpdateValue ($hash, "state", $val, 1);
|
ReadingsSingleUpdateValue ($hash, "state", $val, 1);
|
||||||
if ($do == 0) {
|
if ($do == 0) {
|
||||||
RemoveInternalTimer($hash);
|
RemoveInternalTimer($hash);
|
||||||
InternalTimer(time+5, 'DbRep_firstconnect', $hash, 0);
|
InternalTimer(time+5, 'DbRep_firstconnect', "$name|||", 0);
|
||||||
} else {
|
} else {
|
||||||
my $dbh = $hash->{DBH};
|
my $dbh = $hash->{DBH};
|
||||||
$dbh->disconnect() if($dbh);
|
$dbh->disconnect() if($dbh);
|
||||||
@ -1342,22 +1346,33 @@ return undef;
|
|||||||
# Verbindung zur DB aufbauen und den Timestamp des ältesten
|
# Verbindung zur DB aufbauen und den Timestamp des ältesten
|
||||||
# Datensatzes ermitteln
|
# Datensatzes ermitteln
|
||||||
###################################################################################
|
###################################################################################
|
||||||
sub DbRep_firstconnect($) {
|
sub DbRep_firstconnect(@) {
|
||||||
my ($hash) = @_;
|
my ($string) = @_;
|
||||||
my $name = $hash->{NAME};
|
my ($name,$opt,$prop,$fret) = split("\\|", $string);
|
||||||
my $to = "120";
|
my $hash = $defs{$name};
|
||||||
my $dbloghash = $hash->{dbloghash};
|
my $to = "120";
|
||||||
my $dbconn = $dbloghash->{dbconn};
|
my $dbloghash = $hash->{dbloghash};
|
||||||
my $dbuser = $dbloghash->{dbuser};
|
my $dbconn = $dbloghash->{dbconn};
|
||||||
|
my $dbuser = $dbloghash->{dbuser};
|
||||||
|
|
||||||
RemoveInternalTimer($hash, "DbRep_firstconnect");
|
RemoveInternalTimer($hash, "DbRep_firstconnect");
|
||||||
return if(IsDisabled($name));
|
return if(IsDisabled($name));
|
||||||
if ($init_done == 1) {
|
if ($init_done == 1) {
|
||||||
|
# DB Struktur aus DbLog Instanz übernehmen
|
||||||
|
$hash->{HELPER}{DBREPCOL}{COLSET} = $dbloghash->{HELPER}{COLSET};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{DEVICECOL} = $dbloghash->{HELPER}{DEVICECOL};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{EVENTCOL} = $dbloghash->{HELPER}{EVENTCOL};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{READINGCOL} = $dbloghash->{HELPER}{READINGCOL};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{TYPECOL} = $dbloghash->{HELPER}{TYPECOL};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{UNITCOL} = $dbloghash->{HELPER}{UNITCOL};
|
||||||
|
$hash->{HELPER}{DBREPCOL}{VALUECOL} = $dbloghash->{HELPER}{VALUECOL};
|
||||||
|
|
||||||
|
# DB Strukturelemente abrufen
|
||||||
Log3 ($name, 3, "DbRep $name - Connectiontest to database $dbconn with user $dbuser") if($hash->{LASTCMD} ne "minTimestamp");
|
Log3 ($name, 3, "DbRep $name - Connectiontest to database $dbconn with user $dbuser") if($hash->{LASTCMD} ne "minTimestamp");
|
||||||
$hash->{HELPER}{RUNNING_PID} = BlockingCall("DbRep_getMinTs", "$name", "DbRep_getMinTsDone", $to, "DbRep_getMinTsAborted", $hash);
|
$hash->{HELPER}{RUNNING_PID} = BlockingCall("DbRep_getInitData", "$name|$opt|$prop|$fret", "DbRep_getInitDataDone", $to, "DbRep_getInitDataAborted", $hash);
|
||||||
$hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057
|
$hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057
|
||||||
} else {
|
} else {
|
||||||
InternalTimer(time+1, "DbRep_firstconnect", $hash, 0);
|
InternalTimer(time+1, "DbRep_firstconnect", "$name|$opt|$prop|$fret", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1366,8 +1381,9 @@ return;
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# den ältesten Datensatz (Timestamp) in der DB bestimmen
|
# den ältesten Datensatz (Timestamp) in der DB bestimmen
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
sub DbRep_getMinTs($) {
|
sub DbRep_getInitData($) {
|
||||||
my ($name) = @_;
|
my ($string) = @_;
|
||||||
|
my ($name,$opt,$prop,$fret) = split("\\|", $string);
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my $dbloghash = $hash->{dbloghash};
|
my $dbloghash = $hash->{dbloghash};
|
||||||
my $dbconn = $dbloghash->{dbconn};
|
my $dbconn = $dbloghash->{dbconn};
|
||||||
@ -1391,8 +1407,6 @@ sub DbRep_getMinTs($) {
|
|||||||
my $st = [gettimeofday];
|
my $st = [gettimeofday];
|
||||||
|
|
||||||
eval { $mints = $dbh->selectrow_array("SELECT min(TIMESTAMP) FROM history;"); };
|
eval { $mints = $dbh->selectrow_array("SELECT min(TIMESTAMP) FROM history;"); };
|
||||||
# eval { $mints = $dbh->selectrow_array("select TIMESTAMP from history limit 1;"); };
|
|
||||||
# eval { $mints = $dbh->selectrow_array("select TIMESTAMP from history order by TIMESTAMP limit 1;"); };
|
|
||||||
|
|
||||||
$dbh->disconnect;
|
$dbh->disconnect;
|
||||||
|
|
||||||
@ -1404,58 +1418,63 @@ sub DbRep_getMinTs($) {
|
|||||||
# Background-Laufzeit ermitteln
|
# Background-Laufzeit ermitteln
|
||||||
my $brt = tv_interval($bst);
|
my $brt = tv_interval($bst);
|
||||||
|
|
||||||
$rt = $rt.",".$brt;
|
$rt = $rt.",".$brt;
|
||||||
|
no warnings 'uninitialized';
|
||||||
|
|
||||||
return "$name|$mints|$rt|0";
|
return "$name|$mints|$rt|0|$opt|$prop|$fret";
|
||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Auswertungsroutine den ältesten Datensatz (Timestamp) in der DB bestimmen
|
# Auswertungsroutine den ältesten Datensatz (Timestamp) in der DB bestimmen
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
sub DbRep_getMinTsDone($) {
|
sub DbRep_getInitDataDone($) {
|
||||||
my ($string) = @_;
|
my ($string) = @_;
|
||||||
my @a = split("\\|",$string);
|
my @a = split("\\|",$string);
|
||||||
my $hash = $defs{$a[0]};
|
my $hash = $defs{$a[0]};
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $mints = decode_base64($a[1]);
|
my $mints = decode_base64($a[1]);
|
||||||
my $bt = $a[2];
|
my $bt = $a[2];
|
||||||
my ($rt,$brt) = split(",", $bt);
|
my ($rt,$brt) = split(",", $bt);
|
||||||
my $err = $a[3]?decode_base64($a[3]):undef;
|
my $err = $a[3]?decode_base64($a[3]):undef;
|
||||||
|
my $opt = $a[4];
|
||||||
|
my $prop = $a[5];
|
||||||
|
my $fret = \&{$a[6]} if($a[6]);
|
||||||
my $dblogdevice = $hash->{HELPER}{DBLOGDEVICE};
|
my $dblogdevice = $hash->{HELPER}{DBLOGDEVICE};
|
||||||
$hash->{dbloghash} = $defs{$dblogdevice};
|
$hash->{dbloghash} = $defs{$dblogdevice};
|
||||||
my $dbconn = $hash->{dbloghash}{dbconn};
|
my $dbconn = $hash->{dbloghash}{dbconn};
|
||||||
|
|
||||||
if ($err) {
|
if ($err) {
|
||||||
readingsBeginUpdate($hash);
|
readingsBeginUpdate($hash);
|
||||||
ReadingsBulkUpdateValue ($hash, "errortext", $err);
|
ReadingsBulkUpdateValue ($hash, "errortext", $err);
|
||||||
ReadingsBulkUpdateValue ($hash, "state", "disconnected");
|
ReadingsBulkUpdateValue ($hash, "state", "disconnected");
|
||||||
readingsEndUpdate($hash, 1);
|
readingsEndUpdate($hash, 1);
|
||||||
delete($hash->{HELPER}{RUNNING_PID});
|
delete($hash->{HELPER}{RUNNING_PID});
|
||||||
Log3 ($name, 2, "DbRep $name - DB connect failed. Make sure credentials of database $hash->{DATABASE} are valid and database is reachable.");
|
Log3 ($name, 2, "DbRep $name - DB connect failed. Make sure credentials of database $hash->{DATABASE} are valid and database is reachable.");
|
||||||
return;
|
|
||||||
|
} else {
|
||||||
|
my $state = ($hash->{LASTCMD} eq "minTimestamp")?"done":"connected";
|
||||||
|
$state = "invalid timestamp \"$mints\" found in database - please delete it" if($mints =~ /^0000-00-00.*$/);
|
||||||
|
|
||||||
|
readingsBeginUpdate($hash);
|
||||||
|
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints) if($hash->{LASTCMD} eq "minTimestamp");
|
||||||
|
ReadingsBulkUpdateTimeState($hash,$brt,$rt,$state);
|
||||||
|
readingsEndUpdate($hash, 1);
|
||||||
|
|
||||||
|
Log3 ($name, 3, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} ne "minTimestamp");
|
||||||
|
|
||||||
|
$hash->{HELPER}{MINTS} = $mints;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $state = ($hash->{LASTCMD} eq "minTimestamp")?"done":"connected";
|
|
||||||
$state = "invalid timestamp \"$mints\" found in database - please delete it" if($mints =~ /^0000-00-00.*$/);
|
|
||||||
|
|
||||||
readingsBeginUpdate($hash);
|
|
||||||
ReadingsBulkUpdateValue ($hash, "timestamp_oldest_dataset", $mints) if($hash->{LASTCMD} eq "minTimestamp");
|
|
||||||
ReadingsBulkUpdateTimeState($hash,$brt,$rt,$state);
|
|
||||||
readingsEndUpdate($hash, 1);
|
|
||||||
|
|
||||||
Log3 ($name, 4, "DbRep $name - Connectiontest to db $dbconn successful") if($hash->{LASTCMD} ne "minTimestamp");
|
|
||||||
|
|
||||||
$hash->{HELPER}{MINTS} = $mints;
|
|
||||||
|
|
||||||
delete($hash->{HELPER}{RUNNING_PID});
|
delete($hash->{HELPER}{RUNNING_PID});
|
||||||
|
|
||||||
return;
|
return if(!$fret);
|
||||||
|
return &$fret($hash,$opt,$prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Abbruchroutine den ältesten Datensatz (Timestamp) in der DB bestimmen
|
# Abbruchroutine den ältesten Datensatz (Timestamp) in der DB bestimmen
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
sub DbRep_getMinTsAborted(@) {
|
sub DbRep_getInitDataAborted(@) {
|
||||||
my ($hash,$cause) = @_;
|
my ($hash,$cause) = @_;
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
@ -1564,6 +1583,16 @@ sub DbRep_Main($$;$) {
|
|||||||
BlockingKill($hash->{HELPER}{RUNNING_PID});
|
BlockingKill($hash->{HELPER}{RUNNING_PID});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# initiale Datenermittlung wie minimal Timestamp, Datenbankstrukturen, ...
|
||||||
|
if(!$hash->{HELPER}{MINTS} or !$hash->{HELPER}{DBREPCOL}{COLSET}) {
|
||||||
|
my $dbname = $hash->{DATABASE};
|
||||||
|
Log3 ($name, 3, "DbRep $name - get initial structure information of database \"$dbname\", remaining attempts: ".$hash->{HELPER}{IDRETRIES});
|
||||||
|
$prop = $prop?$prop:'';
|
||||||
|
DbRep_firstconnect("$name|$opt|$prop|DbRep_Main") if($hash->{HELPER}{IDRETRIES} > 0);
|
||||||
|
$hash->{HELPER}{IDRETRIES}--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
ReadingsSingleUpdateValue ($hash, "state", "running", 1);
|
||||||
|
|
||||||
# only for this block because of warnings if details of readings are not set
|
# only for this block because of warnings if details of readings are not set
|
||||||
|
Loading…
x
Reference in New Issue
Block a user