From 640b1e69bc54b70374d720eea2602d0aaa7fbb3e Mon Sep 17 00:00:00 2001 From: nasseeder1 <> Date: Mon, 26 Sep 2016 22:20:08 +0000 Subject: [PATCH] 93_DbRep: new function importFromFile to import data from file (CSV format) git-svn-id: https://svn.fhem.de/fhem/trunk@12216 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/93_DbRep.pm | 304 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 265 insertions(+), 41 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 3aac6ced6..c9a18d7c5 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # 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. + - feature: 93_DbRep: new function importFromFile to import data from file + (CSV format) - bugfix: 73_ElectricityCalculator: Crash due wrong hash pointer assignment - feature: new optional arguments for device creation in copy command - bugfix: 49_SSCam: bugfix of get presets, get patrols of zoom-cams diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm index 18fb86f52..cab5ab510 100644 --- a/fhem/FHEM/93_DbRep.pm +++ b/fhem/FHEM/93_DbRep.pm @@ -37,13 +37,14 @@ ########################################################################################################### # Versions History: # +# 3.9 26.09.2016 new function importFromFile to import data from file (CSV format) # 3.8 16.09.2016 new attr readingPreventFromDel to prevent readings from deletion # when a new operation starts # 3.7.3 11.09.2016 changed format of diffValue-reading if no value was selected # 3.7.2 04.09.2016 problem in diffValue fixed if if no value was selected # 3.7.1 31.08.2016 Reading "errortext" added, commandref continued, exportToFile changed, # diffValue changed to fix wrong timestamp if error occur -# 3.7 30.08.2016 exportToFile added +# 3.7 30.08.2016 exportToFile added (exports data to file (CSV format) # 3.6 29.08.2016 plausibility checks of database column character length # 3.5.2 21.08.2016 fit to new commandref style # 3.5.1 20.08.2016 commandref continued @@ -211,6 +212,7 @@ sub DbRep_Set($@) { "averageValue:noArg ". "delEntries:noArg ". "exportToFile:noArg ". + "importFromFile:noArg ". "maxValue:noArg ". "fetchrows:noArg ". "diffValue:noArg ". @@ -311,10 +313,16 @@ sub DbRep_Set($@) { } elsif ($opt eq "exportToFile") { if (!AttrVal($hash->{NAME}, "expimpfile", "")) { - return " The attribute \"expimpfile\" (path and filename) has to be set for export !"; + return " The attribute \"expimpfile\" (path and filename) has to be set for export to file !"; } sqlexec($hash,"exportToFile"); + } elsif ($opt eq "importFromFile") { + if (!AttrVal($hash->{NAME}, "expimpfile", "")) { + return " The attribute \"expimpfile\" (path and filename) has to be set for import from file !"; + } + sqlexec($hash,"importFromFile"); + } else { @@ -593,7 +601,7 @@ sub sqlexec($$) { } elsif (AttrVal($hash->{NAME}, "timestamp_begin", "") eq "previous_year_begin") { $tsbegin = ($cy-1)."-01-01 00:00:00"; } else { - $tsbegin = AttrVal($hash->{NAME}, "timestamp_begin", ""); + $tsbegin = AttrVal($hash->{NAME}, "timestamp_begin", "1970-01-01 01:00:00"); } # Auswertungszeit Ende (String) @@ -610,20 +618,23 @@ sub sqlexec($$) { # extrahieren der Einzelwerte von Datum/Zeit Beginn my ($yyyy1, $mm1, $dd1, $hh1, $min1, $sec1) = ($tsbegin =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/); - - # Umwandeln in Epochesekunden bzw. setzen Differenz zur akt. Zeit wenn attr "timeDiffToNow" gesetzt Beginn - my $epoch_seconds_begin = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900) if($tsbegin); - $epoch_seconds_begin = AttrVal($hash->{NAME}, "timeDiffToNow", undef) ? (time() - AttrVal($hash->{NAME}, "timeDiffToNow", undef)) : $epoch_seconds_begin; - Log3 ($name, 4, "DbRep $name - Time difference to current time for calculating Timestamp begin: ".AttrVal($hash->{NAME}, "timeDiffToNow", undef)." sec") if(AttrVal($hash->{NAME}, "timeDiffToNow", undef)); - - Log3 ($name, 5, "DbRep $name - Timestamp begin epocheseconds: $epoch_seconds_begin"); - my $tsbegin_string = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin); - Log3 ($name, 4, "DbRep $name - Timestamp begin human readable: $tsbegin_string"); - - - # extrahieren der Einzelwerte von Datum/Zeit Ende bzw. Selektionsende dynamisch auf -timeOlderThan setzen + # extrahieren der Einzelwerte von Datum/Zeit Ende my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($tsend =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/); + # Umwandeln in Epochesekunden bzw. Zeitgrenzen setzen wenn attr "timeDiffToNow" gesetzt Beginn + my $epoch_seconds_begin = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900) if($tsbegin); + + if(AttrVal($hash->{NAME}, "timeDiffToNow", undef)) { + $epoch_seconds_begin = time() - AttrVal($hash->{NAME}, "timeDiffToNow", undef); + Log3 ($name, 4, "DbRep $name - Time difference to current time for calculating Timestamp begin: ".AttrVal($hash->{NAME}, "timeDiffToNow", undef)." sec"); + } elsif (AttrVal($hash->{NAME}, "timeOlderThan", undef)) { + $epoch_seconds_begin = timelocal(00, 00, 01, 01, 01-1, 1970-1900); + } + + my $tsbegin_string = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin); + Log3 ($name, 5, "DbRep $name - Timestamp begin epocheseconds: $epoch_seconds_begin"); + Log3 ($name, 4, "DbRep $name - Timestamp begin human readable: $tsbegin_string"); + # Umwandeln in Epochesekunden Endezeit my $epoch_seconds_end = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900); $epoch_seconds_end = AttrVal($hash->{NAME}, "timeOlderThan", undef) ? (time() - AttrVal($hash->{NAME}, "timeOlderThan", undef)) : $epoch_seconds_end; @@ -726,11 +737,14 @@ $hash->{HELPER}{CV} = \%cv; $hash->{HELPER}{RUNNING_PID} = BlockingCall("expfile_DoParse", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "expfile_ParseDone", $to, "ParseAborted", $hash); + } elsif ($opt eq "importFromFile") { + $hash->{HELPER}{RUNNING_PID} = BlockingCall("impfile_Push", "$name", "impfile_PushDone", $to, "ParseAborted", $hash); + } elsif ($opt eq "max") { $hash->{HELPER}{RUNNING_PID} = BlockingCall("maxval_DoParse", "$name§$device§$reading§$ts", "maxval_ParseDone", $to, "ParseAborted", $hash); } elsif ($opt eq "del") { - $runtime_string_first = AttrVal($hash->{NAME}, "timestamp_begin", undef) ? strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin) : "1970-01-01 01:00:00"; + $runtime_string_first = defined($epoch_seconds_begin) ? strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_begin) : "1970-01-01 01:00:00"; $runtime_string_next = strftime "%Y-%m-%d %H:%M:%S", localtime($epoch_seconds_end); $hash->{HELPER}{RUNNING_PID} = BlockingCall("del_DoParse", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "del_ParseDone", $to, "ParseAborted", $hash); @@ -792,12 +806,12 @@ sub averval_DoParse($) { # SQL zusammenstellen für DB-Abfrage my $sql = "SELECT AVG(VALUE) FROM `history` "; - $sql .= "where " if($reading || $device || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); + $sql .= "where " if($reading || $device || $runtime_string_first || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); $sql .= "DEVICE = '$device' " if($device); $sql .= "AND " if($device && $reading); $sql .= "READING = '$reading' " if($reading); - $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); - $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); + $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); + $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); $sql .= ";"; Log3 ($name, 4, "DbRep $name - SQL to execute: $sql"); @@ -905,7 +919,7 @@ return; sub count_DoParse($) { my ($string) = @_; my ($name, $device, $reading, $ts) = split("\\§", $string); - my $hash = $defs{$name}; + my $hash = $defs{$name}; my $dbloghash = $hash->{dbloghash}; my $dbconn = $dbloghash->{dbconn}; my $dbuser = $dbloghash->{dbuser}; @@ -945,12 +959,12 @@ sub count_DoParse($) { # SQL zusammenstellen für DB-Abfrage my $sql = "SELECT COUNT(*) FROM `history` "; - $sql .= "where " if($reading || $device || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); + $sql .= "where " if($reading || $device || $runtime_string_first || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); $sql .= "DEVICE = '$device' " if($device); $sql .= "AND " if($device && $reading); $sql .= "READING = '$reading' " if($reading); - $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); - $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); + $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); + $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); $sql .= ";"; Log3($name, 4, "DbRep $name - SQL to execute: $sql"); @@ -1545,12 +1559,12 @@ sub sumval_DoParse($) { # SQL zusammenstellen für DB-Abfrage my $sql = "SELECT SUM(VALUE) FROM `history` "; - $sql .= "where " if($reading || $device || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); + $sql .= "where " if($reading || $device || $runtime_string_first || AttrVal($hash->{NAME},"aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME}, "timeOlderThan",undef)); $sql .= "DEVICE = '$device' " if($device); $sql .= "AND " if($device && $reading); $sql .= "READING = '$reading' " if($reading); - $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); - $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || AttrVal($hash->{NAME},"timestamp_begin",undef) || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); + $sql .= "AND " if((AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME}, "timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)) && ($device || $reading)); + $sql .= "TIMESTAMP BETWEEN '$runtime_string_first' AND '$runtime_string_next' " if(AttrVal($hash->{NAME}, "aggregation", "no") ne "no" || $runtime_string_first || AttrVal($hash->{NAME},"timestamp_end",undef) || AttrVal($hash->{NAME},"timeDiffToNow",undef) || AttrVal($hash->{NAME},"timeOlderThan",undef)); $sql .= ";"; Log3 ($name, 4, "DbRep $name - SQL to execute: $sql"); @@ -2085,6 +2099,8 @@ sub expfile_DoParse($) { Log3 ($name, 4, "DbRep $name -> BlockingCall expfile_DoParse finished"); return "$name|''|''|$err"; } else { + # only for this block because of warnings of uninitialized values + no warnings 'uninitialized'; while (my $row = $sth->fetchrow_arrayref) { print FH join(',', map { s{"}{""}g; "\"$_\""; } @$row), "\n"; Log3 ($name, 5, "DbRep $name -> write row: @$row"); @@ -2139,15 +2155,13 @@ sub expfile_ParseDone($) { my $export_string = $ds.$rds." -- ROWS EXPORTED TO FILE -- "; readingsBeginUpdate($hash); - readingsBulkUpdate($hash, $export_string, $nrows); - - my $rows = $ds.$rds.$nrows; - - Log3 ($name, 3, "DbRep $name - Number of exported datasets from $hash->{dbloghash}{NAME} to file ".AttrVal($name, "expimpfile", undef).": $rows"); - + readingsBulkUpdate($hash, $export_string, $nrows); readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); readingsBulkUpdate($hash, "state", "done"); readingsEndUpdate($hash, 1); + + my $rows = $ds.$rds.$nrows; + Log3 ($name, 3, "DbRep $name - Number of exported datasets from $hash->{dbloghash}{NAME} to file ".AttrVal($name, "expimpfile", undef).": $rows"); delete($hash->{HELPER}{RUNNING_PID}); @@ -2156,6 +2170,185 @@ sub expfile_ParseDone($) { return; } +#################################################################################################### +# nichtblockierende DB-Funktion impfile +#################################################################################################### + +sub impfile_Push($) { + my ($name) = @_; + my $hash = $defs{$name}; + my $dbloghash = $hash->{dbloghash}; + my $dbconn = $dbloghash->{dbconn}; + my $dbuser = $dbloghash->{dbuser}; + my $dblogname = $dbloghash->{NAME}; + my $dbmodel = $hash->{dbloghash}{DBMODEL}; + my $dbpassword = $attr{"sec$dblogname"}{secret}; + my $err=0; + + Log3 ($name, 4, "DbRep $name -> Start BlockingCall impfile_Push"); + + my $dbh; + eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1 });}; + + if ($@) { + $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - $@"); + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + return "$name|''|''|$err"; + } + + my $infile = AttrVal($name, "expimpfile", undef); + if (open(FH, "$infile")) { + binmode (FH); + } else { + $err = encode_base64("could not open ".$infile.": ".$!,""); + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + return "$name|''|''|$err"; + } + + # SQL-Startzeit + my $st = [gettimeofday]; + + # only for this block because of warnings if details inline is not set + no warnings 'uninitialized'; + + my $al; + # Datei zeilenweise einlesen und verarbeiten ! + # Beispiel Inline: + # "2016-09-25 08:53:56","STP_5000","SMAUTILS","etotal: 11859.573","etotal","11859.573","" + + $dbh->begin_work(); + my $sth = $dbh->prepare_cached("INSERT INTO history (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES (?,?,?,?,?,?,?)"); + $dbh->{AutoCommit} = 0; + my $irowdone = 0; + my $irowcount = 0; + my $warn = 0; + while () { + $al = $_; + chomp $al; + my @alarr = split("\",\"", $al); + # $al =~ tr/"//d; + my $i_timestamp = $alarr[0]; + $i_timestamp =~ tr/"//d; + my $i_device = $alarr[1]; + my $i_type = $alarr[2]; + my $i_event = $alarr[3]; + my $i_reading = $alarr[4]; + my $i_value = $alarr[5]; + my $i_unit = $alarr[6] ? $alarr[6]: " "; + $i_unit =~ tr/"//d; + $irowcount++; + next if(!$i_timestamp); #leerer Datensatz + + # check ob TIMESTAMP Format ok ? + my ($i_date, $i_time) = split(" ",$i_timestamp); + if ($i_date !~ /(\d{4})-(\d{2})-(\d{2})/ || $i_time !~ /(\d{2}):(\d{2}):(\d{2})/) { + $err = encode_base64("Format of date/time is not valid in row $irowcount of $infile. Must be format \"YYYY-MM-DD HH:MM:SS\" !",""); + Log3 ($name, 2, "DbRep $name -> ERROR - Import of datasets of file $infile was NOT done. Invalid date/time field format in row $irowcount !"); + close(FH); + $dbh->rollback; + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + return "$name|''|''|$err"; + } + + # Daten auf maximale Länge (entsprechend der Feldlänge in DbLog DB create-scripts) beschneiden wenn nicht SQLite + if ($dbmodel ne 'SQLITE') { + if ($dbmodel eq 'POSTGRESQL') { + $i_device = substr($i_device,0, $dbrep_col_postgre{DEVICE}); + $i_reading = substr($i_reading,0, $dbrep_col_postgre{READING}); + $i_value = substr($i_value,0, $dbrep_col_postgre{VALUE}); + $i_unit = substr($i_unit,0, $dbrep_col_postgre{UNIT}) if($i_unit); + } elsif ($dbmodel eq 'MYSQL') { + $i_device = substr($i_device,0, $dbrep_col_mysql{DEVICE}); + $i_reading = substr($i_reading,0, $dbrep_col_mysql{READING}); + $i_value = substr($i_value,0, $dbrep_col_mysql{VALUE}); + $i_unit = substr($i_unit,0, $dbrep_col_mysql{UNIT}) if($i_unit); + } + } + + Log3 ($name, 5, "DbRep $name -> data to insert Timestamp: $i_timestamp, Device: $i_device, Type: $i_type, Event: $i_event, Reading: $i_reading, Value: $i_value, Unit: $i_unit"); + + if($i_timestamp && $i_device && $i_reading) { + + eval {$sth->execute($i_timestamp, $i_device, $i_type, $i_event, $i_reading, $i_value, $i_unit);}; + + if ($@) { + $err = encode_base64($@,""); + Log3 ($name, 2, "DbRep $name - Failed to insert new dataset into database: $@"); + close(FH); + $dbh->rollback; + $dbh->disconnect; + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + return "$name|''|''|$err"; + } else { + $irowdone++ + } + + } else { + $err = encode_base64("format error in in row $irowcount of $infile.",""); + Log3 ($name, 2, "DbRep $name -> ERROR - Import of datasets of file $infile was NOT done. Formaterror in row $irowcount !"); + close(FH); + $dbh->rollback; + $dbh->disconnect; + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + return "$name|''|''|$err"; + } + } + + $dbh->commit; + $dbh->disconnect; + close(FH); + + # SQL-Laufzeit ermitteln + my $rt = tv_interval($st); + + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_Push finished"); + + return "$name|$irowdone|$rt|$err"; +} + +#################################################################################################### +# Auswertungsroutine der nichtblockierenden DB-Funktion impfile +#################################################################################################### + +sub impfile_PushDone($) { + my ($string) = @_; + my @a = split("\\|",$string); + my $hash = $defs{$a[0]}; + my $irowdone = $a[1]; + my $rt = $a[2]; + my $err = $a[3]?decode_base64($a[3]):undef; + my $name = $hash->{NAME}; + + Log3 ($name, 4, "DbRep $name -> Start BlockingCall impfile_PushDone"); + + if ($err) { + readingsSingleUpdate($hash, "errortext", $err, 1); + readingsSingleUpdate($hash, "state", "error", 1); + delete($hash->{HELPER}{RUNNING_PID}); + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_PushDone finished"); + return; + } + + # only for this block because of warnings if details of readings are not set + no warnings 'uninitialized'; + + my $import_string = " -- ROWS IMPORTED FROM FILE -- "; + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, $import_string, $irowdone); + readingsBulkUpdate($hash, "sql_processing_time", sprintf("%.4f",$rt)) if(AttrVal($name, "showproctime", undef)); + readingsBulkUpdate($hash, "state", "done"); + readingsEndUpdate($hash, 1); + + Log3 ($name, 3, "DbRep $name - Number of imported datasets to $hash->{dbloghash}{NAME} from file ".AttrVal($name, "expimpfile", undef).": $irowdone"); + + delete($hash->{HELPER}{RUNNING_PID}); + Log3 ($name, 4, "DbRep $name -> BlockingCall impfile_PushDone finished"); + +return; +} + #################################################################################################### # Abbruchroutine Timeout DB-Abfrage #################################################################################################### @@ -2344,8 +2537,8 @@ return ($runtime,$runtime_string,$runtime_string_first,$runtime_string_next,$ll) =pod =item helper -=item summary browsing / managing content of DbLog-databases. Content is depicted as readings -=item summary_DE durchsuchen / bearbeiten von DbLog-DB Content. Darstellung als Readings +=item summary Reporting & Management content of DbLog-DB's. Content is depicted as readings +=item summary_DE Reporting & Management von DbLog-DB Content. Darstellung als Readings =begin html @@ -2369,7 +2562,8 @@ return ($runtime,$runtime_string,$runtime_string_first,$runtime_string_next,$ll)
  • Calculation of quantity of datasets of a Device/Reading-combination within adjustable time limits and several aggregations.
  • The calculation of summary- , difference- , maximal- and averageValues of numeric readings within adjustable time limits and several aggregations.
  • The deletion of datasets. The containment of deletion can be done by Device and/or Reading as well as fix or dynamically calculated time limits at execution time.
  • -
  • export of datasets in CSV-format.
  • +
  • export of datasets to file (CSV-format).
  • +
  • import of datasets from file (CSV-Format).

  • @@ -2424,7 +2618,7 @@ return ($runtime,$runtime_string,$runtime_string_first,$runtime_string_next,$ll)
    @@ -2611,7 +2819,7 @@ return ($runtime,$runtime_string,$runtime_string_first,$runtime_string_next,$ll)