93_DbRep: SQL Wildcard (%) usage possible as placeholder in a reading- or device-list. Forum: #101756, internal code changes of SQL statement generation

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@20138 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2019-09-09 17:29:19 +00:00
parent 7971983213
commit dc09d933dc
2 changed files with 424 additions and 210 deletions

View File

@ -1,5 +1,8 @@
# 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: SQL Wildcard (%) usage possible as placeholder in a
reading- or device-list. Forum: #101756,
internal code changes of SQL statement generation
- feature: 14_SD_BELL: added model Grothe_Mistral_SE_03 | Grothe_Mistral_SE_01 - feature: 14_SD_BELL: added model Grothe_Mistral_SE_03 | Grothe_Mistral_SE_01
fixed repeats Heidemann_|_Heidemann_HX_|_VTX-BELL fixed repeats Heidemann_|_Heidemann_HX_|_VTX-BELL
- bugfix: 14_SD_UT: fixed Manax MX-RCS250 | mumbi button ALL - bugfix: 14_SD_UT: fixed Manax MX-RCS250 | mumbi button ALL

View File

@ -58,6 +58,10 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern # Version History intern
our %DbRep_vNotesIntern = ( our %DbRep_vNotesIntern = (
"8.26.0" => "07.09.2019 make SQL Wildcard (\%) possible as placeholder in a reading list: https://forum.fhem.de/index.php/topic,101756.0.html ".
"sub DbRep_createUpdateSql deleted, new sub DbRep_createCommonSql ",
"8.25.0" => "01.09.2019 make SQL Wildcard (\%) possible as placeholder in a device list: https://forum.fhem.de/index.php/topic,101756.0.html ".
"sub DbRep_modAssociatedWith changed ",
"8.24.0" => "24.08.2019 devices marked as \"Associated With\" if possible, fhem.pl 20069 2019-08-27 08:36:02Z is needed ", "8.24.0" => "24.08.2019 devices marked as \"Associated With\" if possible, fhem.pl 20069 2019-08-27 08:36:02Z is needed ",
"8.23.1" => "26.08.2019 fix add newline at the end of DbRep_dbValue result, Forum: #103295 ", "8.23.1" => "26.08.2019 fix add newline at the end of DbRep_dbValue result, Forum: #103295 ",
"8.23.0" => "24.08.2019 prepared for devices marked as \"Associated With\" if possible ", "8.23.0" => "24.08.2019 prepared for devices marked as \"Associated With\" if possible ",
@ -158,6 +162,12 @@ our %DbRep_vNotesIntern = (
# Version History extern: # Version History extern:
our %DbRep_vNotesExtern = ( our %DbRep_vNotesExtern = (
"8.25.0" => "29.08.2019 If a list of devices in attribute \"device\" contains a SQL wildcard (\%), this wildcard is now "
."dissolved into separate devices if they are still existing in your FHEM configuration. "
."Please see <a href=\"https://forum.fhem.de/index.php/topic,101756.0.html\">this Forum Thread</a> "
."for further information. ",
"8.24.0" => "24.08.2019 Devices which are specified in attribute \"device\" are marked as \"Associated With\" if they are "
."still existing in your FHEM configuration. At least fhem.pl 20069 2019-08-27 08:36:02 is needed. ",
"8.22.0" => "23.08.2019 A new attribute \"fetchValueFn\" is provided. When fetching the database content, you are able to manipulate ". "8.22.0" => "23.08.2019 A new attribute \"fetchValueFn\" is provided. When fetching the database content, you are able to manipulate ".
"the value displayed from the VALUE database field before create the appropriate reading. ", "the value displayed from the VALUE database field before create the appropriate reading. ",
"8.21.0" => "28.04.2019 FHEM command \"dbReadingsVal\" implemented.", "8.21.0" => "28.04.2019 FHEM command \"dbReadingsVal\" implemented.",
@ -2834,7 +2844,7 @@ sub count_DoParse($) {
if ($@) { if ($@) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
return "$name|''|$device|$reading|''|$err|$table"; return "$name|''|$device|''|$err|$table";
} }
# 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
@ -2889,7 +2899,7 @@ sub count_DoParse($) {
$err = encode_base64($@,""); $err = encode_base64($@,"");
Log3 ($name, 2, "DbRep $name - $@"); Log3 ($name, 2, "DbRep $name - $@");
$dbh->disconnect; $dbh->disconnect;
return "$name|''|$device|$reading|''|$err|$table"; return "$name|''|$device|''|$err|$table";
} }
if($ced) { if($ced) {
@ -2971,7 +2981,8 @@ sub count_ParseDone($) {
} else { } else {
my $ds = $device."__" if ($device); my $ds = $device."__" if ($device);
my $rds = $reading."__" if ($reading); my $rds = $reading."__" if ($reading);
$reading_runtime_string = $rsf.$ds.$rds."COUNT_".$table."__".$runtime_string; # $reading_runtime_string = $rsf.$ds.$rds."COUNT_".$table."__".$runtime_string;
$reading_runtime_string = $rsf."COUNT_".$table."__".$runtime_string;
} }
ReadingsBulkUpdateValue ($hash, $reading_runtime_string, $c?$c:"-"); ReadingsBulkUpdateValue ($hash, $reading_runtime_string, $c?$c:"-");
@ -4264,7 +4275,7 @@ sub currentfillup_Push($) {
my $dblogname = $dbloghash->{NAME}; my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret}; my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0; my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0;
my ($err,$sth,$sql,$devs,$danz,$ranz); my ($err,$sth,$sql,$selspec,$addon,@dwc,@rwc);
# Background-Startzeit # Background-Startzeit
my $bst = [gettimeofday]; my $bst = [gettimeofday];
@ -4285,90 +4296,40 @@ sub currentfillup_Push($) {
my ($IsTimeSet,$IsAggrSet) = DbRep_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) = DbRep_specsForSql($hash,$device,$reading);
# SQL-Startzeit # SQL-Startzeit
my $st = [gettimeofday]; my $st = [gettimeofday];
# insert history mit/ohne primary key # insert history mit/ohne primary key
# SQL zusammenstellen für DB-Operation # SQL zusammenstellen für DB-Operation
if ($usepkc && $dbloghash->{MODEL} eq 'MYSQL') { if ($usepkc && $dbloghash->{MODEL} eq 'MYSQL') {
$sql = "INSERT IGNORE INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where "; $selspec = "INSERT IGNORE INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%)); $addon = "group by timestamp,device,reading";
$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 ($IsTimeSet) {
$sql .= "TIMESTAMP >= '$runtime_string_first' AND TIMESTAMP < '$runtime_string_next' ";
} else {
$sql .= "1 ";
}
$sql .= "group by timestamp,device,reading ;";
} elsif ($usepkc && $dbloghash->{MODEL} eq 'SQLITE') { } elsif ($usepkc && $dbloghash->{MODEL} eq 'SQLITE') {
$sql = "INSERT OR IGNORE INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where "; $selspec = "INSERT OR IGNORE INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%)); $addon = "group by timestamp,device,reading";
$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 ($IsTimeSet) {
$sql .= "TIMESTAMP >= '$runtime_string_first' AND TIMESTAMP < '$runtime_string_next' ";
} else {
$sql .= "1 ";
}
$sql .= "group by timestamp,device,reading ;";
} elsif ($usepkc && $dbloghash->{MODEL} eq 'POSTGRESQL') { } elsif ($usepkc && $dbloghash->{MODEL} eq 'POSTGRESQL') {
$sql = "INSERT INTO current (DEVICE,TIMESTAMP,READING) SELECT device, (array_agg(timestamp ORDER BY reading ASC))[1], reading FROM history where "; $selspec = "INSERT INTO current (DEVICE,TIMESTAMP,READING) SELECT device, (array_agg(timestamp ORDER BY reading ASC))[1], reading FROM history where";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%)); $addon = "group by device,reading ON CONFLICT ($pkc) DO NOTHING";
$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 ($IsTimeSet) {
$sql .= "TIMESTAMP >= '$runtime_string_first' AND TIMESTAMP < '$runtime_string_next' ";
} else {
$sql .= "true ";
}
$sql .= "group by device,reading ON CONFLICT ($pkc) DO NOTHING; ";
} else { } else {
if($dbloghash->{MODEL} ne 'POSTGRESQL') { if($dbloghash->{MODEL} ne 'POSTGRESQL') {
# MySQL und SQLite # MySQL und SQLite
$sql = "INSERT INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where "; $selspec = "INSERT INTO current (TIMESTAMP,DEVICE,READING) SELECT timestamp,device,reading FROM history where";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%)); $addon = "group by device,reading";
$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 ($IsTimeSet) {
$sql .= "TIMESTAMP >= '$runtime_string_first' AND TIMESTAMP < '$runtime_string_next' ";
} else {
$sql .= "1 ";
}
$sql .= "group by device,reading ;";
} else { } else {
# PostgreSQL # PostgreSQL
$sql = "INSERT INTO current (DEVICE,TIMESTAMP,READING) SELECT device, (array_agg(timestamp ORDER BY reading ASC))[1], reading FROM history where "; $selspec = "INSERT INTO current (DEVICE,TIMESTAMP,READING) SELECT device, (array_agg(timestamp ORDER BY reading ASC))[1], reading FROM history where";
$sql .= "DEVICE LIKE '$devs' AND " if($danz <= 1 && $devs !~ m(^%$) && $devs =~ m(\%)); $addon = "group by device,reading";
$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-Statement zusammenstellen
$sql .= "READING IN ($reading) AND " if($ranz > 1); if ($IsTimeSet || $IsAggrSet) {
if ($IsTimeSet) { $sql = DbRep_createCommonSql($hash,$selspec,$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",$addon);
$sql .= "TIMESTAMP >= '$runtime_string_first' AND TIMESTAMP < '$runtime_string_next' ";
} else { } else {
$sql .= "true "; $sql = DbRep_createCommonSql($hash,$selspec,$device,$reading,undef,undef,$addon);
}
$sql .= "group by device,reading;";
}
} }
# Log SQL Statement # Log SQL Statement
@ -4611,10 +4572,11 @@ sub changeval_Push($) {
# SQL zusammenstellen für DB-Update # SQL zusammenstellen für DB-Update
my $addon = $old =~ /%/?"WHERE VALUE LIKE '$old'":"WHERE VALUE='$old'"; my $addon = $old =~ /%/?"WHERE VALUE LIKE '$old'":"WHERE VALUE='$old'";
my $selspec = "UPDATE $table SET TIMESTAMP=TIMESTAMP,VALUE='$new' $addon AND ";
if ($IsTimeSet) { if ($IsTimeSet) {
$sql = DbRep_createUpdateSql($hash,$table,"TIMESTAMP=TIMESTAMP,VALUE='$new' $addon",$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",''); $sql = DbRep_createCommonSql($hash,$selspec,$device,$reading,"'$runtime_string_first'","'$runtime_string_next'",'');
} else { } else {
$sql = DbRep_createUpdateSql($hash,$table,"TIMESTAMP=TIMESTAMP,VALUE='$new' $addon",$device,$reading,undef,undef,''); $sql = DbRep_createCommonSql($hash,$selspec,$device,$reading,undef,undef,'');
} }
Log3 ($name, 4, "DbRep $name - SQL execute: $sql"); Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
$sth = $dbh->prepare($sql) ; $sth = $dbh->prepare($sql) ;
@ -8329,15 +8291,14 @@ sub DbRep_reduceLog($) {
$filter = 1; $filter = 1;
} }
my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$d,$r); my ($idevs,$idevswc,$idanz,$ireading,$iranz,$irdswc,$edevs,$edevswc,$edanz,$ereading,$eranz,$erdswc) = DbRep_specsForSql($hash,$d,$r);
# 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) = DbRep_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");
my $sql; my $sql;
my $table = "history"; my $selspec = "SELECT TIMESTAMP,DEVICE,'',READING,VALUE FROM history where ";
my $selspec = "TIMESTAMP,DEVICE,'',READING,VALUE";
my $addon = "ORDER BY TIMESTAMP ASC"; my $addon = "ORDER BY TIMESTAMP ASC";
if($filter) { if($filter) {
@ -8346,9 +8307,9 @@ sub DbRep_reduceLog($) {
.($a[-1] =~ /^INCLUDE=(.+):(.+)$/i ? "DEVICE like '$1' AND READING like '$2' AND " : '') .($a[-1] =~ /^INCLUDE=(.+):(.+)$/i ? "DEVICE like '$1' AND READING like '$2' AND " : '')
."TIMESTAMP <= '$ots'".($nts?" AND TIMESTAMP >= '$nts' ":" ")."ORDER BY TIMESTAMP ASC"; ."TIMESTAMP <= '$ots'".($nts?" AND TIMESTAMP >= '$nts' ":" ")."ORDER BY TIMESTAMP ASC";
} elsif ($IsTimeSet || $IsAggrSet) { } elsif ($IsTimeSet || $IsAggrSet) {
$sql = DbRep_createSelectSql($hash,$table,$selspec,$d,$r,"'$nts'","'$ots'",$addon); $sql = DbRep_createCommonSql($hash,$selspec,$d,$r,"'$nts'","'$ots'",$addon);
} else { } else {
$sql = DbRep_createSelectSql($hash,$table,$selspec,$d,$r,undef,undef,$addon); $sql = DbRep_createCommonSql($hash,$selspec,$d,$r,undef,undef,$addon);
} }
Log3 ($name, 4, "DbRep $name - SQL execute: $sql"); Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
@ -8361,7 +8322,10 @@ sub DbRep_reduceLog($) {
Log3 ($name, 3, "DbRep $name - reduceLog requested with options: " Log3 ($name, 3, "DbRep $name - reduceLog requested with options: "
.(($average) ? "$average" : '') .(($average) ? "$average" : '')
.($filter ? ((($average && $filter) ? ", " : '').(uc((split('=',$a[-1]))[0]).'='.(split('=',$a[-1]))[1])) : .($filter ? ((($average && $filter) ? ", " : '').(uc((split('=',$a[-1]))[0]).'='.(split('=',$a[-1]))[1])) :
((($idanz || $iranz) ? " INCLUDE -> " : '').($idanz ? "Devs: ".$idevs : '').($iranz ? " Readings: ".$ireading : '').(($edanz || $eranz) ? " EXCLUDE -> " : '').($edanz ? "Devs: ".$edevs : '').($eranz ? " Readings: ".$ereading : '')) )); ((($idanz || $idevswc || $iranz || $irdswc) ? " INCLUDE -> " : '').
(($idanz || $idevswc)? "Devs: ".($idevs?$idevs:'').($idevswc?$idevswc:'') : '').(($iranz || $irdswc) ? " Readings: ".($ireading?$ireading:'').($irdswc?$irdswc:'') : '').
(($edanz || $edevswc || $eranz || $erdswc) ? " EXCLUDE -> " : '').
(($edanz || $edevswc)? "Devs: ".($edevs?$edevs:'').($edevswc?$edevswc:'') : '').(($eranz || $erdswc) ? " Readings: ".($ereading?$ereading:'').($erdswc?$erdswc:'') : '')) ));
if ($ots) { if ($ots) {
my ($sth_del, $sth_upd, $sth_delD, $sth_updD, $sth_get); my ($sth_del, $sth_upd, $sth_delD, $sth_updD, $sth_get);
@ -8854,17 +8818,17 @@ return;
} }
#################################################################################################### ####################################################################################################
# SQL-Statement zusammenstellen für DB-Abfrage # SQL-Statement zusammenstellen Common
#################################################################################################### ####################################################################################################
sub DbRep_createSelectSql($$$$$$$$) { sub DbRep_createCommonSql ($$$$$$$) {
my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_; my ($hash,$selspec,$device,$reading,$tf,$tn,$addon) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $dbmodel = $hash->{dbloghash}{MODEL}; my $dbmodel = $hash->{dbloghash}{MODEL};
my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter
my ($sql,$vf);
my $tnfull = 0; my $tnfull = 0;
my ($sql,$vf,@dwc,@rwc);
my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$device,$reading); my ($idevs,$idevswc,$idanz,$ireading,$iranz,$irdswc,$edevs,$edevswc,$edanz,$ereading,$eranz,$erdswc) = DbRep_specsForSql($hash,$device,$reading);
if($tn && $tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) { if($tn && $tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
$tnfull = 1; $tnfull = 1;
@ -8878,23 +8842,69 @@ sub DbRep_createSelectSql($$$$$$$$) {
} }
} }
$sql = "SELECT $selspec FROM $table where "; $sql = $selspec." ";
# included devices # included devices
$sql .= "DEVICE LIKE '$idevs' AND " if($idanz <= 1 && $idevs !~ m(^%$) && $idevs =~ m(\%)); $sql .= "( " if(($idanz || $idevswc) && $idevs !~ m(^%$));
$sql .= "DEVICE = '$idevs' AND " if($idanz <= 1 && $idevs !~ m(\%)); if($idevswc && $idevs !~ m(^%$)) {
$sql .= "DEVICE IN ($idevs) AND " if($idanz > 1); @dwc = split(",",$idevswc);
my $i = 1;
my $len = scalar(@dwc);
foreach(@dwc) {
if($i<$len) {
$sql .= "DEVICE LIKE '$_' OR ";
} else {
$sql .= "DEVICE LIKE '$_' ";
}
$i++;
}
if($idanz) {
$sql .= "OR ";
}
}
$sql .= "DEVICE = '$idevs' " if($idanz == 1 && $idevs && $idevs !~ m(^%$));
$sql .= "DEVICE IN ($idevs) " if($idanz > 1);
$sql .= ") AND " if(($idanz || $idevswc) && $idevs !~ m(^%$));
# excluded devices # excluded devices
$sql .= "DEVICE NOT LIKE '$edevs' AND " if($edanz && $edanz == 1 && $edevs =~ m(\%)); if($edevswc) {
$sql .= "DEVICE != '$edevs' AND " if($edanz && $edanz == 1 && $edevs !~ m(\%)); @dwc = split(",",$edevswc);
$sql .= "DEVICE NOT IN ($edevs) AND " if($edanz > 1); foreach(@dwc) {
$sql .= "DEVICE NOT LIKE '$_' AND ";
}
}
$sql .= "DEVICE != '$edevs' " if($edanz == 1 && $edanz && $edevs !~ m(^%$));
$sql .= "DEVICE NOT IN ($edevs) " if($edanz > 1);
$sql .= "AND " if($edanz && $edevs !~ m(^%$));
# included readings # included readings
$sql .= "READING LIKE '$ireading' AND " if($iranz <= 1 && $ireading !~ m(^%$) && $ireading =~ m(\%)); $sql .= "( " if(($iranz || $irdswc) && $ireading !~ m(^%$));
$sql .= "READING = '$ireading' AND " if($iranz <= 1 && $ireading !~ m(\%)); if($irdswc && $ireading !~ m(^%$)) {
$sql .= "READING IN ($ireading) AND " if($iranz > 1); @rwc = split(",",$irdswc);
my $i = 1;
my $len = scalar(@rwc);
foreach(@rwc) {
if($i<$len) {
$sql .= "READING LIKE '$_' OR ";
} else {
$sql .= "READING LIKE '$_' ";
}
$i++;
}
if($iranz) {
$sql .= "OR ";
}
}
$sql .= "READING = '$ireading' " if($iranz == 1 && $ireading && $ireading !~ m(\%));
$sql .= "READING IN ($ireading) " if($iranz > 1);
$sql .= ") AND " if(($iranz || $irdswc) && $ireading !~ m(^%$));
# excluded readings # excluded readings
$sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); if($erdswc) {
$sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); @dwc = split(",",$erdswc);
$sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); foreach(@dwc) {
$sql .= "READING NOT LIKE '$_' AND ";
}
}
$sql .= "READING != '$ereading' " if($eranz && $eranz == 1 && $ereading !~ m(\%));
$sql .= "READING NOT IN ($ereading) " if($eranz > 1);
$sql .= "AND " if($eranz && $ereading !~ m(^%$));
# add valueFilter # add valueFilter
$sql .= $vf if(defined $vf); $sql .= $vf if(defined $vf);
# Timestamp Filter # Timestamp Filter
@ -8913,19 +8923,19 @@ return $sql;
} }
#################################################################################################### ####################################################################################################
# SQL-Statement zusammenstellen für DB-Updates # SQL-Statement zusammenstellen für DB-Abfrage Select
#################################################################################################### ####################################################################################################
sub DbRep_createUpdateSql($$$$$$$$) { sub DbRep_createSelectSql($$$$$$$$) {
my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_; my ($hash,$table,$selspec,$device,$reading,$tf,$tn,$addon) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $dbmodel = $hash->{dbloghash}{MODEL}; my $dbmodel = $hash->{dbloghash}{MODEL};
my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter
my ($sql,$vf);
my $tnfull = 0; my $tnfull = 0;
my ($sql,$vf,@dwc,@rwc);
my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$device,$reading); my ($idevs,$idevswc,$idanz,$ireading,$iranz,$irdswc,$edevs,$edevswc,$edanz,$ereading,$eranz,$erdswc) = DbRep_specsForSql($hash,$device,$reading);
if($tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) { if($tn && $tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
$tnfull = 1; $tnfull = 1;
} }
@ -8937,23 +8947,69 @@ sub DbRep_createUpdateSql($$$$$$$$) {
} }
} }
$sql = "UPDATE $table SET $selspec AND "; $sql = "SELECT $selspec FROM $table where ";
# included devices # included devices
$sql .= "DEVICE LIKE '$idevs' AND " if($idanz <= 1 && $idevs !~ m(^%$) && $idevs =~ m(\%)); $sql .= "( " if(($idanz || $idevswc) && $idevs !~ m(^%$));
$sql .= "DEVICE = '$idevs' AND " if($idanz <= 1 && $idevs !~ m(\%)); if($idevswc && $idevs !~ m(^%$)) {
$sql .= "DEVICE IN ($idevs) AND " if($idanz > 1); @dwc = split(",",$idevswc);
my $i = 1;
my $len = scalar(@dwc);
foreach(@dwc) {
if($i<$len) {
$sql .= "DEVICE LIKE '$_' OR ";
} else {
$sql .= "DEVICE LIKE '$_' ";
}
$i++;
}
if($idanz) {
$sql .= "OR ";
}
}
$sql .= "DEVICE = '$idevs' " if($idanz == 1 && $idevs && $idevs !~ m(^%$));
$sql .= "DEVICE IN ($idevs) " if($idanz > 1);
$sql .= ") AND " if(($idanz || $idevswc) && $idevs !~ m(^%$));
# excluded devices # excluded devices
$sql .= "DEVICE NOT LIKE '$edevs' AND " if($edanz && $edanz == 1 && $edevs =~ m(\%)); if($edevswc) {
$sql .= "DEVICE != '$edevs' AND " if($edanz && $edanz == 1 && $edevs !~ m(\%)); @dwc = split(",",$edevswc);
$sql .= "DEVICE NOT IN ($edevs) AND " if($edanz > 1); foreach(@dwc) {
$sql .= "DEVICE NOT LIKE '$_' AND ";
}
}
$sql .= "DEVICE != '$edevs' " if($edanz == 1 && $edanz && $edevs !~ m(^%$));
$sql .= "DEVICE NOT IN ($edevs) " if($edanz > 1);
$sql .= "AND " if($edanz && $edevs !~ m(^%$));
# included readings # included readings
$sql .= "READING LIKE '$ireading' AND " if($iranz <= 1 && $ireading !~ m(^%$) && $ireading =~ m(\%)); $sql .= "( " if(($iranz || $irdswc) && $ireading !~ m(^%$));
$sql .= "READING = '$ireading' AND " if($iranz <= 1 && $ireading !~ m(\%)); if($irdswc && $ireading !~ m(^%$)) {
$sql .= "READING IN ($ireading) AND " if($iranz > 1); @rwc = split(",",$irdswc);
my $i = 1;
my $len = scalar(@rwc);
foreach(@rwc) {
if($i<$len) {
$sql .= "READING LIKE '$_' OR ";
} else {
$sql .= "READING LIKE '$_' ";
}
$i++;
}
if($iranz) {
$sql .= "OR ";
}
}
$sql .= "READING = '$ireading' " if($iranz == 1 && $ireading && $ireading !~ m(\%));
$sql .= "READING IN ($ireading) " if($iranz > 1);
$sql .= ") AND " if(($iranz || $irdswc) && $ireading !~ m(^%$));
# excluded readings # excluded readings
$sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); if($erdswc) {
$sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); @dwc = split(",",$erdswc);
$sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); foreach(@dwc) {
$sql .= "READING NOT LIKE '$_' AND ";
}
}
$sql .= "READING != '$ereading' " if($eranz && $eranz == 1 && $ereading !~ m(\%));
$sql .= "READING NOT IN ($ereading) " if($eranz > 1);
$sql .= "AND " if($eranz && $ereading !~ m(^%$));
# add valueFilter # add valueFilter
$sql .= $vf if(defined $vf); $sql .= $vf if(defined $vf);
# Timestamp Filter # Timestamp Filter
@ -8979,15 +9035,15 @@ sub DbRep_createDeleteSql($$$$$$$) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $dbmodel = $hash->{dbloghash}{MODEL}; my $dbmodel = $hash->{dbloghash}{MODEL};
my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter my $valfilter = AttrVal($name, "valueFilter", undef); # Wertefilter
my ($sql,$vf);
my $tnfull = 0; my $tnfull = 0;
my ($sql,$vf,@dwc,@rwc);
if($table eq "current") { if($table eq "current") {
$sql = "delete FROM $table; "; $sql = "delete FROM $table; ";
return $sql; return $sql;
} }
my ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz) = DbRep_specsForSql($hash,$device,$reading); my ($idevs,$idevswc,$idanz,$ireading,$iranz,$irdswc,$edevs,$edevswc,$edanz,$ereading,$eranz,$erdswc) = DbRep_specsForSql($hash,$device,$reading);
if($tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) { if($tn =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
$tnfull = 1; $tnfull = 1;
@ -9003,21 +9059,67 @@ sub DbRep_createDeleteSql($$$$$$$) {
$sql = "delete FROM $table where "; $sql = "delete FROM $table where ";
# included devices # included devices
$sql .= "DEVICE LIKE '$idevs' AND " if($idanz <= 1 && $idevs !~ m(^%$) && $idevs =~ m(\%)); $sql .= "( " if(($idanz || $idevswc) && $idevs !~ m(^%$));
$sql .= "DEVICE = '$idevs' AND " if($idanz <= 1 && $idevs !~ m(\%)); if($idevswc && $idevs !~ m(^%$)) {
$sql .= "DEVICE IN ($idevs) AND " if($idanz > 1); @dwc = split(",",$idevswc);
my $i = 1;
my $len = scalar(@dwc);
foreach(@dwc) {
if($i<$len) {
$sql .= "DEVICE LIKE '$_' OR ";
} else {
$sql .= "DEVICE LIKE '$_' ";
}
$i++;
}
if($idanz) {
$sql .= "OR ";
}
}
$sql .= "DEVICE = '$idevs' " if($idanz == 1 && $idevs && $idevs !~ m(^%$));
$sql .= "DEVICE IN ($idevs) " if($idanz > 1);
$sql .= ") AND " if(($idanz || $idevswc) && $idevs !~ m(^%$));
# excluded devices # excluded devices
$sql .= "DEVICE NOT LIKE '$edevs' AND " if($edanz && $edanz == 1 && $edevs =~ m(\%)); if($edevswc) {
$sql .= "DEVICE != '$edevs' AND " if($edanz && $edanz == 1 && $edevs !~ m(\%)); @dwc = split(",",$edevswc);
$sql .= "DEVICE NOT IN ($edevs) AND " if($edanz > 1); foreach(@dwc) {
$sql .= "DEVICE NOT LIKE '$_' AND ";
}
}
$sql .= "DEVICE != '$edevs' " if($edanz == 1 && $edanz && $edevs !~ m(^%$));
$sql .= "DEVICE NOT IN ($edevs) " if($edanz > 1);
$sql .= "AND " if($edanz && $edevs !~ m(^%$));
# included readings # included readings
$sql .= "READING LIKE '$ireading' AND " if($iranz <= 1 && $ireading !~ m(^%$) && $ireading =~ m(\%)); $sql .= "( " if(($iranz || $irdswc) && $ireading !~ m(^%$));
$sql .= "READING = '$ireading' AND " if($iranz <= 1 && $ireading !~ m(\%)); if($irdswc && $ireading !~ m(^%$)) {
$sql .= "READING IN ($ireading) AND " if($iranz > 1); @rwc = split(",",$irdswc);
my $i = 1;
my $len = scalar(@rwc);
foreach(@rwc) {
if($i<$len) {
$sql .= "READING LIKE '$_' OR ";
} else {
$sql .= "READING LIKE '$_' ";
}
$i++;
}
if($iranz) {
$sql .= "OR ";
}
}
$sql .= "READING = '$ireading' " if($iranz == 1 && $ireading && $ireading !~ m(\%));
$sql .= "READING IN ($ireading) " if($iranz > 1);
$sql .= ") AND " if(($iranz || $irdswc) && $ireading !~ m(^%$));
# excluded readings # excluded readings
$sql .= "READING NOT LIKE '$ereading' AND " if($eranz && $eranz == 1 && $ereading =~ m(\%)); if($erdswc) {
$sql .= "READING != '$ereading' AND " if($eranz && $eranz == 1 && $ereading !~ m(\%)); @dwc = split(",",$erdswc);
$sql .= "READING NOT IN ($ereading) AND " if($eranz > 1); foreach(@dwc) {
$sql .= "READING NOT LIKE '$_' AND ";
}
}
$sql .= "READING != '$ereading' " if($eranz && $eranz == 1 && $ereading !~ m(\%));
$sql .= "READING NOT IN ($ereading) " if($eranz > 1);
$sql .= "AND " if($eranz && $ereading !~ m(^%$));
# add valueFilter # add valueFilter
$sql .= $vf if(defined $vf); $sql .= $vf if(defined $vf);
# Timestamp Filter # Timestamp Filter
@ -9040,10 +9142,12 @@ return $sql;
sub DbRep_specsForSql($$$) { sub DbRep_specsForSql($$$) {
my ($hash,$device,$reading) = @_; my ($hash,$device,$reading) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my (@idvspcs,@edvspcs,@idvs,@edvs,@idvswc,@edvswc,@residevs,@residevswc);
my ($nl,$nlwc) = ("","");
##### inkludierte / excludierte Devices und deren Anzahl ermitteln ##### ##### inkludierte / excludierte Devices und deren Anzahl ermitteln #####
my ($idevice,$edevice) = ('',''); my ($idevice,$edevice) = ('','');
my ($idevs,$edevs) = ('',''); my ($idevs,$idevswc,$edevs,$edevswc) = ('','','','');
my ($idanz,$edanz) = (0,0); my ($idanz,$edanz) = (0,0);
if($device =~ /EXCLUDE=/i) { if($device =~ /EXCLUDE=/i) {
($idevice,$edevice) = split(/EXCLUDE=/i,$device); ($idevice,$edevice) = split(/EXCLUDE=/i,$device);
@ -9052,35 +9156,102 @@ sub DbRep_specsForSql($$$) {
$idevice = $device; $idevice = $device;
} }
# Devices inkludiert # Devices exkludiert
my @idvspcs = devspec2array($idevice); if($edevice) {
$idevs = join(",",@idvspcs); @edvs = split(",",$edevice);
$idevs =~ s/'/''/g; # escape ' with '' foreach my $e (@edvs) {
$e =~ s/%/\.*/g if($e !~ /^%$/); # SQL Wildcard % auflösen
@edvspcs = devspec2array($e);
@edvspcs = map {s/\.\*/%/g; $_; } @edvspcs;
if((map {$_ =~ /%/;} @edvspcs) && $edevice !~ /^%$/) { # Devices mit Wildcard (%) erfassen, die nicht aufgelöst werden konnten
$edevswc .= "," if($edevswc);
$edevswc .= join(",",@edvspcs);
} else {
$edevs .= "," if($edevs);
$edevs .= join(",",@edvspcs);
}
}
}
$edanz = split(",",$edevs); # Anzahl der exkludierten Elemente (Lauf1)
$idanz = $#idvspcs+1; # Devices inkludiert
@idvs = split(",",$idevice);
foreach my $d (@idvs) {
$d =~ s/%/\.*/g if($d !~ /^%$/); # SQL Wildcard % auflösen
@idvspcs = devspec2array($d);
@idvspcs = map {s/\.\*/%/g; $_; } @idvspcs;
if((map {$_ =~ /%/;} @idvspcs) && $idevice !~ /^%$/) { # Devices mit Wildcard (%) erfassen, die nicht aufgelöst werden konnten
$idevswc .= "," if($idevswc);
$idevswc .= join(",",@idvspcs);
} else {
$idevs .= "," if($idevs);
$idevs .= join(",",@idvspcs);
}
}
$idanz = split(",",$idevs); # Anzahl der inkludierten Elemente (Lauf1)
Log3 $name, 5, "DbRep $name - Devices for operation - \n"
."included ($idanz): $idevs \n"
."included with wildcard: $idevswc \n"
."excluded ($edanz): $edevs \n"
."excluded with wildcard: $edevswc";
# exkludierte Devices aus inkludierten entfernen (aufgelöste)
@idvs = split(",",$idevs);
@edvs = split(",",$edevs);
foreach my $in (@idvs) {
my $inc = 1;
foreach(@edvs) {
next if($in ne $_);
$inc = 0;
$nl .= "|" if($nl);
$nl .= $_; # Liste der entfernten devices füllen
}
push(@residevs, $in) if($inc);
}
$edevs = join(",", map {($_ !~ /$nl/)?$_:();} @edvs) if($nl);
# exkludierte Devices aus inkludierten entfernen (wildcard konnte nicht aufgelöst werden)
@idvswc = split(",",$idevswc);
@edvswc = split(",",$edevswc);
foreach my $inwc (@idvswc) {
my $inc = 1;
foreach(@edvswc) {
next if($inwc ne $_);
$inc = 0;
$nlwc .= "|" if($nlwc);
$nlwc .= $_; # Liste der entfernten devices füllen
}
push(@residevswc, $inwc) if($inc);
}
$edevswc = join(",", map {($_ !~ /$nlwc/)?$_:();} @edvswc) if($nlwc);
# Log3($name, 1, "DbRep $name - nlwc: $nlwc, mwc: @mwc");
# Ergebnis zusammenfassen
$idevs = join(",",@residevs);
$idevs =~ s/'/''/g; # escape ' with ''
$idevswc = join(",",@residevswc);
$idevswc =~ s/'/''/g; # escape ' with ''
$idanz = split(",",$idevs); # Anzahl der inkludierten Elemente (Lauf2)
if($idanz > 1) { if($idanz > 1) {
$idevs =~ s/,/','/g; $idevs =~ s/,/','/g;
$idevs = "'".$idevs."'"; $idevs = "'".$idevs."'";
} }
# Devices exkludiert $edanz = split(",",$edevs); # Anzahl der exkludierten Elemente (Lauf2)
if($edevice) {
my @edvspcs = devspec2array($edevice);
$edevs = join(",",@edvspcs);
$edevs =~ s/'/''/g; # escape ' with ''
$edanz = $#edvspcs+1;
if($edanz > 1) { if($edanz > 1) {
$edevs =~ s/,/','/g; $edevs =~ s/,/','/g;
$edevs = "'".$edevs."'"; $edevs = "'".$edevs."'";
} }
}
Log3 $name, 5, "DbRep $name - Devices for operation - included: $idevs , excluded: $edevs";
##### inkludierte / excludierte Readings und deren Anzahl ermitteln ##### ##### inkludierte / excludierte Readings und deren Anzahl ermitteln #####
my ($ireading,$ereading) = ('',''); my ($ireading,$ereading) = ('','');
my ($iranz,$eranz) = (0,0); my ($iranz,$eranz) = (0,0);
my ($erdswc,$erdgs,$irdswc,$irdgs) = ('','','','');
my (@erds,@irds);
$reading =~ s/'/''/g; # escape ' with '' $reading =~ s/'/''/g; # escape ' with ''
if($reading =~ /EXCLUDE=/i) { if($reading =~ /EXCLUDE=/i) {
@ -9090,27 +9261,54 @@ sub DbRep_specsForSql($$$) {
$ireading = $reading; $ireading = $reading;
} }
if($ereading) {
@erds = split(",",$ereading);
foreach my $e (@erds) {
if($e =~ /%/ && $e !~ /^%$/) { # Readings mit Wildcard (%) erfassen
$erdswc .= "," if($erdswc);
$erdswc .= $e;
} else {
$erdgs .= "," if($erdgs);
$erdgs .= $e;
}
}
}
# Readings inkludiert # Readings inkludiert
my @ireads = split(",",$ireading); @irds = split(",",$ireading);
$iranz = $#ireads+1; foreach my $i (@irds) {
if($i =~ /%/ && $i !~ /^%$/) { # Readings mit Wildcard (%) erfassen
$irdswc .= "," if($irdswc);
$irdswc .= $i;
} else {
$irdgs .= "," if($irdgs);
$irdgs .= $i;
}
}
$iranz = split(",",$irdgs);
if($iranz > 1) { if($iranz > 1) {
$ireading =~ s/,/','/g; $irdgs =~ s/,/','/g;
$ireading = "'".$ireading."'"; $irdgs = "'".$irdgs."'";
} }
if($ereading) { if($ereading) {
# Readings exkludiert # Readings exkludiert
my @ereads = split(",",$ereading); $eranz = split(",",$erdgs);
$eranz = $#ereads+1;
if($eranz > 1) { if($eranz > 1) {
$ereading =~ s/,/','/g; $erdgs =~ s/,/','/g;
$ereading = "'".$ereading."'"; $erdgs = "'".$erdgs."'";
} }
} }
Log3 $name, 5, "DbRep $name - Readings for operation - included: $ireading, excluded: $ereading "; Log3 $name, 5, "DbRep $name - Readings for operation - \n"
."included ($iranz): $irdgs \n"
."included with wildcard: $irdswc \n"
."excluded ($eranz): $erdgs \n"
."excluded with wildcard: $erdswc";
return ($idevs,$idanz,$ireading,$iranz,$edevs,$edanz,$ereading,$eranz); return ($idevs,$idevswc,$idanz,$irdgs,$iranz,$irdswc,$edevs,$edevswc,$edanz,$erdgs,$eranz,$erdswc);
} }
#################################################################################################### ####################################################################################################
@ -10796,32 +10994,48 @@ return;
################################################################################### ###################################################################################
sub DbRep_modAssociatedWith ($$$) { sub DbRep_modAssociatedWith ($$$) {
my ($hash,$cmd,$awdev) = @_; my ($hash,$cmd,$awdev) = @_;
my @naw; my $name = $hash->{NAME};
my (@naw,@edvs,@edvspcs,$edevswc);
# my @def = split("{",$hash->{DEF}); my ($edevs,$idevice,$edevice) = ('','','');
# $hash->{DEF} = $def[0];
if($cmd eq "del") { if($cmd eq "del") {
readingsDelete($hash,".associatedWith"); readingsDelete($hash,".associatedWith");
return; return;
} }
my @nadev = split("[, ]", $awdev); ($idevice,$edevice) = split(/EXCLUDE=/i,$awdev);
if($edevice) {
@edvs = split(",",$edevice);
foreach my $e (@edvs) {
$e =~ s/%/\.*/g if($e !~ /^%$/); # SQL Wildcard % auflösen
@edvspcs = devspec2array($e);
@edvspcs = map {s/\.\*/%/g; $_; } @edvspcs;
if((map {$_ =~ /%/;} @edvspcs) && $edevice !~ /^%$/) { # Devices mit Wildcard (%) aussortieren, die nicht aufgelöst werden konnten
$edevswc .= "|" if($edevswc);
$edevswc .= join(" ",@edvspcs);
} else {
$edevs .= "|" if($edevs);
$edevs .= join("|",@edvspcs);
}
}
}
my @nadev = split("[, ]", $idevice);
foreach my $d (@nadev) { foreach my $d (@nadev) {
if($defs{$d}) { $d =~ s/%/\.*/g if($d !~ /^%$/); # SQL Wildcard % in Regex
push(@naw, $d);
next;
}
my @a = devspec2array($d); my @a = devspec2array($d);
foreach(@a) { foreach(@a) {
next if(!$defs{$_}); next if(!$defs{$_});
push(@naw, $_) if( !( "EXCLUDE=".$_ ~~ @nadev) ); push(@naw, $_) if($_ !~ /$edevs/);
} }
} }
if(@naw) { if(@naw) {
ReadingsSingleUpdateValue ($hash, ".associatedWith", join(" ",@naw), 0); ReadingsSingleUpdateValue ($hash, ".associatedWith", join(" ",@naw), 0);
} else {
readingsDelete($hash, ".associatedWith");
} }
return; return;
@ -11982,12 +12196,12 @@ return;
</ul> </ul>
<br> <br>
For compatibility reasons the reducelog command can optionally be completed with supplements "EXCLUDE" For compatibility reason the reducelog command can optionally be completed with supplements "EXCLUDE"
respectively "INCLUDE" to exclude and/or include device/reading combinations from reducelog: <br><br> respectively "INCLUDE" to exclude and/or include device/reading combinations from reducelog: <br><br>
<ul> <ul>
"reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br> "reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br>
</ul> </ul>
This declaration is evaluated as Regex and overwrites the attributes "device" and "reading", This declaration is evaluated as Regex and overwrites the settings made by attributes "device" and "reading",
which won't be considered in this case. <br><br> which won't be considered in this case. <br><br>
<ul> <ul>
@ -12545,10 +12759,8 @@ return $ret;
<a name="device"></a> <a name="device"></a>
<li><b>device </b> - Selection of particular or several devices. <br> <li><b>device </b> - Selection of particular or several devices. <br>
You can specify a list of devices separated by "," or use device specifications (devspec). <br> You can specify a list of devices separated by "," or use device specifications (devspec). <br>
Inside of lists or device specifications a SQL wildcard (%) will be evaluated as a normal In that case the device names are derived from the device specification and the existing
ASCII-character. devices in FHEM before carry out the SQL selection. <br>
The device names are derived from device specification and the active devices in FHEM before
SQL selection will be carried out. <br>
If the the device, list or device specification is prepended by "EXCLUDE=", If the the device, list or device specification is prepended by "EXCLUDE=",
the devices are excluded from database selection. the devices are excluded from database selection.
<br><br> <br><br>
@ -12836,9 +13048,9 @@ sub bdump {
<a name="reading"></a> <a name="reading"></a>
<li><b>reading </b> - Selection of particular or several readings. <li><b>reading </b> - Selection of particular or several readings.
More than one reading can be specified by a comma separated list. <br> More than one reading can be specified by a comma separated list. <br>
If SQL wildcard (%) is set in a list, it will be evaluated as a normal ASCII-character. <br> SQL wildcard (%) can be used. <br>
If the reading or the reading-list is prepended by "EXCLUDE=", those readings are excluded If the reading or the reading list is prepended by "EXCLUDE=", those readings are not
from database selection. included.
<br><br> <br><br>
<ul> <ul>
@ -12846,8 +13058,8 @@ sub bdump {
<code>attr &lt;name&gt; reading etotal</code> <br> <code>attr &lt;name&gt; reading etotal</code> <br>
<code>attr &lt;name&gt; reading et%</code> <br> <code>attr &lt;name&gt; reading et%</code> <br>
<code>attr &lt;name&gt; reading etotal,etoday</code> <br> <code>attr &lt;name&gt; reading etotal,etoday</code> <br>
<code>attr &lt;name&gt; reading etotal,etoday EXCLUDE=state </code> <br> <code>attr &lt;name&gt; reading eto%,Einspeisung EXCLUDE=etoday </code> <br>
<code>attr &lt;name&gt; reading etotal,etoday EXCLUDE=Einspeisung% </code> <br> <code>attr &lt;name&gt; reading etotal,etoday,Ein% EXCLUDE=%Wirkleistung </code> <br>
</ul> </ul>
<br><br> <br><br>
</li> </li>
@ -13537,9 +13749,9 @@ sub bdump {
<table> <table>
<colgroup> <col width=15%> <col width=85%> </colgroup> <colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td style="vertical-align:top"><b>&lt;old string&gt; :</b> <td><li>ein einfacher String mit/ohne Leerzeichen, z.B. "OL 12" </li> <tr><td style="vertical-align:top"><b>&lt;alter String&gt; :</b> <td><li>ein einfacher String mit/ohne Leerzeichen, z.B. "OL 12" </li>
<li>ein String mit Verwendung von SQL-Wildcard, z.B. "%OL%" </li> </td></tr> <li>ein String mit Verwendung von SQL-Wildcard, z.B. "%OL%" </li> </td></tr>
<tr><td style="vertical-align:top"><b>&lt;new string&gt; :</b> <td><li>ein einfacher String mit/ohne Leerzeichen, z.B. "12 kWh" </li> <tr><td style="vertical-align:top"><b>&lt;neuer String&gt; :</b> <td><li>ein einfacher String mit/ohne Leerzeichen, z.B. "12 kWh" </li>
<li>Perl Code eingeschlossen in "{}" inkl. Quotes, z.B. "{($VALUE,$UNIT) = split(" ",$VALUE)}". <li>Perl Code eingeschlossen in "{}" inkl. Quotes, z.B. "{($VALUE,$UNIT) = split(" ",$VALUE)}".
Dem Perl-Ausdruck werden die Variablen $VALUE und $UNIT übergeben. Sie können innerhalb Dem Perl-Ausdruck werden die Variablen $VALUE und $UNIT übergeben. Sie können innerhalb
des Perl-Code geändert werden. Der zurückgebene Wert von $VALUE und $UNIT wird in dem Feld des Perl-Code geändert werden. Der zurückgebene Wert von $VALUE und $UNIT wird in dem Feld
@ -14437,12 +14649,12 @@ sub bdump {
</ul> </ul>
<br> <br>
Aus Kompatibilitätsgründen kann der Befehl optional durch die Zusätze "EXCLUDE" bzw. "INCLUDE" Aus Kompatibilitätsgründen kann der Set-Befehl optional durch die Zusätze "EXCLUDE" bzw. "INCLUDE"
ergänzt werden um device/reading Kombinationen von reduceLog auszuschließen bzw. einzuschließen: <br><br> direkt ergänzt werden um device/reading Kombinationen von reduceLog auszuschließen bzw. einzuschließen: <br><br>
<ul> <ul>
"reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br> "reduceLog [average[=day]] [EXCLUDE=device1:reading1,device2:reading2,...] [INCLUDE=device:reading]" <br><br>
</ul> </ul>
Diese Angabe wird als Regex ausgewertet und überschreibt die Attribute "device" und "reading", Diese Angabe wird als Regex ausgewertet und überschreibt die Einstellung der Attribute "device" und "reading",
die in diesem Fall nicht beachtet werden. <br><br> die in diesem Fall nicht beachtet werden. <br><br>
<ul> <ul>
@ -15022,9 +15234,8 @@ return $ret;
<a name="device"></a> <a name="device"></a>
<li><b>device </b> - Abgrenzung der DB-Selektionen auf ein bestimmtes oder mehrere Devices. <br> <li><b>device </b> - Abgrenzung der DB-Selektionen auf ein bestimmtes oder mehrere Devices. <br>
Es können Geräte-Spezifikationen (devspec) angegeben werden. <br> Es können Geräte-Spezifikationen (devspec) angegeben werden. <br>
Innerhalb von Geräte-Spezifikationen wird SQL-Wildcard (%) als normales ASCII-Zeichen gewertet. In diesem Fall werden die Devicenamen vor der Selektion aus der Geräte-Spezifikationen und den aktuell in FHEM
Die Devicenamen werden vor der Selektion aus der Geräte-Spezifikationen und den aktuell in FHEM vorhandenen Devices aufgelöst. <br>
vorhandenen Devices abgeleitet. <br>
Wird dem Device bzw. der Device-Liste oder Geräte-Spezifikation ein "EXCLUDE=" vorangestellt, Wird dem Device bzw. der Device-Liste oder Geräte-Spezifikation ein "EXCLUDE=" vorangestellt,
werden diese Devices von der Selektion ausgeschlossen. werden diese Devices von der Selektion ausgeschlossen.
<br><br> <br><br>
@ -15298,9 +15509,9 @@ sub bdump {
<li><b>reading </b> - Abgrenzung der DB-Selektionen auf ein bestimmtes oder mehrere Readings sowie exkludieren von <li><b>reading </b> - Abgrenzung der DB-Selektionen auf ein bestimmtes oder mehrere Readings sowie exkludieren von
Readings. Readings.
Mehrere Readings werden als Komma separierte Liste angegeben. Mehrere Readings werden als Komma separierte Liste angegeben.
SQL Wildcard (%) wird in einer Liste als normales ASCII-Zeichen gewertet. <br> Es können SQL Wildcard (%) verwendet werden. <br>
Wird dem Reading bzw. der Reading-Liste ein "EXCLUDE=" vorangestellt, werden diese Readings Wird dem Reading bzw. der Reading-Liste ein "EXCLUDE=" vorangestellt, werden diese Readings
von der Selektion ausgeschlossen. nicht inkludiert.
<br><br> <br><br>
<ul> <ul>
@ -15308,8 +15519,8 @@ sub bdump {
<code>attr &lt;name&gt; reading etotal</code> <br> <code>attr &lt;name&gt; reading etotal</code> <br>
<code>attr &lt;name&gt; reading et%</code> <br> <code>attr &lt;name&gt; reading et%</code> <br>
<code>attr &lt;name&gt; reading etotal,etoday</code> <br> <code>attr &lt;name&gt; reading etotal,etoday</code> <br>
<code>attr &lt;name&gt; reading etotal,etoday EXCLUDE=state </code> <br> <code>attr &lt;name&gt; reading eto%,Einspeisung EXCLUDE=etoday </code> <br>
<code>attr &lt;name&gt; reading etotal,etoday EXCLUDE=Einspeisung% </code> <br> <code>attr &lt;name&gt; reading etotal,etoday,Ein% EXCLUDE=%Wirkleistung </code> <br>
</ul> </ul>
<br><br> <br><br>
</li> </li>