diff --git a/fhem/CHANGED b/fhem/CHANGED
index 7428d3b21..bf2e60373 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,6 @@
# 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: 76_SolarForecast: improve manual setting of pvCorrectionFactor_XX
- feature: 98_RandomTimer: add recomputeTimes setter
- change: 38_netatmo: new token refresh handling and fallback reading
- bugfix: 76_SolarForecast: fix Warnings
diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm
index 08a7c44cf..c5a3b6da5 100644
--- a/fhem/FHEM/76_SolarForecast.pm
+++ b/fhem/FHEM/76_SolarForecast.pm
@@ -155,6 +155,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.29.2" => "17.06.2024 ___readCandQ: improve manual setting of pvCorrectionFactor_XX ",
"1.29.1" => "17.06.2024 fix Warnings, Forum: https://forum.fhem.de/index.php?msg=1315283, fix roofIdentPair ",
"1.29.0" => "16.06.2024 _setreset: improve reset consumerMaster ".
"tranformed setter moduleAzimuth to setupStringAzimuth ".
@@ -458,7 +459,7 @@ my $fgCDdef = 130;
my $bPath = 'https://svn.fhem.de/trac/browser/trunk/fhem/contrib/SolarForecast/'; # Basispfad Abruf contrib SolarForecast Files
my $pPath = '?format=txt'; # Download Format
-my $cfile = 'controls_solarforecast.txt'; # Name des Conrrolfiles
+my $cfile = 'controls_solarforecast.txt'; # Name des Controlfiles
# default CSS-Style
my $cssdef = qq{.flowg.text { stroke: none; fill: gray; font-size: 60px; } \n}.
@@ -1538,7 +1539,7 @@ sub Set {
debug => getDebug ($hash)
};
- if($hset{$opt} && defined &{$hset{$opt}{fn}}) {
+ if ($hset{$opt} && defined &{$hset{$opt}{fn}}) {
my $ret = q{};
$ret = &{$hset{$opt}{fn}} ($params);
return $ret;
@@ -1934,8 +1935,11 @@ sub _setpvCorrectionFactor { ## no critic "not used"
}
$prop =~ s/,/./x;
+
+ my ($acu, $aln) = isAutoCorrUsed ($name);
+ my $mode = $acu =~ /on/xs ? 'manual flex' : 'manual fix';
- readingsSingleUpdate($hash, $opt, $prop." (manual)", 1);
+ readingsSingleUpdate ($hash, $opt, $prop." ($mode)", 1);
my $cfnum = (split "_", $opt)[1];
readingsDelete ($hash, "pvCorrectionFactor_${cfnum}_autocalc");
@@ -1960,17 +1964,35 @@ sub _setpvCorrectionFactorAuto { ## no critic "not used"
$prop = $pfa.' '.$prop;
}
- readingsSingleUpdate($hash, 'pvCorrectionFactor_Auto', $prop, 1);
+ readingsSingleUpdate ($hash, 'pvCorrectionFactor_Auto', $prop, 1);
if ($prop eq 'off') {
for my $n (1..24) {
$n = sprintf "%02d", $n;
my $rv = ReadingsVal ($name, "pvCorrectionFactor_${n}", "");
- deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*") if($rv !~ /manual/xs);
+
+ if ($rv !~ /manual/xs) {
+ deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*");
+ }
+ else {
+ $rv =~ s/flex/fix/xs;
+ readingsSingleUpdate ($hash, "pvCorrectionFactor_${n}", $rv, 0);
+ }
}
deleteReadingspec ($hash, "pvCorrectionFactor_.*_autocalc");
}
+ elsif ($prop =~ /on/xs) {
+ for my $n (1..24) {
+ $n = sprintf "%02d", $n;
+ my $rv = ReadingsVal ($name, "pvCorrectionFactor_${n}", "");
+
+ if ($rv =~ /manual/xs) {
+ $rv =~ s/fix/flex/xs;
+ readingsSingleUpdate ($hash, "pvCorrectionFactor_${n}", $rv, 0);
+ }
+ }
+ }
writeCacheToFile ($hash, 'plantconfig', $plantcfg.$name); # Anlagenkonfiguration sichern
@@ -2096,7 +2118,7 @@ sub _setreset { ## no critic "not used"
}
}
- Log3($name, 3, qq{$name - all stored PV correction factors from pvCircular and pvHistory deleted});
+ Log3 ($name, 3, qq{$name - all stored PV correction factors from pvCircular and pvHistory deleted});
}
return;
@@ -7203,8 +7225,8 @@ sub _specialActivities {
Log3 ($name, 4, "$name - Daily special tasks - Task 4 started");
- __deleteHiddenReadings ($paref); # verstecktes Steuerungsreading löschen
- periodicWriteMemcache ($hash, 'bckp'); # Backup Files erstellen und alte Versionen löschen
+ __deletePvCorffReadings ($paref); # Readings der pvCorrectionFactor-Steuerung löschen
+ periodicWriteMemcache ($hash, 'bckp'); # Backup Files erstellen und alte Versionen löschen
Log3 ($name, 4, "$name - Daily special tasks - Task 4 finished");
}
@@ -7238,9 +7260,9 @@ return;
}
#############################################################################
-# versteckte Steuerungsreadings löschen
+# Readings der pvCorrectionFactor-Steuerung löschen
#############################################################################
-sub __deleteHiddenReadings {
+sub __deletePvCorffReadings {
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
@@ -7252,8 +7274,17 @@ sub __deleteHiddenReadings {
readingsDelete ($hash, ".pvCorrectionFactor_${n}_apipercentil");
readingsDelete ($hash, ".signaldone_${n}");
- if (ReadingsVal ($name, "pvCorrectionFactor_Auto", "off") =~ /on/xs) {
- deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*");
+ if (ReadingsVal ($name, 'pvCorrectionFactor_Auto', 'off') =~ /on/xs) {
+ my $pcf = ReadingsVal ($name, "pvCorrectionFactor_${n}", '');
+ ($pcf) = split " / ", $pcf if($pcf =~ /\s\/\s/xs);
+
+ if ($pcf !~ /manual/xs) { # manuell gesetzte pcf-Readings nicht löschen
+ deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*");
+ }
+ else {
+ readingsSingleUpdate ($hash, "pvCorrectionFactor_${n}", $pcf, 0);
+ deleteReadingspec ($hash, "pvCorrectionFactor_${n}_autocalc");
+ }
}
}
@@ -7984,36 +8015,40 @@ sub ___readCandQ {
my ($acu, $aln) = isAutoCorrUsed ($name); # Autokorrekturmodus
my $sunalt = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), 'sunalt', undef); # Sun Altitude
- my $hc = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor
+ my $hcraw = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor (evtl. manuell gesetzt)
+ my $cpcf = ReadingsVal ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), ''); # aktuelles pcf-Reading
my $hq = '-'; # keine Qualität definiert
my $crang = 'simple';
-
+ my $hc;
+
delete $data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange};
if ($acu =~ /on_complex/xs) { # Autokorrektur complex soll genutzt werden
$crang = cloud2bin ($cc); # Range errechnen
- ($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, $crang, undef); # Korrekturfaktor/Qualität der Stunde des Tages (complex)
- $hq //= '-';
- $hc //= 1; # Korrekturfaktor = 1 (keine Korrektur) # keine Qualität definiert
- $hc = 1 if(1 * $hc == 0); # 0.0-Werte ignorieren (Schleifengefahr)
-
+ ($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, $crang, undef); # Korrekturfaktor/Qualität der Stunde des Tages (complex)
+
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange} = $crang;
}
elsif ($acu =~ /on_simple/xs) {
($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
- $hq //= '-';
- $hc //= 1; # Korrekturfaktor = 1
- $hc = 1 if(1 * $hc == 0); # 0.0-Werte ignorieren (Schleifengefahr)
}
else { # keine Autokorrektur
($hc, $hq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$fh1), $sabin, 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
- $hq //= '-';
- $hc = 1;
}
- $hc = sprintf "%.2f", $hc;
-
- debugLog ($paref, 'pvCorrectionRead', "read parameters - fd: $fd, hod: ".sprintf("%02d",$fh1).", Sun Altitude Bin: $sabin, Cloud range: $crang, corrf: $hc, quality: $hq");
+ $hq //= '-'; # keine Qualität definiert
+ $hc //= $hcraw; # Korrekturfaktor Voreinstellung
+ $hc = 1 if(1 * $hc == 0); # 0.0-Werte ignorieren (Schleifengefahr)
+ $hc = sprintf "%.2f", $hc;
+
+ if ($cpcf =~ /manual\sfix/xs) { # Voreinstellung pcf-Reading verwenden wenn 'manual fix'
+ $hc = $hcraw;
+ debugLog ($paref, 'pvCorrectionRead', "use 'manual fix' - fd: $fd, hod: ".sprintf("%02d",$fh1).", corrf: $hc, quality: $hq");
+ }
+ else {
+ my $flex = $cpcf =~ /manual\sflex/xs ? "use 'manual flex'" : 'read parameters';
+ debugLog ($paref, 'pvCorrectionRead', "$flex - fd: $fd, hod: ".sprintf("%02d",$fh1).", Sun Altitude Bin: $sabin, Cloud range: $crang, corrf: $hc, quality: $hq");
+ }
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{pvcorrf} = $hc."/".$hq;
@@ -10805,13 +10840,16 @@ sub calcValueImproves {
for my $h (1..23) {
next if(!$chour || $h > $chour);
- $paref->{h} = $h;
+
+ $paref->{cpcf} = ReadingsVal ($name, 'pvCorrectionFactor_'.sprintf("%02d",$h), ''); # aktuelles pvCorf-Reading
+ $paref->{h} = $h;
- _calcCaQcomplex ($paref); # Korrekturberechnung mit Bewölkung duchführen/speichern
- _calcCaQsimple ($paref); # einfache Korrekturberechnung duchführen/speichern
- _addHourAiRawdata ($paref); # AI Raw Data hinzufügen
+ _calcCaQcomplex ($paref); # Korrekturberechnung mit Bewölkung duchführen/speichern
+ _calcCaQsimple ($paref); # einfache Korrekturberechnung duchführen/speichern
+ _addHourAiRawdata ($paref); # AI Raw Data hinzufügen
delete $paref->{h};
+ delete $paref->{cpcf};
}
delete $paref->{aln};
@@ -10877,7 +10915,13 @@ sub _calcCaQcomplex {
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_cloudcover', 'done');
if ($acu =~ /on_complex/xs) {
- storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Sun Alt range: $sabin, Cloud range: $crang, Days in range: $dnum)");
+ if ($paref->{cpcf} !~ /manual/xs) { # pcf-Reading nur überschreiben wenn nicht 'manual xxx' gesetzt
+ storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Sun Alt range: $sabin, Cloud range: $crang, Days in range: $dnum)");
+ }
+ else {
+ storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $paref->{cpcf}." / flexmatic result $factor for Sun Alt range: $sabin, Cloud range: $crang, Days in range: $dnum");
+ }
+
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h).'_autocalc', 'done');
}
@@ -10939,7 +10983,13 @@ sub _calcCaQsimple {
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_apipercentil', 'done');
if ($acu =~ /on_simple/xs) {
- storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Days in range: $dnum)");
+ if ($paref->{cpcf} !~ /manual/xs) { # pcf-Reading nur überschreiben wenn nicht 'manual xxx' gesetzt
+ storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Days in range: $dnum)");
+ }
+ else {
+ storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $paref->{cpcf}." / flexmatic result $factor, Days in range: $dnum");
+ }
+
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h).'_autocalc', 'done');
}
@@ -18695,8 +18745,23 @@ to ensure that the system configuration is correct.
pvCorrectionFactor_XX <Zahl>
- Manual correction factor for hour XX of the day to adjust the forecast to the individual installation.
- (default: 1.0)
+ Manual correction factor for hour XX of the day.
+ (default: 1.0)
+
+ Depending on the setting pvCorrectionFactor_Auto ('off' or 'on_.*'),
+ a static or dynamic default setting is made:
+
+
+
+
+ off | The set correction factor is not overwritten by the auto-correction. |
+ | In the pvCorrectionFactor_XX reading, the status is signaled by the addition 'manual fix'. |
+ | |
+ on_.* | The set correction factor is overwritten by the auto-correction or AI |
+ | if a calculated correction value is available in the system. |
+ | In the pvCorrectionFactor_XX reading, the status is signaled by the addition 'manual flex'. |
+
+
@@ -20964,8 +21029,23 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
pvCorrectionFactor_XX <Zahl>
- Manueller Korrekturfaktor für die Stunde XX des Tages zur Anpassung der Vorhersage an die individuelle Anlage.
- (default: 1.0)
+ Voreinstellung des Korrekturfaktors für die Stunde XX des Tages.
+ (default: 1.0)
+
+ In Abhängigkeit vom Setting pvCorrectionFactor_Auto ('off' bzw. 'on_.*') erfolgt
+ eine statische oder dynamische Voreinstellung:
+
+
+
+
+ off | Der eingestellte Korrekturfaktor wird durch die Autokorrektur nicht überschrieben. |
+ | Im Reading pvCorrectionFactor_XX wird der Status durch den Zusatz 'manual fix' signalisiert. |
+ | |
+ on_.* | Der eingestellte Korrekturfaktor wird durch die Autokorrektur bzw. KI überschrieben |
+ | sofern ein berechneter Korrekturwert im System verfügbar ist. |
+ | Im Reading pvCorrectionFactor_XX wird der Status durch den Zusatz 'manual flex' signalisiert. |
+
+