diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index a98498c69..09f9302e6 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -160,7 +160,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
- "1.51.1" => "19.04.2025 consumer: interruptable, swoncond, swoffcond can be perl code enclosed by {..} ".
+ "1.51.1" => "19.04.2025 consumer: interruptable, swoncond, swoffcond, spignorecond can be perl code enclosed by {..} ".
"check key is valid in plantControl, aiControl, flowGraphicControl, consumerControl, setupMeterDev ".
"setupOtherProducer, setupInverterDev, setupBatteryDev, consumer ".
"writeCacheToFile: bugfix - cache File on OS is deleted if cache is empty ",
@@ -6136,7 +6136,7 @@ sub _attrconsumer { ## no critic "not used"
}
}
- if (exists $h->{interruptable}) { # Check Regex,Code/Hysterese
+ if (exists $h->{interruptable}) {
if ($h->{interruptable} !~ /^[01]$/xs) {
my ($dev, $rd, $code, $hyst);
@@ -6152,7 +6152,7 @@ sub _attrconsumer { ## no critic "not used"
}
if (!$dev || !$rd || !defined $code) {
- return qq{A Device, Reading and Regex/Code must be specified for the 'interruptable' key!};
+ return qq{A Device, Reading and Regex/Code must be specified for the 'interruptable' key};
}
if ($code =~ m/^\s*\{.*\}\s*$/xs) { # interruptable prüft Perl-Code
@@ -6171,8 +6171,12 @@ sub _attrconsumer { ## no critic "not used"
}
}
- if (exists $h->{swoncond}) { # Check Regex
- my (undef, undef, $code) = split ":", $h->{swoncond}, 3;
+ if (exists $h->{swoncond}) {
+ my ($dev, $rd, $code) = split ":", $h->{swoncond}, 3;
+
+ if (!$dev || !$rd || !defined $code) {
+ return qq{A Device, Reading and Regex/Code must be specified for the 'swoncond' key};
+ }
if ($code =~ m/^\s*\{.*\}\s*$/xs) { # swoncond prüft Perl-Code
$code =~ s/\s//xg;
@@ -6185,8 +6189,12 @@ sub _attrconsumer { ## no critic "not used"
}
}
- if (exists $h->{swoffcond}) { # Check Regex
- my (undef, undef, $code) = split ":", $h->{swoffcond}, 3;
+ if (exists $h->{swoffcond}) {
+ my ($dev, $rd, $code) = split ":", $h->{swoffcond}, 3;
+
+ if (!$dev || !$rd || !defined $code) {
+ return qq{A Device, Reading and Regex/Code must be specified for the 'swoffcond' key};
+ }
if ($code =~ m/^\s*\{.*\}\s*$/xs) { # swoffcond prüft Perl-Code
$code =~ s/\s//xg;
@@ -6198,6 +6206,24 @@ sub _attrconsumer { ## no critic "not used"
return "swoffcond: $err" if($err);
}
}
+
+ if (exists $h->{spignorecond}) {
+ my ($dev, $rd, $code) = split ":", $h->{spignorecond}, 3;
+
+ if (!$dev || !$rd || !defined $code) {
+ return qq{A Device, Reading and Regex/Code must be specified for the 'spignorecond' key};
+ }
+
+ if ($code =~ m/^\s*\{.*\}\s*$/xs) { # spignorecond prüft Perl-Code
+ $code =~ s/\s//xg;
+ ($err) = checkCode ($name, $code);
+ return "spignorecond: $err" if($err);
+ }
+ else { # spignorecond prüft Regex
+ $err = checkRegex ($code);
+ return "spignorecond: $err" if($err);
+ }
+ }
if (exists $h->{swstate}) { # Check Regex
my (undef,$onregex,$offregex) = split ":", $h->{swstate};
@@ -8277,8 +8303,9 @@ sub centralTask {
for my $c (1..MAXCONSUMER) { # 19.04.2025
$c = sprintf "%02d", $c;
if (defined $data{$name}{consumers} && defined $data{$name}{consumers}{$c}) {
- delete $data{$name}{consumers}{$c}{swoncondregex} if(exists $data{$name}{consumers}{$c}{swoncondregex});
- delete $data{$name}{consumers}{$c}{swoffcondregex} if(exists $data{$name}{consumers}{$c}{swoffcondregex});
+ delete $data{$name}{consumers}{$c}{swoncondregex} if(exists $data{$name}{consumers}{$c}{swoncondregex});
+ delete $data{$name}{consumers}{$c}{swoffcondregex} if(exists $data{$name}{consumers}{$c}{swoffcondregex});
+ delete $data{$name}{consumers}{$c}{spignorecondregex} if(exists $data{$name}{consumers}{$c}{spignorecondregex});
}
}
}
@@ -8618,9 +8645,9 @@ sub _collectAllRegConsumers {
($dswoffcond, $rswoffcond, $swoffcondition) = split ":", $hc->{swoffcond}, 3;
}
- my ($dspignorecond, $rigncond, $spignorecondregex);
+ my ($dspignorecond, $rigncond, $spignorecondition);
if (exists $hc->{spignorecond}) { # Bedingung um vorhandenen PV Überschuß zu ignorieren
- ($dspignorecond, $rigncond, $spignorecondregex) = split ":", $hc->{spignorecond}, 3;
+ ($dspignorecond, $rigncond, $spignorecondition) = split ":", $hc->{spignorecond}, 3;
}
my $interruptable = 0;
@@ -8703,7 +8730,7 @@ sub _collectAllRegConsumers {
$data{$name}{consumers}{$c}{swoffcondition} = $swoffcondition // q{}; # Regex einer vorrangigen Ausschaltbedingung
$data{$name}{consumers}{$c}{dspignorecond} = $dspignorecond // q{}; # Device liefert Ignore Bedingung
$data{$name}{consumers}{$c}{rigncond} = $rigncond // q{}; # Reading liefert Ignore Bedingung
- $data{$name}{consumers}{$c}{spignorecondregex} = $spignorecondregex // q{}; # Regex der Ignore Bedingung
+ $data{$name}{consumers}{$c}{spignorecondition} = $spignorecondition // q{}; # Code/Regex der Ignore Bedingung
$data{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar
$data{$name}{consumers}{$c}{hysteresis} = $hyst; # Hysterese
$data{$name}{consumers}{$c}{sunriseshift} = $riseshift if(defined $riseshift); # Verschiebung (Sekunden) Sonnenaufgang bei SunPath Verwendung
@@ -12164,7 +12191,11 @@ sub __setConsRcmdState {
}
my ($spignore, $info, $err) = isSurplusIgnoCond ($hash, $c, $debug); # PV Überschuß ignorieren?
+
Log3 ($name, 1, "$name - $err") if($err);
+ if ($debug =~ /consumerSwitching${c}/x && $info) {
+ Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - IgnoreCondition - $info});
+ }
if (!defined $surplus) { # $surplus kann undef sein! -> dann bisherigen isConsumptionRecommended verwenden
$data{$name}{consumers}{$c}{isConsumptionRecommended} = ReadingsVal ($name, "consumer${c}_ConsumptionRecommended", 0);
@@ -21481,36 +21512,58 @@ sub isSurplusIgnoCond {
my $c = shift;
my $debug = shift;
+ my $name = $hash->{NAME};
+ my $igno = 0;
my $info = q{};
my $digncond = ConsumerVal ($hash, $c, 'dspignorecond', ''); # Device zur Lieferung einer "Überschuß Ignore-Bedingung"
- my ($err) = isDeviceValid ( { name => $hash->{NAME},
+ my ($err) = isDeviceValid ( { name => $name,
obj => $digncond,
method => 'string',
}
);
if ($digncond && $err) {
$err = qq{ERROR - the device "$digncond" doesn't exist! Check the key "spignorecond" in attribute "consumer${c}"};
- return (0, $info, $err);
+ return ($igno, $info, $err);
}
- $err = q{};
- my $rigncond = ConsumerVal ($hash, $c, 'rigncond', ''); # Reading zur Lieferung einer zusätzlichen Einschaltbedingung
- my $spignorecondregex = ConsumerVal ($hash, $c, 'spignorecondregex', ''); # Regex einer zusätzliche Einschaltbedingung
- my $condval = ReadingsVal ($digncond, $rigncond, ''); # Wert zum Vergleich mit Regex
+ $err = q{};
+ my $rigncond = ConsumerVal ($hash, $c, 'rigncond', ''); # Reading zur Lieferung einer zusätzlichen Einschaltbedingung
+ my $ignorecode = ConsumerVal ($hash, $c, 'spignorecondition', ''); # Code/Regex für PV Überschuß Ignore
+ my $condval = ReadingsVal ($digncond, $rigncond, undef); # Wert zum Vergleich mit Code/Regex
- if ($condval && $debug =~ /consumerSwitching${c}/x) {
- my $name = $hash->{NAME};
- Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - PV surplus ignore condition ist set - device: $digncond, reading: $rigncond, condition: $spignorecondregex});
+ if ($debug =~ /consumerSwitching${c}/x && defined $condval) {
+ Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - PV surplus ignore condition - device: $digncond, reading: $rigncond, condition: $ignorecode});
+ }
+
+ if (defined $condval) {
+ if ($ignorecode =~ m/^\{.*\}$/xs) { # wertet Perl-Code aus
+ my $VALUE = $condval;
+ my $true = eval $ignorecode;
+
+ if ($@) {
+ Log3 ($name, 1, "$name - ERROR in surplus ignore condition Code execution: ".$@);
+ }
+
+ if ($true) {
+ $info = qq{Value “$condval” resulted in 'true' after exec "$ignorecode" \n};
+ $info .= "-> Check successful ";
+ $igno = 1;
+ }
+ else {
+ $info = qq{Value “$condval” resulted in 'false' after exec "$ignorecode" \n};
+ $igno = 0;
+ }
+ }
+ elsif ($condval =~ m/^$ignorecode$/x) { # wertet Regex aus
+ $igno = 1;
+ }
+ else {
+ $info = qq{Value "$condval" doesn't match the condition: "$ignorecode"};
+ }
}
- if ($condval && $condval =~ m/^$spignorecondregex$/x) {
- return (1, $info, $err);
- }
-
- $info = qq{The device "$digncond", reading "$rigncond" doesn't match the Regex "$spignorecondregex"};
-
-return (0, $info, $err);
+return ($igno, $info, $err);
}
################################################################
@@ -24416,13 +24469,13 @@ to ensure that the system configuration is correct.
-