2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

93_DbRep: V7.10.0, new "changeValue" command, minor fixes

git-svn-id: https://svn.fhem.de/fhem/trunk@16163 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2018-02-12 22:27:06 +00:00
parent b8d387addd
commit f76a5519bd
2 changed files with 216 additions and 48 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it. # Do not insert empty lines here, update check depends on it.
- feature: 93_DbRep: V7.10.0, new "changeValue" command, minor fixes
- bugfix: 88_xs1Bridge: fix Filelog check - bugfix: 88_xs1Bridge: fix Filelog check
- new: 39_Talk2Fhem: new module for language control - new: 39_Talk2Fhem: new module for language control
- feature: 70_BRAVIA: TV input select for all active tuners - feature: 70_BRAVIA: TV input select for all active tuners

View File

@ -37,9 +37,10 @@
########################################################################################################################### ###########################################################################################################################
# Versions History: # Versions History:
# #
# 7.10.0 10.02.2018 bugfix delete attr timeYearPeriod if set other time attributes, new "changeValue" command
# 7.9.0 09.02.2018 new attribute "avgTimeWeightMean" (time weight mean calculation), code review of selection # 7.9.0 09.02.2018 new attribute "avgTimeWeightMean" (time weight mean calculation), code review of selection
# routines, maxValue handle negative values correctly, # routines, maxValue handle negative values correctly,
# one security second for correct create TimeArray in normRelativeTime # one security second for correct create TimeArray in DbRep_normRelTime
# 7.8.1 04.02.2018 bugfix if IsDisabled (again), code review, bugfix last dataset is not selected if timestamp # 7.8.1 04.02.2018 bugfix if IsDisabled (again), code review, bugfix last dataset is not selected if timestamp
# is fully set ("date time"), fix "$runtime_string_next = "$runtime_string_next.999";" if # is fully set ("date time"), fix "$runtime_string_next = "$runtime_string_next.999";" if
# $runtime_string_next is part of sql-execute place holder AND contains date+time # $runtime_string_next is part of sql-execute place holder AND contains date+time
@ -76,7 +77,7 @@
# 7.1.0 22.12.2017 new attribute timeYearPeriod for reports correspondig to e.g. electricity billing, # 7.1.0 22.12.2017 new attribute timeYearPeriod for reports correspondig to e.g. electricity billing,
# bugfix connection check is running after restart allthough dev is disabled # bugfix connection check is running after restart allthough dev is disabled
# 7.0.0 18.12.2017 don't set $runtime_string_first,$runtime_string_next,$ts if time/aggregation-attributes # 7.0.0 18.12.2017 don't set $runtime_string_first,$runtime_string_next,$ts if time/aggregation-attributes
# not set, devren_Push redesigned, new command get blockinginfo, identify if reopen is # not set, change_Push redesigned, new command get blockinginfo, identify if reopen is
# running on dblog-device and postpone the set-command # running on dblog-device and postpone the set-command
# 6.4.3 17.12.2017 bugfix in delSeqDoublets, fetchrows if datasets contain characters like "' <blank> and s.o. # 6.4.3 17.12.2017 bugfix in delSeqDoublets, fetchrows if datasets contain characters like "' <blank> and s.o.
# 6.4.2 15.12.2017 change "delSeqDoublets" to respect attribute "limit" (adviceDelete,adviceRemain), # 6.4.2 15.12.2017 change "delSeqDoublets" to respect attribute "limit" (adviceDelete,adviceRemain),
@ -311,7 +312,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
sub DbRep_Main($$;$); sub DbRep_Main($$;$);
sub DbLog_cutCol($$$$$$$); # DbLog-Funktion nutzen um Daten auf maximale Länge beschneiden sub DbLog_cutCol($$$$$$$); # DbLog-Funktion nutzen um Daten auf maximale Länge beschneiden
my $DbRepVersion = "7.9.0"; my $DbRepVersion = "7.10.0";
my %dbrep_col = ("DEVICE" => 64, my %dbrep_col = ("DEVICE" => 64,
"TYPE" => 64, "TYPE" => 64,
@ -477,6 +478,7 @@ sub DbRep_Set($@) {
"eraseReadings:noArg ". "eraseReadings:noArg ".
(($hash->{ROLE} ne "Agent")?"sumValue:display,writeToDB ":""). (($hash->{ROLE} ne "Agent")?"sumValue:display,writeToDB ":"").
(($hash->{ROLE} ne "Agent")?"averageValue:display,writeToDB ":""). (($hash->{ROLE} ne "Agent")?"averageValue:display,writeToDB ":"").
(($hash->{ROLE} ne "Agent")?"changeValue ":"").
(($hash->{ROLE} ne "Agent")?"delEntries:noArg ":""). (($hash->{ROLE} ne "Agent")?"delEntries:noArg ":"").
(($hash->{ROLE} ne "Agent")?"delSeqDoublets:adviceRemain,adviceDelete,delete ":""). (($hash->{ROLE} ne "Agent")?"delSeqDoublets:adviceRemain,adviceDelete,delete ":"").
"deviceRename ". "deviceRename ".
@ -631,7 +633,7 @@ sub DbRep_Set($@) {
} elsif ($opt eq "deviceRename") { } elsif ($opt eq "deviceRename") {
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt"; $hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
my ($olddev, $newdev) = split(",",$prop); my ($olddev, $newdev) = split(",",$prop);
if (!$olddev || !$newdev) {return "Both entries \"old device name\", \"new device name\" are needed. Use \"set ... deviceRename olddevname,newdevname\" ";} if (!$olddev || !$newdev) {return "Both entries \"old device name\", \"new device name\" are needed. Use \"set $name deviceRename olddevname,newdevname\" ";}
$hash->{HELPER}{OLDDEV} = $olddev; $hash->{HELPER}{OLDDEV} = $olddev;
$hash->{HELPER}{NEWDEV} = $newdev; $hash->{HELPER}{NEWDEV} = $newdev;
$hash->{HELPER}{RENMODE} = "devren"; $hash->{HELPER}{RENMODE} = "devren";
@ -640,7 +642,7 @@ sub DbRep_Set($@) {
} elsif ($opt eq "readingRename") { } elsif ($opt eq "readingRename") {
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt"; $hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
my ($oldread, $newread) = split(",",$prop); my ($oldread, $newread) = split(",",$prop);
if (!$oldread || !$newread) {return "Both entries \"old reading name\", \"new reading name\" are needed. Use \"set ... readingRename oldreadingname,newreadingname\" ";} if (!$oldread || !$newread) {return "Both entries \"old reading name\", \"new reading name\" are needed. Use \"set $name readingRename oldreadingname,newreadingname\" ";}
$hash->{HELPER}{OLDREAD} = $oldread; $hash->{HELPER}{OLDREAD} = $oldread;
$hash->{HELPER}{NEWREAD} = $newread; $hash->{HELPER}{NEWREAD} = $newread;
$hash->{HELPER}{RENMODE} = "readren"; $hash->{HELPER}{RENMODE} = "readren";
@ -736,6 +738,20 @@ sub DbRep_Set($@) {
} }
DbRep_Main($hash,$opt,$sqlcmd); DbRep_Main($hash,$opt,$sqlcmd);
} elsif ($opt =~ /changeValue/) {
shift @a;
shift @a;
$prop = join(" ", @a);
$hash->{LASTCMD} = $prop?"$opt $prop":"$opt";
unless($prop =~ m/^(".*",".*")$/) {return "Both entries \"old value\", \"new value\" are needed. Use \"set $name changeValue \"old value\",\"new value\" (use quotes)";}
my ($oldval,$newval) = split(/","/,$prop);
$oldval =~ s/"//g;
$newval =~ s/"//g;
$hash->{HELPER}{OLDVAL} = $oldval;
$hash->{HELPER}{NEWVAL} = $newval;
$hash->{HELPER}{RENMODE} = "changeval";
DbRep_Main($hash,$opt);
} else { } else {
return "$setlist"; return "$setlist";
} }
@ -1003,6 +1019,7 @@ sub DbRep_Attr($$$$) {
delete($attr{$name}{timestamp_begin}) if ($attr{$name}{timestamp_begin}); delete($attr{$name}{timestamp_begin}) if ($attr{$name}{timestamp_begin});
delete($attr{$name}{timestamp_end}) if ($attr{$name}{timestamp_end}); delete($attr{$name}{timestamp_end}) if ($attr{$name}{timestamp_end});
delete($attr{$name}{timeOlderThan}) if ($attr{$name}{timeOlderThan}); delete($attr{$name}{timeOlderThan}) if ($attr{$name}{timeOlderThan});
delete($attr{$name}{timeYearPeriod}) if ($attr{$name}{timeYearPeriod});
} }
if ($aName eq "timeOlderThan") { if ($aName eq "timeOlderThan") {
unless ($aVal =~ /^[0-9]+$/ || $aVal =~ /^\s*[dhms]:([\d]+)\s*/ && $aVal !~ /.*,.*/ ) unless ($aVal =~ /^[0-9]+$/ || $aVal =~ /^\s*[dhms]:([\d]+)\s*/ && $aVal !~ /.*,.*/ )
@ -1010,6 +1027,7 @@ sub DbRep_Attr($$$$) {
delete($attr{$name}{timestamp_begin}) if ($attr{$name}{timestamp_begin}); delete($attr{$name}{timestamp_begin}) if ($attr{$name}{timestamp_begin});
delete($attr{$name}{timestamp_end}) if ($attr{$name}{timestamp_end}); delete($attr{$name}{timestamp_end}) if ($attr{$name}{timestamp_end});
delete($attr{$name}{timeDiffToNow}) if ($attr{$name}{timeDiffToNow}); delete($attr{$name}{timeDiffToNow}) if ($attr{$name}{timeDiffToNow});
delete($attr{$name}{timeYearPeriod}) if ($attr{$name}{timeYearPeriod});
} }
if ($aName eq "dumpMemlimit" || $aName eq "dumpSpeed") { if ($aName eq "dumpMemlimit" || $aName eq "dumpSpeed") {
unless ($aVal =~ /^[0-9]+$/) { return "The Value of $aName is not valid. Use only figures 0-9 without decimal places.";} unless ($aVal =~ /^[0-9]+$/) { return "The Value of $aName is not valid. Use only figures 0-9 without decimal places.";}
@ -1294,7 +1312,7 @@ sub DbRep_Main($$;$) {
# zentrales Timestamp-Array und Zeitgrenzen bereitstellen # zentrales Timestamp-Array und Zeitgrenzen bereitstellen
my ($epoch_seconds_begin,$epoch_seconds_end,$runtime_string_first,$runtime_string_next); my ($epoch_seconds_begin,$epoch_seconds_end,$runtime_string_first,$runtime_string_next);
my $ts = "no_aggregation"; # Dummy für eine Select-Schleife wenn != $IsTimeSet || $IsAggrSet my $ts = "no_aggregation"; # Dummy für eine Select-Schleife wenn != $IsTimeSet || $IsAggrSet
my ($IsTimeSet,$IsAggrSet,$aggregation) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet,$aggregation) = DbRep_checktimeaggr($hash);
if($IsTimeSet || $IsAggrSet) { if($IsTimeSet || $IsAggrSet) {
($epoch_seconds_begin,$epoch_seconds_end,$runtime_string_first,$runtime_string_next,$ts) = DbRep_createTimeArray($hash,$aggregation,$opt); ($epoch_seconds_begin,$epoch_seconds_end,$runtime_string_first,$runtime_string_next,$ts) = DbRep_createTimeArray($hash,$aggregation,$opt);
} else { } else {
@ -1353,8 +1371,8 @@ sub DbRep_Main($$;$) {
} elsif ($opt eq "insert") { } elsif ($opt eq "insert") {
$hash->{HELPER}{RUNNING_PID} = BlockingCall("insert_Push", "$name", "insert_Done", $to, "ParseAborted", $hash); $hash->{HELPER}{RUNNING_PID} = BlockingCall("insert_Push", "$name", "insert_Done", $to, "ParseAborted", $hash);
} elsif ($opt =~ /deviceRename|readingRename/) { } elsif ($opt =~ /deviceRename|readingRename|changeValue/) {
$hash->{HELPER}{RUNNING_PID} = BlockingCall("devren_Push", "$name", "devren_Done", $to, "ParseAborted", $hash); $hash->{HELPER}{RUNNING_PID} = BlockingCall("change_Push", "$name|$device|$reading|$runtime_string_first|$runtime_string_next", "change_Done", $to, "ParseAborted", $hash);
} elsif ($opt =~ /sqlCmd/ ) { } elsif ($opt =~ /sqlCmd/ ) {
# Execute a generic sql command # Execute a generic sql command
@ -1631,7 +1649,7 @@ sub DbRep_createTimeArray($$$) {
###################################################################################### ######################################################################################
# Umwandeln in Epochesekunden Beginn # Umwandeln in Epochesekunden Beginn
my $epoch_seconds_begin = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900) if($tsbegin); my $epoch_seconds_begin = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900) if($tsbegin);
my ($timeolderthan,$timedifftonow) = normRelativeTime($hash); my ($timeolderthan,$timedifftonow) = DbRep_normRelTime($hash);
if($timedifftonow) { if($timedifftonow) {
$epoch_seconds_begin = time() - $timedifftonow; $epoch_seconds_begin = time() - $timedifftonow;
@ -1937,7 +1955,7 @@ sub averval_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -2142,7 +2160,8 @@ sub averval_DoParse($) {
$sum += $val1*($dt/$tsum); $sum += $val1*($dt/$tsum);
$val1 = $val; $val1 = $val;
$to = $tn; $to = $tn;
Log3 ($name, 5, "DbRep $name - data element: $twmrow");
Log3 ($name, 5, "DbRep $name - time sum: $tsum, delta time: $dt, value: $val1, twm: ".$val1*($dt/$tsum));
} }
} }
if(AttrVal($name, "aggregation", "") eq "hour") { if(AttrVal($name, "aggregation", "") eq "hour") {
@ -2293,7 +2312,7 @@ sub count_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet,$aggregation) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet,$aggregation) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -2457,7 +2476,7 @@ sub maxval_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -2695,7 +2714,7 @@ sub minval_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -2938,7 +2957,7 @@ sub diffval_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -3304,7 +3323,7 @@ sub sumval_DoParse($) {
no warnings 'uninitialized'; no warnings 'uninitialized';
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -3489,7 +3508,7 @@ sub del_DoParse($) {
} }
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# SQL zusammenstellen für DB-Operation # SQL zusammenstellen für DB-Operation
@ -3769,7 +3788,7 @@ sub currentfillup_Push($) {
my ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbh); my ($usepkh,$usepkc,$pkh,$pkc) = DbRep_checkUsePK($hash,$dbh);
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
($devs,$danz,$reading,$ranz) = specsForSql($hash,$device,$reading); ($devs,$danz,$reading,$ranz) = specsForSql($hash,$device,$reading);
@ -3955,27 +3974,29 @@ return;
#################################################################################################### ####################################################################################################
# nichtblockierendes DB deviceRename / readingRename # nichtblockierendes DB deviceRename / readingRename
#################################################################################################### ####################################################################################################
sub devren_Push($) { sub change_Push($) {
my ($name) = @_; my ($string) = @_;
my ($name,$device,$reading,$runtime_string_first,$runtime_string_next) = 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};
my $dbuser = $dbloghash->{dbuser}; my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME}; my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret}; my $dbpassword = $attr{"sec$dblogname"}{secret};
my $table = "history";
my ($dbh,$err,$sql); my ($dbh,$err,$sql);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
Log3 ($name, 4, "DbRep $name -> Start BlockingCall devren_Push"); Log3 ($name, 4, "DbRep $name -> Start BlockingCall change_Push");
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });}; eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });};
if ($@) { if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
Log3 ($name, 4, "DbRep $name -> BlockingCall devren_Push finished"); Log3 ($name, 4, "DbRep $name -> BlockingCall change_Push finished");
return "$name|''|''|$err"; return "$name|''|''|$err";
} }
@ -4017,7 +4038,33 @@ sub devren_Push($) {
$sql = "UPDATE history SET TIMESTAMP=TIMESTAMP,READING='$new' WHERE READING='$old'; "; $sql = "UPDATE history SET TIMESTAMP=TIMESTAMP,READING='$new' WHERE READING='$old'; ";
Log3 ($name, 4, "DbRep $name - SQL execute: $sql"); Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
$sth = $dbh->prepare($sql) ; $sth = $dbh->prepare($sql) ;
}
} elsif ($renmode eq "changeval") {
$old = delete $hash->{HELPER}{OLDVAL};
$new = delete $hash->{HELPER}{NEWVAL};
# SQL zusammenstellen für DB-Operation
Log3 ($name, 5, "DbRep $name -> Change old value \"$old\" to new value \"$new\" in database $dblogname ");
# prepare DB operation
$old =~ s/'/''/g; # escape ' with ''
$new =~ s/'/''/g; # escape ' with ''
my $d = AttrVal($name,"device","%");
my $r = AttrVal($name,"reading","%");
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# SQL zusammenstellen für DB-Update
if ($IsTimeSet) {
$sql = DbRep_createUpdateSql($hash,$table,"TIMESTAMP=TIMESTAMP,VALUE='$new' WHERE VALUE='$old'",$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",'');
} else {
$sql = DbRep_createUpdateSql($hash,$table,"TIMESTAMP=TIMESTAMP,VALUE='$new' WHERE VALUE='$old'",$device,$reading,undef,undef,'');
}
Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
$sth = $dbh->prepare($sql) ;
}
my $urow; my $urow;
eval { $sth->execute(); }; eval { $sth->execute(); };
@ -4027,11 +4074,15 @@ sub devren_Push($) {
if ($@) { if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
my $m = ($renmode eq "devren")?"device":"reading"; if($renmode ne "changeValue") {
Log3 ($name, 2, "DbRep $name - Failed to rename old $m name \"$old\" to new $m name \"$new\": $@"); my $m = ($renmode eq "devren")?"device":"reading";
Log3 ($name, 2, "DbRep $name - Failed to rename old $m name \"$old\" to new $m name \"$new\": $@");
} else {
Log3 ($name, 2, "DbRep $name - Failed to change old value \"$old\" to new value \"$new\": $@");
}
$dbh->rollback() if(!$dbh->{AutoCommit}); $dbh->rollback() if(!$dbh->{AutoCommit});
$dbh->disconnect(); $dbh->disconnect();
Log3 ($name, 4, "DbRep $name -> BlockingCall devren_Push finished"); Log3 ($name, 4, "DbRep $name -> BlockingCall change_Push finished");
return "$name|''|''|$err"; return "$name|''|''|$err";
} else { } else {
$dbh->commit() if(!$dbh->{AutoCommit}); $dbh->commit() if(!$dbh->{AutoCommit});
@ -4042,7 +4093,7 @@ sub devren_Push($) {
# SQL-Laufzeit ermitteln # SQL-Laufzeit ermitteln
my $rt = tv_interval($st); my $rt = tv_interval($st);
Log3 ($name, 4, "DbRep $name -> BlockingCall devren_Push finished"); Log3 ($name, 4, "DbRep $name -> BlockingCall change_Push finished");
# Background-Laufzeit ermitteln # Background-Laufzeit ermitteln
my $brt = tv_interval($bst); my $brt = tv_interval($bst);
@ -4055,7 +4106,7 @@ sub devren_Push($) {
#################################################################################################### ####################################################################################################
# Auswertungsroutine DB deviceRename # Auswertungsroutine DB deviceRename
#################################################################################################### ####################################################################################################
sub devren_Done($) { sub change_Done($) {
my ($string) = @_; my ($string) = @_;
my @a = split("\\|",$string); my @a = split("\\|",$string);
my $hash = $defs{$a[0]}; my $hash = $defs{$a[0]};
@ -4067,7 +4118,7 @@ sub devren_Done($) {
my $old = $a[4]; my $old = $a[4];
my $new = $a[5]; my $new = $a[5];
Log3 ($name, 4, "DbRep $name -> Start BlockingCall devren_Done"); Log3 ($name, 4, "DbRep $name -> Start BlockingCall change_Done");
my $renmode = delete $hash->{HELPER}{RENMODE}; my $renmode = delete $hash->{HELPER}{RENMODE};
@ -4075,7 +4126,7 @@ sub devren_Done($) {
ReadingsSingleUpdateValue ($hash, "errortext", $err, 1); ReadingsSingleUpdateValue ($hash, "errortext", $err, 1);
ReadingsSingleUpdateValue ($hash, "state", "error", 1); ReadingsSingleUpdateValue ($hash, "state", "error", 1);
delete($hash->{HELPER}{RUNNING_PID}); delete($hash->{HELPER}{RUNNING_PID});
Log3 ($name, 4, "DbRep $name -> BlockingCall devren_Done finished"); Log3 ($name, 4, "DbRep $name -> BlockingCall change_Done finished");
return; return;
} }
@ -4095,6 +4146,11 @@ sub devren_Done($) {
ReadingsBulkUpdateValue ($hash, "reading_not_renamed", "Warning - old: ".$old." not found, not renamed to new: ".$new) ReadingsBulkUpdateValue ($hash, "reading_not_renamed", "Warning - old: ".$old." not found, not renamed to new: ".$new)
if ($urow == 0); if ($urow == 0);
} }
if($renmode eq "changeval") {
ReadingsBulkUpdateValue ($hash, "value_changed", "old: ".$old." to new: ".$new) if($urow != 0);
ReadingsBulkUpdateValue ($hash, "value_not_changed", "Warning - old: ".$old." not found, not changed to new: ".$new)
if ($urow == 0);
}
ReadingsBulkUpdateTimeState($hash,$brt,$rt,"done"); ReadingsBulkUpdateTimeState($hash,$brt,$rt,"done");
readingsEndUpdate($hash, 1); readingsEndUpdate($hash, 1);
@ -4108,12 +4164,11 @@ sub devren_Done($) {
} }
delete($hash->{HELPER}{RUNNING_PID}); delete($hash->{HELPER}{RUNNING_PID});
Log3 ($name, 4, "DbRep $name -> BlockingCall devren_Done finished"); Log3 ($name, 4, "DbRep $name -> BlockingCall change_Done finished");
return; return;
} }
#################################################################################################### ####################################################################################################
# nichtblockierende DB-Abfrage fetchrows # nichtblockierende DB-Abfrage fetchrows
#################################################################################################### ####################################################################################################
@ -4146,7 +4201,7 @@ sub fetchrows_DoParse($) {
} }
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# SQL zusammenstellen für DB-Abfrage # SQL zusammenstellen für DB-Abfrage
@ -4597,7 +4652,7 @@ sub expfile_DoParse($) {
} }
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef) # ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
my ($IsTimeSet,$IsAggrSet) = checktimeaggr($hash); my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet"); Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
# Timestampstring to Array # Timestampstring to Array
@ -6106,7 +6161,7 @@ sub mysql_DoDumpClientSide($) {
$ffd = $ffd?encode_base64($ffd,""):0; $ffd = $ffd?encode_base64($ffd,""):0;
# alte Dumpfiles löschen # alte Dumpfiles löschen
my @fd = deldumpfiles($hash,$backupfile); my @fd = DbRep_deldumpfiles($hash,$backupfile);
my $bfd = join(", ", @fd ); my $bfd = join(", ", @fd );
$bfd = $bfd?encode_base64($bfd,""):0; $bfd = $bfd?encode_base64($bfd,""):0;
@ -6269,7 +6324,7 @@ sub mysql_DoDumpServerSide($) {
$ffd = $ffd?encode_base64($ffd,""):0; $ffd = $ffd?encode_base64($ffd,""):0;
# alte Dumpfiles löschen # alte Dumpfiles löschen
my @fd = deldumpfiles($hash,$bfile); my @fd = DbRep_deldumpfiles($hash,$bfile);
my $bfd = join(", ", @fd ); my $bfd = join(", ", @fd );
$bfd = $bfd?encode_base64($bfd,""):0; $bfd = $bfd?encode_base64($bfd,""):0;
@ -6393,7 +6448,7 @@ sub sqlite_DoDump($) {
$ffd = $ffd?encode_base64($ffd,""):0; $ffd = $ffd?encode_base64($ffd,""):0;
# alte Dumpfiles löschen # alte Dumpfiles löschen
my @fd = deldumpfiles($hash,$bfile); my @fd = DbRep_deldumpfiles($hash,$bfile);
my $bfd = join(", ", @fd ); my $bfd = join(", ", @fd );
$bfd = $bfd?encode_base64($bfd,""):0; $bfd = $bfd?encode_base64($bfd,""):0;
@ -6806,6 +6861,43 @@ sub createSelectSql($$$$$$$$) {
return $sql; return $sql;
} }
####################################################################################################
# SQL-Statement zusammenstellen für DB-Updates
####################################################################################################
sub DbRep_createUpdateSql($$$$$$$$) {
my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_;
my $name = $hash->{NAME};
my $dbmodel = $hash->{dbloghash}{MODEL};
my ($sql,$devs,$danz,$ranz);
my $tnfull = 0;
($devs,$danz,$reading,$ranz) = specsForSql($hash,$device,$reading);
if($tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
$tnfull = 1;
}
$sql = "UPDATE $table SET $selspec AND ";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%));
$sql .= "DEVICE = '$devs' AND " if($danz <= 1 && $devs !~ m(\%));
$sql .= "DEVICE IN ($devs) AND " if($danz > 1);
$sql .= "READING LIKE '$reading' AND " if($ranz <= 1 && $reading !~ m(^%$) && $reading =~ m(\%));
$sql .= "READING = '$reading' AND " if($ranz <= 1 && $reading !~ m(\%));
$sql .= "READING IN ($reading) AND " if($ranz > 1);
if (($tf && $tn)) {
$sql .= "TIMESTAMP >= $tf AND TIMESTAMP ".($tnfull?"<=":"<")." $tn ";
} else {
if ($dbmodel eq "POSTGRESQL") {
$sql .= "true ";
} else {
$sql .= "1 ";
}
}
$sql .= "$addon;";
return $sql;
}
#################################################################################################### ####################################################################################################
# SQL-Statement zusammenstellen für Löschvorgänge # SQL-Statement zusammenstellen für Löschvorgänge
#################################################################################################### ####################################################################################################
@ -6880,7 +6972,7 @@ return ($devs,$danz,$reading,$ranz);
# Check ob Zeitgrenzen bzw. Aggregation gesetzt sind, evtl. übertseuern (je nach Funktion) # Check ob Zeitgrenzen bzw. Aggregation gesetzt sind, evtl. übertseuern (je nach Funktion)
# Return "1" wenn Bedingung erfüllt, sonst "0" # Return "1" wenn Bedingung erfüllt, sonst "0"
#################################################################################################### ####################################################################################################
sub checktimeaggr ($) { sub DbRep_checktimeaggr ($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $IsTimeSet = 0; my $IsTimeSet = 0;
@ -6903,7 +6995,7 @@ sub checktimeaggr ($) {
$aggregation = "day"; # für Tagesmittelwertberechnung des deuteschen Wetterdienstes immer "day" $aggregation = "day"; # für Tagesmittelwertberechnung des deuteschen Wetterdienstes immer "day"
$IsAggrSet = 1; $IsAggrSet = 1;
} }
if($hash->{LASTCMD} =~ /delEntries|fetchrows|deviceRename|readingRename|tableCurrentFillup/) { if($hash->{LASTCMD} =~ /delEntries|fetchrows|deviceRename|readingRename|changeValue|tableCurrentFillup/) {
$IsAggrSet = 0; $IsAggrSet = 0;
$aggregation = "no"; $aggregation = "no";
} }
@ -7022,7 +7114,7 @@ return;
# #
# liefert die Attribute timeOlderThan, timeDiffToNow als Sekunden normiert zurück # liefert die Attribute timeOlderThan, timeDiffToNow als Sekunden normiert zurück
#################################################################################################### ####################################################################################################
sub normRelativeTime ($) { sub DbRep_normRelTime ($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $tdtn = AttrVal($name, "timeDiffToNow", undef); my $tdtn = AttrVal($name, "timeDiffToNow", undef);
@ -7443,7 +7535,7 @@ return (undef,$db_MB_start,$db_MB_end);
#################################################################################################### ####################################################################################################
# Dump-Files im dumpDirLocal löschen bis auf die letzten "n" # Dump-Files im dumpDirLocal löschen bis auf die letzten "n"
#################################################################################################### ####################################################################################################
sub deldumpfiles ($$) { sub DbRep_deldumpfiles ($$) {
my ($hash,$bfile) = @_; my ($hash,$bfile) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $dbloghash = $hash->{dbloghash}; my $dbloghash = $hash->{dbloghash};
@ -7691,7 +7783,7 @@ sub DbRep_OutputWriteToDB($$$$$) {
} }
no warnings 'uninitialized'; no warnings 'uninitialized';
(undef,undef,$aggr) = checktimeaggr($hash); (undef,undef,$aggr) = DbRep_checktimeaggr($hash);
$reading = $optxt."_".$aggr."_".$reading; $reading = $optxt."_".$aggr."_".$reading;
$type = $defs{$device}{TYPE} if($defs{$device}); # $type vom Device ableiten $type = $defs{$device}{TYPE} if($defs{$device}); # $type vom Device ableiten
@ -8006,7 +8098,8 @@ return;
<li> 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. </li> <li> 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. </li>
<li> export of datasets to file (CSV-format). </li> <li> export of datasets to file (CSV-format). </li>
<li> import of datasets from file (CSV-Format). </li> <li> import of datasets from file (CSV-Format). </li>
<li> rename of device names in datasets </li> <li> rename of device/readings in datasets </li>
<li> change of reading values in the database </li>
<li> automatic rename of device names in datasets and other DbRep-definitions after FHEM "rename" command (see <a href="#DbRepAutoRename">DbRep-Agent</a>) </li> <li> automatic rename of device names in datasets and other DbRep-definitions after FHEM "rename" command (see <a href="#DbRepAutoRename">DbRep-Agent</a>) </li>
<li> Execution of arbitrary user specific SQL-commands </li> <li> Execution of arbitrary user specific SQL-commands </li>
<li> creation of backups of the database in running state non-blocking (MySQL, SQLite) </li> <li> creation of backups of the database in running state non-blocking (MySQL, SQLite) </li>
@ -8117,11 +8210,47 @@ return;
</ul> </ul>
</li><br> </li><br>
<li><b> cancelDump </b> - stops a running database dump. </li> <br>
<li><b> changeValue </b> - changes the saved value of readings.
If the selection is limited to particular device/reading-combinations by
<a href="#DbRepattr">attribute</a> "device" respectively "reading", it is considered as well
as possibly defined time limits by time attributes (time.*). <br>
If no limits are set, the whole database is scanned and the specified value will be
changed. <br><br>
<ul>
<b>Example: </b> <br>
set &lt;name&gt; changeValue "&lt;old string&gt;","&lt;new string&gt;" <br>
# the old string will be changed to new string. <br>
# Both strings may contain spaces. The strings have to be quoted and separated by comma.
<br><br>
Summarized the attributes to control changeValue are: <br><br>
<ul>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> <b>device</b> </td><td>: selection only of datasets which contain &lt;device&gt; </td></tr>
<tr><td> <b>reading</b> </td><td>: selection only of datasets which contain &lt;reading&gt; enthalten </td></tr>
<tr><td> <b>time.*</b> </td><td>: a number of attributes to limit selection by time </td></tr>
</table>
</ul>
<br>
<br>
<b>Note:</b> <br>
Even though the function itself is designed non-blocking, make sure the assigned DbLog-device
is operating in asynchronous mode to avoid FHEMWEB from blocking. <br><br>
</li> <br>
</ul>
<li><b> countEntries [history|current] </b> - provides the number of table-entries (default: history) between period set <li><b> countEntries [history|current] </b> - provides the number of table-entries (default: history) between period set
by timestamp-<a href="#DbRepattr">attributes</a> if set. by timestamp-<a href="#DbRepattr">attributes</a> if set.
If timestamp-attributes are not set, all entries of the table will be count. If timestamp-attributes are not set, all entries of the table will be count.
The <a href="#DbRepattr">attributes</a> "device" and "reading" can be used to The <a href="#DbRepattr">attributes</a> "device" and "reading" can be used to
limit the evaluation. </li> <br> limit the evaluation. </li> <br>
<li><b> delEntries </b> - deletes all database entries or only the database entries specified by <a href="#DbRepattr">attributes</a> Device and/or <li><b> delEntries </b> - deletes all database entries or only the database entries specified by <a href="#DbRepattr">attributes</a> Device and/or
Reading and the entered time period between "timestamp_begin", "timestamp_end" (if set) or "timeDiffToNow/timeOlderThan". <br><br> Reading and the entered time period between "timestamp_begin", "timestamp_end" (if set) or "timeDiffToNow/timeOlderThan". <br><br>
@ -8211,7 +8340,8 @@ return;
<a href="#DbRepattr">attributes</a> device and/or reading will not be considered. <br><br> <a href="#DbRepattr">attributes</a> device and/or reading will not be considered. <br><br>
<ul> <ul>
<b>input format: </b> set &lt;name&gt; deviceRename &lt;old device name&gt;,&lt;new device name&gt; <br> <b>Example: </b> <br>
set &lt;name&gt; deviceRename &lt;old device name&gt;,&lt;new device name&gt; <br>
# The amount of renamed device names (datasets) will be displayed in reading "device_renamed". <br> # The amount of renamed device names (datasets) will be displayed in reading "device_renamed". <br>
# If the device name to be renamed was not found in the database, a WARNUNG will appear in reading "device_not_renamed". <br> # If the device name to be renamed was not found in the database, a WARNUNG will appear in reading "device_not_renamed". <br>
# Appropriate entries will be written to Logfile if verbose >= 3 is set. # Appropriate entries will be written to Logfile if verbose >= 3 is set.
@ -8597,7 +8727,8 @@ return;
<a href="#DbRepattr">attributes</a> device and/or reading will not be considered. <br><br> <a href="#DbRepattr">attributes</a> device and/or reading will not be considered. <br><br>
<ul> <ul>
<b>input format: </b> set &lt;name&gt; readingRename &lt;old reading name&gt;,&lt;new reading name&gt; <br> <b>Example: </b> <br>
set &lt;name&gt; readingRename &lt;old reading name&gt;,&lt;new reading name&gt; <br>
# The amount of renamed reading names (datasets) will be displayed in reading "reading_renamed". <br> # The amount of renamed reading names (datasets) will be displayed in reading "reading_renamed". <br>
# If the reading name to be renamed was not found in the database, a WARNUNG will appear in reading "reading_not_renamed". <br> # If the reading name to be renamed was not found in the database, a WARNUNG will appear in reading "reading_not_renamed". <br>
# Appropriate entries will be written to Logfile if verbose >= 3 is set. # Appropriate entries will be written to Logfile if verbose >= 3 is set.
@ -9429,7 +9560,8 @@ sub bdump {
dynamisch berechneter Zeitgrenzen zum Ausführungszeitpunkt erfolgen. </li> dynamisch berechneter Zeitgrenzen zum Ausführungszeitpunkt erfolgen. </li>
<li> Export von Datensätzen in ein File im CSV-Format </li> <li> Export von Datensätzen in ein File im CSV-Format </li>
<li> Import von Datensätzen aus File im CSV-Format </li> <li> Import von Datensätzen aus File im CSV-Format </li>
<li> Umbenennen von Device-Namen in Datenbanksätzen </li> <li> Umbenennen von Device/Readings in Datenbanksätzen </li>
<li> Ändern von Reading-Werten (VALUES) in der Datenbank </li>
<li> automatisches Umbenennen von Device-Namen in Datenbanksätzen und DbRep-Definitionen nach FHEM "rename" <li> automatisches Umbenennen von Device-Namen in Datenbanksätzen und DbRep-Definitionen nach FHEM "rename"
Befehl (siehe <a href="#DbRepAutoRename">DbRep-Agent</a>) </li> Befehl (siehe <a href="#DbRepAutoRename">DbRep-Agent</a>) </li>
<li> Ausführen von beliebigen Benutzer spezifischen SQL-Kommandos </li> <li> Ausführen von beliebigen Benutzer spezifischen SQL-Kommandos </li>
@ -9543,6 +9675,39 @@ sub bdump {
</ul> </ul>
<li><b> cancelDump </b> - bricht einen laufenden Datenbankdump ab. </li> <br> <li><b> cancelDump </b> - bricht einen laufenden Datenbankdump ab. </li> <br>
<li><b> changeValue </b> - ändert den gespeicherten Wert eines Readings.
Ist die Selektion auf bestimmte Device/Reading-Kombinationen durch die
<a href="#DbRepattr">Attribute</a> "device" bzw. "reading" beschränkt, werden sie genauso
berücksichtigt wie gesetzte Zeitgrenzen (Attribute time.*). <br>
Fehlen diese Beschränkungen, wird die gesamte Datenbank durchsucht und der angegebene Wert
geändert. <br><br>
<ul>
<b>Beispiel: </b> <br>
set &lt;name&gt; changeValue "&lt;alter String&gt;","&lt;neuer String&gt;" <br>
# der alte String wird in den neuen String geändert. <br>
# Beide Strings können Leerzeichen enthalten. Die Werte sind in Quotes zu setzen und durch Komma zu trennen.
<br><br>
Zusammengefasst sind die zur Steuerung von changeValue relevanten Attribute: <br><br>
<ul>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> <b>device</b> </td><td>: Selektion nur von Datensätzen die &lt;device&gt; enthalten </td></tr>
<tr><td> <b>reading</b> </td><td>: Selektion nur von Datensätzen die &lt;reading&gt; enthalten </td></tr>
<tr><td> <b>time.*</b> </td><td>: eine Reihe von Attributen zur Zeitabgrenzung </td></tr>
</table>
</ul>
<br>
<br>
<b>Hinweis:</b> <br>
Obwohl die Funktion selbst non-blocking ausgelegt ist, sollte das zugeordnete DbLog-Device
im asynchronen Modus betrieben werden um ein Blockieren von FHEMWEB zu vermeiden (Tabellen-Lock). <br><br>
</li> <br>
</ul>
<li><b> countEntries [history | current] </b> <li><b> countEntries [history | current] </b>
- liefert die Anzahl der Tabelleneinträge (default: history) in den gegebenen - liefert die Anzahl der Tabelleneinträge (default: history) in den gegebenen
@ -9645,7 +9810,8 @@ sub bdump {
Reading werden nicht berücksichtigt. <br><br> Reading werden nicht berücksichtigt. <br><br>
<ul> <ul>
<b>Eingabeformat: </b> set &lt;name&gt; deviceRename &lt;alter Devicename&gt;,&lt;neuer Devicename&gt; <br> <b>Beispiel: </b><br>
set &lt;name&gt; deviceRename &lt;alter Devicename&gt;,&lt;neuer Devicename&gt; <br>
# Die Anzahl der umbenannten Device-Datensätze wird im Reading "device_renamed" ausgegeben. <br> # Die Anzahl der umbenannten Device-Datensätze wird im Reading "device_renamed" ausgegeben. <br>
# Wird der umzubenennende Gerätename in der Datenbank nicht gefunden, wird eine WARNUNG im Reading "device_not_renamed" ausgegeben. <br> # Wird der umzubenennende Gerätename in der Datenbank nicht gefunden, wird eine WARNUNG im Reading "device_not_renamed" ausgegeben. <br>
# Entsprechende Einträge erfolgen auch im Logfile mit verbose=3 # Entsprechende Einträge erfolgen auch im Logfile mit verbose=3
@ -10039,7 +10205,8 @@ sub bdump {
Device bzw. Reading werden nicht berücksichtigt. <br><br> Device bzw. Reading werden nicht berücksichtigt. <br><br>
<ul> <ul>
<b>Eingabeformat: </b> set &lt;name&gt; readingRename &lt;alter Readingname&gt;,&lt;neuer Readingname&gt; <br> <b>Beispiel: </b><br>
set &lt;name&gt; readingRename &lt;alter Readingname&gt;,&lt;neuer Readingname&gt; <br>
# Die Anzahl der umbenannten Device-Datensätze wird im Reading "reading_renamed" # Die Anzahl der umbenannten Device-Datensätze wird im Reading "reading_renamed"
ausgegeben. <br> ausgegeben. <br>
# Wird der umzubenennende Readingname in der Datenbank nicht gefunden, wird eine # Wird der umzubenennende Readingname in der Datenbank nicht gefunden, wird eine