diff --git a/fhem/CHANGED b/fhem/CHANGED
index ad9cf67bf..09a9c72d2 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,8 @@
# 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: seqDoubletsVariance - separate specification of positive
+ and negative variance possible,
+ (Forum: 53584.msg959963.html#msg959963)
- change: 49_SSCam: internal code changes/optimization
- bugfix: 73_AutoShuttersControl: add condition to attr
ASC_autoShuttersControlEvening to window event
diff --git a/fhem/FHEM/93_DbRep.pm b/fhem/FHEM/93_DbRep.pm
index 68f7f318c..9c9683383 100644
--- a/fhem/FHEM/93_DbRep.pm
+++ b/fhem/FHEM/93_DbRep.pm
@@ -58,6 +58,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern
our %DbRep_vNotesIntern = (
+ "8.28.0" => "30.09.2019 seqDoubletsVariance - separate specification of positive and negative variance possible, Forum: https://forum.fhem.de/index.php/topic,53584.msg959963.html#msg959963 ",
"8.27.2" => "27.09.2019 fix export data to file, fix delDoublets if MySQL and VALUE contains \, fix readingRename without leading device ",
"8.27.1" => "22.09.2019 comma are shown in sqlCmdHistory, Forum: #103908 ",
"8.27.0" => "15.09.2019 save memory usage by eliminating \$hash -> {dbloghash}, fix warning uninitialized value \$idevice in split ",
@@ -1243,7 +1244,16 @@ sub DbRep_Attr($$$$) {
}
if ($aName =~ /seqDoubletsVariance/) {
- unless (looks_like_number($aVal)) { return " The Value of $aName is not valid. Only figures are allowed !";}
+ my $edge = "";
+ if($aVal =~ /EDGE=/) {
+ ($aVal,$edge) = split("EDGE=", $aVal);
+ unless ($edge =~ /^balanced$|^negative$/i) { return " The parameter EDGE can only be \"balanced\" or \"negative\" !";}
+ }
+ my ($varpos,$varneg) = split(" ", $aVal);
+ $varpos = DbRep_trim($varpos);
+ $varneg = $varpos if(!$varneg);
+ $varneg = DbRep_trim($varneg);
+ unless (looks_like_number($varpos) && looks_like_number($varneg)) { return " The Value of $aName is not valid. Only figures are allowed (except \"EDGE\") !";}
}
if ($aName eq "timeYearPeriod") {
@@ -5144,9 +5154,23 @@ sub delseqdoubl_DoParse($) {
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0;
my $limit = AttrVal($name, "limit", 1000);
- my $var = AttrVal($name, "seqDoubletsVariance", undef);
+ my $var = AttrVal($name, "seqDoubletsVariance", undef); # allgemeine Varianz
my $table = "history";
- my ($err,$dbh,$sth,$sql,$rowlist,$nrows,$selspec,$st,$var1,$var2);
+ my ($err,$dbh,$sth,$sql,$rowlist,$nrows,$selspec,$st,$varo,$varu);
+
+ # positive und negative Flankenvarianz spezifizieren
+ my $edge = "balanced";
+ if($var && $var =~ /EDGE=/) {
+ ($var,$edge) = split("EDGE=", $var);
+ }
+ my ($varpos,$varneg);
+ if (defined $var) {
+ ($varpos,$varneg) = split(" ",$var);
+ $varpos = DbRep_trim($varpos);
+ $varneg = $varpos if(!$varneg);
+ $varneg = DbRep_trim($varneg);
+ }
+ Log3 ($name, 4, "DbRep $name - delSeqDoublets params -> positive variance: $varpos, negative variance: $varneg, EDGE: $edge");
# Background-Startzeit
my $bst = [gettimeofday];
@@ -5209,27 +5233,46 @@ sub delseqdoubl_DoParse($) {
my ($or,$oor,$odev,$oread,$oval,$ooval,$ndev,$nread,$nval);
my $i = 0;
foreach my $nr (map { $_->[0]."_ESC_".$_->[1]."_ESC_".($_->[2] =~ s/ /_ESC_/r)."_ESC_".$_->[3] } @{$sth->fetchall_arrayref()}) {
- ($ndev,$nread,undef,undef,$nval) = split("_ESC_", $nr); # Werte des aktuellen Elements
- $or = pop @sel; # das letzte Element der Liste
- ($odev,$oread,undef,undef,$oval) = split("_ESC_", $or); # Value des letzten Elements
- if (looks_like_number($oval) && $var) { # Varianz +- falls $val numerischer Wert
- $var1 = $oval + $var;
- $var2 = $oval - $var;
+ ($ndev,$nread,undef,undef,$nval) = split("_ESC_", $nr); # Werte des aktuellen Elements
+ $or = pop @sel; # das letzte Element der Liste
+ ($odev,$oread,undef,undef,$oval) = split("_ESC_", $or); # Value des letzten Elements
+
+ if (looks_like_number($oval) && defined $varpos && defined $varneg) { # unterschiedliche Varianz +/- für numerische Werte
+ $varo = $oval + $varpos;
+ $varu = $oval - $varneg;
+ } elsif (looks_like_number($oval) && defined $varpos && !defined $varneg) { # identische Varianz +/- für numerische Werte
+ $varo = $oval + $varpos;
+ $varu = $oval - $varpos;
} else {
- undef $var1;
- undef $var2;
+ undef $varo;
+ undef $varu;
}
$oor = pop @sel; # das vorletzte Element der Liste
$ooval = (split '_ESC_', $oor)[-1]; # Value des vorletzten Elements
- if ($ndev.$nread ne $odev.$oread) {
+ # Log3 ($name, 1, "DbRep $name - OOVAL: $ooval, OVAL: $oval, VARO: $varo, VARU: $varu");
+
+ if ($ndev.$nread ne $odev.$oread) {
$i = 0; # neues Device/Reading in einer Periode -> ooor soll erhalten bleiben
push (@sel,$oor) if($oor);
push (@sel,$or) if($or);
push (@sel,$nr);
- } elsif ($i>=2 && ($ooval eq $oval && $oval eq $nval) || ($i>=2 && $var1 && $var2 && ($ooval <= $var1) && ($var2 <= $ooval) && ($nval <= $var1) && ($var2 <= $nval)) ) {
- push (@sel,$oor);
- push (@sel,$nr);
- push (@warp,$or); # Array der zu löschenden Datensätze
+
+ } elsif ($i>=2 && ($ooval eq $oval && $oval eq $nval) ||
+ ($i>=2 && $varo && $varu && ($ooval <= $varo) && ($varu <= $ooval) && ($nval <= $varo) && ($varu <= $nval)) ) {
+ if ($edge =~ /negative/i && ($ooval > $oval)) {
+ push (@sel,$oor); # negative Flanke -> der fallende DS und desssen Vorgänger
+ push (@sel,$or); # werden behalten obwohl im Löschkorridor
+ push (@sel,$nr);
+ } elsif ($edge =~ /positive/i && ($ooval < $oval)) {
+ push (@sel,$oor); # positive Flanke -> der steigende DS und desssen Vorgänger
+ push (@sel,$or); # werden behalten obwohl im Löschkorridor
+ push (@sel,$nr);
+ } else {
+ push (@sel,$oor); # Array der zu behaltenden Datensätze
+ push (@sel,$nr); # Array der zu behaltenden Datensätze
+ push (@warp,$or); # Array der zu löschenden Datensätze
+ }
+
if ($opt =~ /delete/ && $or) { # delete Datensätze
my ($dev,$read,$date,$time,$val) = split("_ESC_", $or);
my $dt = $date." ".$time;
@@ -5273,10 +5316,10 @@ sub delseqdoubl_DoParse($) {
$nremain = $nremain + $#sel+1 if(@sel);
$ntodel = $ntodel + $#warp+1 if(@warp);
my $sum = $nremain+$ntodel;
- Log3 ($name, 3, "DbRep $name -> rows analyzed by \"$hash->{LASTCMD}\": $sum") if($sum && $opt =~ /advice/);
+ Log3 ($name, 3, "DbRep $name - rows analyzed by \"$hash->{LASTCMD}\": $sum") if($sum && $opt =~ /advice/);
}
- Log3 ($name, 3, "DbRep $name -> rows deleted by \"$hash->{LASTCMD}\": $ndel") if($ndel);
+ Log3 ($name, 3, "DbRep $name - rows deleted by \"$hash->{LASTCMD}\": $ndel") if($ndel);
my $retn = ($opt =~ /adviceRemain/)?$nremain:($opt =~ /adviceDelete/)?$ntodel:$ndel;
@@ -5291,7 +5334,7 @@ sub delseqdoubl_DoParse($) {
}
use warnings;
- Log3 ($name, 5, "DbRep $name -> row result list:\n$rowlist");
+ Log3 ($name, 5, "DbRep $name - row result list:\n$rowlist");
$dbh->disconnect;
@@ -13089,19 +13132,29 @@ sub bdump {
new operation starts
-
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 3.0 2.0
attr <name> seqDoubletsVariance 1.5 EDGE=negative
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 3.0 2.0
attr <name> seqDoubletsVariance 1.5 EDGE=negative
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 3.0 2.0
attr <name> seqDoubletsVariance 1.5 EDGE=negative
attr <name> seqDoubletsVariance 0.0014
attr <name> seqDoubletsVariance 1.45
attr <name> seqDoubletsVariance 3.0 2.0
attr <name> seqDoubletsVariance 1.5 EDGE=negative