mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
76_SolarForecast: take into account the position of the sun in addition to cloud cover when determining the correction factor
git-svn-id: https://svn.fhem.de/fhem/trunk@28553 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
914598bf7e
commit
bf5c9aee7d
@ -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: 76_SolarForecast: take into account the position of the sun in
|
||||
addition to cloud cover when determining the
|
||||
correction factor
|
||||
- change: 76_SolarForecast: check age of Rad1h data, use RR1c instead of R101
|
||||
- feature: 70_PylonLowVoltage: print out faulty response with verbose 5
|
||||
- bugfix: 88_HMCCU: fixed device detection bug
|
||||
|
@ -158,6 +158,11 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.16.3" => "24.02.2024 store pvcorrf, quality, pvrlsum, pvfcsum, dnumsum with value <sunalt2bin>.<cloud2bin> in pvCircular ".
|
||||
"get pvcorrf / quality from neff in combination with sun altitude (CircularSunCloudkorrVal) ".
|
||||
"delete CircularCloudkorrVal, show sun position in beamgrafic weather mouse over ".
|
||||
"split pvCorrection into pvCorrectionRead and pvCorrectionWrite ".
|
||||
"_checkSetupNotComplete: improve setup Wizzard for ForecastSolar-API ",
|
||||
"1.16.2" => "22.02.2024 minor changes, R101 -> RR1c, totalrain instead of weatherrainprob, delete wrp r101 ".
|
||||
"delete wrp from circular & airaw, remove rain2bin, __getDWDSolarData: change \$runh, ".
|
||||
"fix Illegal division by zero Forum: https://forum.fhem.de/index.php?msg=1304009 ".
|
||||
@ -339,10 +344,10 @@ my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx";
|
||||
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
||||
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
||||
my $aistdudef = 1095; # default Haltezeit KI Raw Daten (Tage)
|
||||
my $aiSpreadUpLim = 150; # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiSpreadLowLim = 50; # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiAccUpLim = 170; # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiAccLowLim = 30; # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiSpreadUpLim = 130; # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiSpreadLowLim = 70; # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||
my $aiAccUpLim = 150; # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
my $aiAccLowLim = 50; # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||
|
||||
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
|
||||
my @dweattrmust = qw(TTT Neff RR1c ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||
@ -419,7 +424,8 @@ my @dd = qw( none
|
||||
epiecesCalc
|
||||
graphic
|
||||
notifyHandling
|
||||
pvCorrection
|
||||
pvCorrectionRead
|
||||
pvCorrectionWrite
|
||||
radiationProcess
|
||||
saveData2Cache
|
||||
);
|
||||
@ -694,8 +700,8 @@ my %htitles = (
|
||||
DE => qq{Ein -> kein off-Kommando definiert!} },
|
||||
natc => { EN => qq{automatic cycle:},
|
||||
DE => qq{automatischer Zyklus:} },
|
||||
predtime => { EN => qq{Prediction time Weather data:},
|
||||
DE => qq{Vorhersagezeitpunkt Wetterdaten:} },
|
||||
predtime => { EN => qq{Prediction time Radiation data:},
|
||||
DE => qq{Vorhersagezeitpunkt Strahlungsdaten:} },
|
||||
upd => { EN => qq{Click for update},
|
||||
DE => qq{Klick für Update} },
|
||||
on => { EN => qq{switched on},
|
||||
@ -706,6 +712,12 @@ my %htitles = (
|
||||
DE => qq{undefiniert} },
|
||||
dela => { EN => qq{delayed},
|
||||
DE => qq{verzoegert} },
|
||||
azimuth => { EN => qq{Azimuth},
|
||||
DE => qq{Azimut} },
|
||||
elevatio => { EN => qq{Elevation},
|
||||
DE => qq{Höhe} },
|
||||
sunpos => { EN => qq{Sun position (decimal degrees)},
|
||||
DE => qq{Sonnenstand (Dezimalgrad)} },
|
||||
conrec => { EN => qq{Current time is within the consumption planning},
|
||||
DE => qq{Aktuelle Zeit liegt innerhalb der Verbrauchsplanung} },
|
||||
conrecba => { EN => qq{Current time is within the consumption planning, Priority charging Battery is active},
|
||||
@ -1439,6 +1451,13 @@ sub _setcurrentRadiationAPI { ## no critic "not used"
|
||||
return "You have to install the required perl module: ".$rmf if($rmf);
|
||||
}
|
||||
|
||||
readingsSingleUpdate ($hash, "currentRadiationAPI", $prop, 1);
|
||||
createAssociatedWith ($hash);
|
||||
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
|
||||
setModel ($hash); # Model setzen
|
||||
|
||||
return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett
|
||||
|
||||
if ($prop eq 'ForecastSolar-API') {
|
||||
my ($set, $lat, $lon) = locCoordinates();
|
||||
return qq{set attributes 'latitude' and 'longitude' in global device first} if(!$set);
|
||||
@ -1450,15 +1469,6 @@ sub _setcurrentRadiationAPI { ## no critic "not used"
|
||||
return qq{Please complete command "set $name moduleAzimuth".} if(!$dir);
|
||||
}
|
||||
|
||||
if ($prop eq 'VictronVRM-API') {
|
||||
|
||||
}
|
||||
|
||||
readingsSingleUpdate ($hash, "currentRadiationAPI", $prop, 1);
|
||||
createAssociatedWith ($hash);
|
||||
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
|
||||
setModel ($hash); # Model setzen
|
||||
|
||||
my $type = $hash->{TYPE};
|
||||
$data{$type}{$name}{current}{allStringsFullfilled} = 0; # Stringkonfiguration neu prüfen lassen
|
||||
|
||||
@ -4691,7 +4701,7 @@ sub Attr {
|
||||
if ($cmd eq 'set') {
|
||||
if ($aName eq 'ctrlInterval' || $aName eq 'ctrlBackupFilesKeep' || $aName eq 'ctrlAIdataStorageDuration') {
|
||||
unless ($aVal =~ /^[0-9]+$/x) {
|
||||
return qq{The value for $aName is not valid. Use only figures 0-9 !};
|
||||
return qq{Invalid value for $aName. Use only figures 0-9!};
|
||||
}
|
||||
}
|
||||
|
||||
@ -5681,15 +5691,94 @@ sub centralTask {
|
||||
}
|
||||
|
||||
## nicht-Bin Werte löschen / wrp löschen
|
||||
my $ra = '0|00|05|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100|2.{2}|percentile|simple';
|
||||
my $ra = '0|00|05|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100|.*\..*|simple';
|
||||
|
||||
for my $hod (keys %{$data{$type}{$name}{circular}}) { # 30.01.2024
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvcorrf}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvcorrf}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range};
|
||||
}
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range} if(!defined $data{$type}{$name}{circular}{$hod}{pvcorrf}{$range});
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{quality}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{quality}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range};
|
||||
}
|
||||
delete $data{$type}{$name}{circular}{$hod}{quality}{$range} if(!defined $data{$type}{$name}{circular}{$hod}{quality}{$range});
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvrlsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvrlsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvrlsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{pvfcsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{pvfcsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{pvfcsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $range (keys %{$data{$type}{$name}{circular}{$hod}{dnumsum}}) {
|
||||
delete $data{$type}{$name}{circular}{$hod}{dnumsum}{$range} if($range !~ /^($ra)$/xs);
|
||||
|
||||
if($range !~ /simple|\./xs) { # 24.02.2024
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"5.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"10.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"15.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"20.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"25.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"30.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"35.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"40.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
$data{$type}{$name}{circular}{$hod}{dnumsum}{"45.$range"} = $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
delete $data{$type}{$name}{circular}{$hod}{dnumsum}{$range};
|
||||
}
|
||||
}
|
||||
|
||||
for my $wp (keys %{$data{$type}{$name}{circular}{$hod}}) { # 19.02.204
|
||||
@ -5697,6 +5786,7 @@ sub centralTask {
|
||||
delete $data{$type}{$name}{circular}{$hod}{$wp};
|
||||
}
|
||||
}
|
||||
|
||||
## currentWeatherDev in Attr umsetzen
|
||||
my $cwd = ReadingsVal ($name, 'currentWeatherDev', ''); # 30.01.2024
|
||||
if ($cwd) {
|
||||
@ -6779,17 +6869,17 @@ sub ___readCandQ {
|
||||
my $cc = $paref->{cloudcover};
|
||||
|
||||
my ($acu, $aln) = isAutoCorrUsed ($name); # Autokorrekturmodus
|
||||
my $hc = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor
|
||||
my $sunalt = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), 'sunalt', ''); # Sun Altitude
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
my $hc = ReadingsNum ($name, 'pvCorrectionFactor_'.sprintf("%02d",$fh1), 1.00); # Voreinstellung RAW-Korrekturfaktor
|
||||
my $hq = '-'; # keine Qualität definiert
|
||||
my $crang = 'simple';
|
||||
|
||||
delete $data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange};
|
||||
|
||||
my $sunalt = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), 'sunalt', ''); # Sun Altitude
|
||||
my $safac = CircularSunaltkorrVal ($hash, sprintf("%02d",$fh1), $sunalt, 0); # Faktor gespeichert für eine Sun Altitude
|
||||
|
||||
if ($acu =~ /on_complex/xs) { # Autokorrektur complex soll genutzt werden
|
||||
my $crang = cloud2bin ($cc); # Range errechnen
|
||||
($hc, $hq) = CircularCloudkorrVal ($hash, sprintf("%02d",$fh1), $crang, undef); # Korrekturfaktor/Qualität der Stunde des Tages (complex)
|
||||
$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)
|
||||
@ -6797,19 +6887,21 @@ sub ___readCandQ {
|
||||
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{cloudrange} = $crang;
|
||||
}
|
||||
elsif ($acu =~ /on_simple/xs) {
|
||||
($hc, $hq) = CircularCloudkorrVal ($hash, sprintf("%02d",$fh1), 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
($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) = CircularCloudkorrVal ($hash, sprintf("%02d",$fh1), 'simple', undef); # Korrekturfaktor/Qualität der Stunde des Tages (simple)
|
||||
($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");
|
||||
|
||||
$data{$type}{$name}{nexthours}{"NextHour".sprintf("%02d",$num)}{pvcorrf} = $hc."/".$hq;
|
||||
|
||||
if($fd == 0 && $fh1) {
|
||||
@ -7415,31 +7507,31 @@ sub _batSocTarget {
|
||||
|
||||
## Aufladewahrscheinlichkeit beachten
|
||||
#######################################
|
||||
my $pvfctm = ReadingsNum ($name, 'Tomorrow_PVforecast', 0); # PV Prognose morgen
|
||||
my $pvfctd = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Prognose Rest heute
|
||||
my $csopt = ReadingsNum ($name, 'Battery_OptimumTargetSoC', $lowSoc); # aktuelles SoC Optimum
|
||||
my $pvfctm = ReadingsNum ($name, 'Tomorrow_PVforecast', 0); # PV Prognose morgen
|
||||
my $pvfctd = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Prognose Rest heute
|
||||
my $csopt = ReadingsNum ($name, 'Battery_OptimumTargetSoC', $lowSoc); # aktuelles SoC Optimum
|
||||
|
||||
my $pvexpect = $pvfctm > $pvfctd ? $pvfctm : $pvfctd;
|
||||
my $batinstcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $cantarget = 100 - (100 / $batinstcap) * $pvexpect; # berechneter möglicher Min SOC nach Berücksichtigung Ladewahrscheinlichkeit
|
||||
|
||||
my $batinstcap = CurrentVal ($hash, 'batinstcap', 0); # installierte Batteriekapazität Wh
|
||||
my $cantarget = 100 - (100 / $batinstcap) * $pvexpect; # berechneter möglicher Min SOC nach Berücksichtigung Ladewahrscheinlichkeit
|
||||
|
||||
my $newtarget = sprintf "%.0f", ($cantarget < $target ? $cantarget : $target); # Abgleich möglicher Min SOC gg. berechneten Min SOC
|
||||
my $newtarget = sprintf "%.0f", ($cantarget < $target ? $cantarget : $target); # Abgleich möglicher Min SOC gg. berechneten Min SOC
|
||||
my $logadd = '';
|
||||
|
||||
if ($newtarget > $csopt && $t > $delayts) { # Erhöhung des SoC (wird ab Sonnenuntergang angewendet)
|
||||
if ($newtarget > $csopt && $t > $delayts) { # Erhöhung des SoC (wird ab Sonnenuntergang angewendet)
|
||||
$target = $newtarget;
|
||||
$logadd = "(new target > $csopt % and Sunset has passed)";
|
||||
}
|
||||
elsif ($newtarget > $csopt && $t <= $delayts) { # bisheriges Optimum bleibt vorerst
|
||||
elsif ($newtarget > $csopt && $t <= $delayts) { # bisheriges Optimum bleibt vorerst
|
||||
$target = $csopt;
|
||||
$nt = (timestampToTimestring ($delayts, $paref->{lang}))[0];
|
||||
$logadd = "(calculated new target $newtarget % is only activated after $nt)";
|
||||
}
|
||||
elsif ($newtarget < $csopt) { # Targetminderung sofort umsetzen -> Freiplatz für Ladeprognose
|
||||
elsif ($newtarget < $csopt) { # Targetminderung sofort umsetzen -> Freiplatz für Ladeprognose
|
||||
$target = $newtarget;
|
||||
$logadd = "(new target < current Target SoC $csopt)";
|
||||
}
|
||||
else { # bisheriges Optimum bleibt
|
||||
else { # bisheriges Optimum bleibt
|
||||
$target = $newtarget;
|
||||
$logadd = "(no change)";
|
||||
}
|
||||
@ -7577,33 +7669,33 @@ sub _createSummaries {
|
||||
$pvfc = 0 if($pvfc < 0); # PV Prognose darf nicht negativ sein
|
||||
$confc = 0 if($confc < 0); # Verbrauchsprognose darf nicht negativ sein
|
||||
|
||||
if($h == 1) {
|
||||
if ($h == 1) {
|
||||
$next1HoursSum->{PV} += $pvfc / 60 * $minute;
|
||||
$next1HoursSum->{Consumption} += $confc / 60 * $minute;
|
||||
}
|
||||
|
||||
if($h <= 2) {
|
||||
if ($h <= 2) {
|
||||
$next2HoursSum->{PV} += $pvfc if($h < 2);
|
||||
$next2HoursSum->{PV} += $pvfc / 60 * $minute if($h == 2);
|
||||
$next2HoursSum->{Consumption} += $confc if($h < 2);
|
||||
$next2HoursSum->{Consumption} += $confc / 60 * $minute if($h == 2);
|
||||
}
|
||||
|
||||
if($h <= 3) {
|
||||
if ($h <= 3) {
|
||||
$next3HoursSum->{PV} += $pvfc if($h < 3);
|
||||
$next3HoursSum->{PV} += $pvfc / 60 * $minute if($h == 3);
|
||||
$next3HoursSum->{Consumption} += $confc if($h < 3);
|
||||
$next3HoursSum->{Consumption} += $confc / 60 * $minute if($h == 3);
|
||||
}
|
||||
|
||||
if($h <= 4) {
|
||||
if ($h <= 4) {
|
||||
$next4HoursSum->{PV} += $pvfc if($h < 4);
|
||||
$next4HoursSum->{PV} += $pvfc / 60 * $minute if($h == 4);
|
||||
$next4HoursSum->{Consumption} += $confc if($h < 4);
|
||||
$next4HoursSum->{Consumption} += $confc / 60 * $minute if($h == 4);
|
||||
}
|
||||
|
||||
if($istdy) {
|
||||
if ($istdy) {
|
||||
$restOfDaySum->{PV} += $pvfc;
|
||||
$restOfDaySum->{Consumption} += $confc;
|
||||
$tdConFcTillSunset += $confc if($don);
|
||||
@ -9526,7 +9618,7 @@ sub _calcCaQcomplex {
|
||||
|
||||
if (!$aln) {
|
||||
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_cloudcover', 'done');
|
||||
debugLog ($paref, 'pvCorrection', "Autolearning is switched off for hour: $h -> skip the recalculation of the complex correction factor");
|
||||
debugLog ($paref, 'pvCorrectionWrite', "Autolearning is switched off for hour: $h -> skip the recalculation of the complex correction factor");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -9560,7 +9652,7 @@ sub _calcCaQcomplex {
|
||||
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_cloudcover', 'done');
|
||||
|
||||
if ($acu =~ /on_complex/xs) {
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, cloudiness range: $crang, days in range: $dnum)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Sun Alt range: $sabin, Cloud range: $crang, Days in range: $dnum)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h).'_autocalc', 'done');
|
||||
}
|
||||
|
||||
@ -9584,13 +9676,13 @@ sub _calcCaQsimple {
|
||||
my $sr = ReadingsVal ($name, '.pvCorrectionFactor_'.sprintf("%02d",$h).'_apipercentil', '');
|
||||
|
||||
if($sr eq "done") {
|
||||
# debugLog ($paref, 'pvCorrection', "Simple Corrf factor Hour: ".sprintf("%02d",$h)." already calculated");
|
||||
# debugLog ($paref, 'pvCorrectionWrite', "Simple Corrf factor Hour: ".sprintf("%02d",$h)." already calculated");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$aln) {
|
||||
storeReading ('.pvCorrectionFactor_'.sprintf("%02d",$h).'_apipercentil', 'done');
|
||||
debugLog ($paref, 'pvCorrection', "Autolearning is switched off for hour: $h -> skip the recalculation of the simple correction factor");
|
||||
debugLog ($paref, 'pvCorrectionWrite', "Autolearning is switched off for hour: $h -> skip the recalculation of the simple correction factor");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -9602,8 +9694,12 @@ sub _calcCaQsimple {
|
||||
return;
|
||||
}
|
||||
|
||||
my $sunalt = HistoryVal ($hash, $day, sprintf("%02d",$h), 'sunalt', 0); # Sonne Altitude
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
|
||||
$paref->{pvrl} = $pvrl;
|
||||
$paref->{pvfc} = $pvfc;
|
||||
$paref->{sabin} = $sabin;
|
||||
$paref->{crang} = 'simple';
|
||||
$paref->{calc} = 'Simple';
|
||||
|
||||
@ -9611,13 +9707,14 @@ sub _calcCaQsimple {
|
||||
|
||||
delete $paref->{pvrl};
|
||||
delete $paref->{pvfc};
|
||||
delete $paref->{sabin};
|
||||
delete $paref->{crang};
|
||||
delete $paref->{calc};
|
||||
|
||||
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)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h), $factor." (automatic - old factor: $oldfac, Days in range: $dnum)");
|
||||
storeReading ('pvCorrectionFactor_'.sprintf("%02d",$h).'_autocalc', 'done');
|
||||
}
|
||||
|
||||
@ -9644,10 +9741,14 @@ sub __calcNewFactor {
|
||||
my $pvrlsum = $pvrl;
|
||||
my $pvfcsum = $pvfc;
|
||||
|
||||
my ($oldfac, $oldq) = CircularCloudkorrVal ($hash, sprintf("%02d",$h), $crang, 0); # bisher definierter Korrekturfaktor
|
||||
my ($pvhis, $fchis, $dnum) = CircularSumVal ($hash, sprintf("%02d",$h), $crang, 0);
|
||||
debugLog ($paref, 'pvCorrectionWrite', "$calc Corrf -> Start calculation correction factor for hour: $h");
|
||||
|
||||
my ($oldfac, $oldq) = CircularSunCloudkorrVal ($hash, sprintf("%02d",$h), $sabin, $crang, 0); # bisher definierter Korrekturfaktor / Qualität
|
||||
my ($pvhis, $fchis, $dnum) = CircularSumVal ($hash, sprintf("%02d",$h), $sabin, $crang, 0);
|
||||
$oldfac = 1 if(1 * $oldfac == 0);
|
||||
|
||||
debugLog ($paref, 'pvCorrectionWrite', "$calc Corrf -> read historical values: pv real sum: $pvhis, pv forecast sum: $fchis, days sum: $dnum");
|
||||
|
||||
if ($dnum) { # Werte in History vorhanden -> haben Prio !
|
||||
$dnum++;
|
||||
$pvrlsum = $pvrl + $pvhis;
|
||||
@ -9666,10 +9767,6 @@ sub __calcNewFactor {
|
||||
$factor = sprintf "%.2f", ($pvrl / $pvfc);
|
||||
}
|
||||
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$crang} = $pvrlsum; # PV Erzeugung Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$crang} = $pvfcsum; # PV Prognose Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$crang} = $dnum; # Anzahl aller historischen Tade dieser Range
|
||||
|
||||
my $maxvar = AttrVal ($name, 'affectMaxDayVariance', $defmaxvar); # max. Korrekturvarianz
|
||||
$factor = 1.00 if(1 * $factor == 0); # 0.00-Werte ignorieren (Schleifengefahr)
|
||||
|
||||
@ -9686,16 +9783,23 @@ sub __calcNewFactor {
|
||||
|
||||
my $qual = __calcFcQuality ($pvfc, $pvrl); # Qualität der Vorhersage für die vergangene Stunde
|
||||
|
||||
debugLog ($paref, 'pvCorrection', "$calc Corrf -> start calculation correction factor for hour: $h");
|
||||
debugLog ($paref, 'pvCorrection', "$calc Corrf -> determined values - hour: $h, cloudiness range: $crang, old corrf: $oldfac, new corrf: $factor, days: $dnum");
|
||||
debugLog ($paref, 'pvCorrection|saveData2Cache', "$calc Corrf -> write correction values into Circular - hour: $h, cloudiness range: $crang, factor: $factor, quality: $qual");
|
||||
debugLog ($paref, 'pvCorrectionWrite', "$calc Corrf -> determined values - hour: $h, Sun Altitude range: $sabin, Cloud range: $crang, old factor: $oldfac, new factor: $factor, days: $dnum");
|
||||
debugLog ($paref, 'pvCorrectionWrite|saveData2Cache', "$calc Corrf -> write correction values into Circular - hour: $h, Sun Altitude range: $sabin, Cloud range: $crang, factor: $factor, quality: $qual, days: $dnum");
|
||||
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$crang} = $factor; # Korrekturfaktor nach "Cloudcover" oder "Simple"
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$crang} = $qual;
|
||||
|
||||
if (defined $sabin) { # Korrekturfaktor für Sonne Altitude
|
||||
$sabin = 200 + $sabin; # 200 + value für pvcorrf Sonne Altitude
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$sabin} = $factor;
|
||||
if ($crang ne 'simple') {
|
||||
my $idx = $sabin.'.'.$crang; # value für pvcorrf Sonne Altitude
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$idx} = $pvrlsum; # PV Erzeugung Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$idx} = $pvfcsum; # PV Prognose Summe speichern
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$idx} = $dnum; # Anzahl aller historischen Tade dieser Range
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$idx} = $factor;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$idx} = $qual;
|
||||
}
|
||||
else {
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvrlsum}{$crang} = $pvrlsum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvfcsum}{$crang} = $pvfcsum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{dnumsum}{$crang} = $dnum;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{pvcorrf}{$crang} = $factor;
|
||||
$data{$type}{$name}{circular}{sprintf("%02d",$h)}{quality}{$crang} = $qual;
|
||||
}
|
||||
|
||||
return ($oldfac, $factor, $dnum);
|
||||
@ -10435,8 +10539,8 @@ sub _checkSetupNotComplete {
|
||||
my $medev = ReadingsVal ($name, 'currentMeterDev', undef); # Meter Device
|
||||
|
||||
my $peaks = ReadingsVal ($name, 'modulePeakString', undef); # String Peak
|
||||
my $dir = ReadingsVal ($name, 'moduleAzimuth', undef); # Modulausrichtung Konfig (Azimut)
|
||||
my $ta = ReadingsVal ($name, 'moduleDeclination', undef); # Modul Neigungswinkel Konfig
|
||||
my $maz = ReadingsVal ($name, 'moduleAzimuth', undef); # Modulausrichtung Konfig (Azimut)
|
||||
my $mdec = ReadingsVal ($name, 'moduleDeclination', undef); # Modul Neigungswinkel Konfig
|
||||
my $mrt = ReadingsVal ($name, 'moduleRoofTops', undef); # RoofTop Konfiguration (SolCast API)
|
||||
|
||||
my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt
|
||||
@ -10472,9 +10576,9 @@ sub _checkSetupNotComplete {
|
||||
my $chkicon = "<a onClick=$cmdplchk>$img</a>";
|
||||
my $chktitle = $htitles{plchk}{$lang};
|
||||
|
||||
if (!$is || !$wedev || !$radev || !$indev || !$medev || !$peaks ||
|
||||
(isSolCastUsed ($hash) ? (!$rip || !$mrt) : isVictronKiUsed ($hash) ? !$vrmcr : (!$dir || !$ta )) ||
|
||||
(isForecastSolarUsed ($hash) ? !$coset : '') ||
|
||||
if (!$is || !$wedev || !$radev || !$indev || !$medev || !$peaks ||
|
||||
(isSolCastUsed ($hash) ? (!$rip || !$mrt) : isVictronKiUsed ($hash) ? !$vrmcr : (!$maz || !$mdec )) ||
|
||||
(isForecastSolarUsed ($hash) ? !$coset : '') ||
|
||||
!defined $pv0) {
|
||||
$ret .= "<table class='roomoverview'>";
|
||||
$ret .= "<tr style='height:".$height."px'>";
|
||||
@ -10484,6 +10588,12 @@ sub _checkSetupNotComplete {
|
||||
if (!$wedev) { ## no critic 'Cascading'
|
||||
$ret .= $hqtxt{cfd}{$lang};
|
||||
}
|
||||
elsif (!$is) {
|
||||
$ret .= $hqtxt{ist}{$lang};
|
||||
}
|
||||
elsif (!$peaks) {
|
||||
$ret .= $hqtxt{mps}{$lang};
|
||||
}
|
||||
elsif (!$radev) {
|
||||
$ret .= $hqtxt{crd}{$lang};
|
||||
}
|
||||
@ -10493,22 +10603,16 @@ sub _checkSetupNotComplete {
|
||||
elsif (!$medev) {
|
||||
$ret .= $hqtxt{mid}{$lang};
|
||||
}
|
||||
elsif (!$is) {
|
||||
$ret .= $hqtxt{ist}{$lang};
|
||||
}
|
||||
elsif (!$peaks) {
|
||||
$ret .= $hqtxt{mps}{$lang};
|
||||
}
|
||||
elsif (!$rip && isSolCastUsed ($hash)) {
|
||||
$ret .= $hqtxt{rip}{$lang};
|
||||
}
|
||||
elsif (!$mrt && isSolCastUsed ($hash)) {
|
||||
$ret .= $hqtxt{mrt}{$lang};
|
||||
}
|
||||
elsif (!$dir && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
|
||||
elsif (!$maz && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
|
||||
$ret .= $hqtxt{mdr}{$lang};
|
||||
}
|
||||
elsif (!$ta && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
|
||||
elsif (!$mdec && !isSolCastUsed ($hash) && !isVictronKiUsed ($hash)) {
|
||||
$ret .= $hqtxt{mta}{$lang};
|
||||
}
|
||||
elsif (!$vrmcr && isVictronKiUsed ($hash)) {
|
||||
@ -11685,6 +11789,8 @@ sub _beamGraphicFirstHour {
|
||||
|
||||
$hfcg->{0}{weather} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'weatherid', 999);
|
||||
$hfcg->{0}{wcc} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'wcc', '-');
|
||||
$hfcg->{0}{sunalt} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'sunalt', '-');
|
||||
$hfcg->{0}{sunaz} = HistoryVal ($hash, $hfcg->{0}{day_str}, $hfcg->{0}{time_str}, 'sunaz', '-');
|
||||
}
|
||||
else {
|
||||
$val1 = CircularVal ($hash, $hfcg->{0}{time_str}, 'pvfc', 0);
|
||||
@ -11755,6 +11861,8 @@ sub _beamGraphicRemainingHours {
|
||||
|
||||
$hfcg->{$i}{weather} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'weatherid', 999);
|
||||
$hfcg->{$i}{wcc} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'wcc', '-');
|
||||
$hfcg->{$i}{sunalt} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'sunalt', '-');
|
||||
$hfcg->{$i}{sunaz} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'sunaz', '-');
|
||||
}
|
||||
else {
|
||||
$nh = sprintf '%02d', $i + $offset;
|
||||
@ -11769,6 +11877,8 @@ sub _beamGraphicRemainingHours {
|
||||
$val4 = NexthoursVal ($hash, 'NextHour'.$nh, 'confc', 0);
|
||||
$hfcg->{$i}{weather} = NexthoursVal ($hash, 'NextHour'.$nh, 'weatherid', 999);
|
||||
$hfcg->{$i}{wcc} = NexthoursVal ($hash, 'NextHour'.$nh, 'cloudcover', '-');
|
||||
$hfcg->{$i}{sunalt} = NexthoursVal ($hash, 'NextHour'.$nh, 'sunalt', '-');
|
||||
$hfcg->{$i}{sunaz} = NexthoursVal ($hash, 'NextHour'.$nh, 'sunaz', '-');
|
||||
#$val4 = (ReadingsVal($name,"NextHour".$ii."_IsConsumptionRecommended",'no') eq 'yes') ? $icon : undef;
|
||||
}
|
||||
|
||||
@ -12158,6 +12268,12 @@ sub __weatherOnBeam {
|
||||
|
||||
$wcc += 0 if(isNumeric ($wcc)); # Javascript Fehler vermeiden: https://forum.fhem.de/index.php/topic,117864.msg1233661.html#msg1233661
|
||||
$title .= ': '.$wcc;
|
||||
$title .= ' ';
|
||||
$title .= $htitles{sunpos}{$lang}.':';
|
||||
$title .= ' ';
|
||||
$title .= $htitles{elevatio}{$lang}.' '.$hfcg->{$i}{sunalt};
|
||||
$title .= ' ';
|
||||
$title .= $htitles{azimuth}{$lang}.' '.$hfcg->{$i}{sunaz};
|
||||
|
||||
if ($icon_name eq 'unknown') {
|
||||
debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer");
|
||||
@ -12708,7 +12824,7 @@ sub _addHourAiRawdata {
|
||||
|
||||
if (!$aln) {
|
||||
storeReading ('.signaldone_'.sprintf("%02d",$h), 'done');
|
||||
debugLog ($paref, 'pvCorrection', "Autolearning is switched off for hour: $h -> skip add AI raw data");
|
||||
debugLog ($paref, 'pvCorrectionRead', "Autolearning is switched off for hour: $h -> skip add AI raw data");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -13866,10 +13982,11 @@ sub listDataPool {
|
||||
my $aihit = NexthoursVal ($hash, $idx, 'aihit', '-');
|
||||
my $pvfc = NexthoursVal ($hash, $idx, 'pvfc', '-');
|
||||
my $neff = NexthoursVal ($hash, $idx, 'cloudcover', '-');
|
||||
my $sunalt = NexthoursVal ($hash, $idx, 'sunalt', '-');
|
||||
|
||||
my ($f,$q) = split "/", $pvcorrf;
|
||||
$sq .= "\n" if($sq);
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Cloud: $neff";
|
||||
$sq .= "Start: $nhts, Quality: $q, Factor: $f, AI usage: $aihit, PV expect: $pvfc Wh, Sun Alt: $sunalt, Cloud: $neff";
|
||||
}
|
||||
}
|
||||
|
||||
@ -13980,17 +14097,17 @@ sub _ldchash2val {
|
||||
|
||||
for my $f (sort {$a<=>$b} keys %{$pool->{$idx}{$key}}) {
|
||||
next if($f eq 'simple');
|
||||
if ($f !~ /2.{2}/xs) {
|
||||
if ($f !~ /\./xs) {
|
||||
$ret .= " " if($ret);
|
||||
$ret .= "$f=".$pool->{$idx}{$key}{$f};
|
||||
my $ct = ($ret =~ tr/=// // 0) / 10;
|
||||
$ret .= "\n " if($ct =~ /^([1-9])?$/);
|
||||
$ret .= "\n " if($ct =~ /^[1-9](.{1})?$/);
|
||||
}
|
||||
elsif ($f =~ /2.{2}/xs) {
|
||||
elsif ($f =~ /\./xs) {
|
||||
$ret2 .= " " if($ret2);
|
||||
$ret2 .= "$f=".$pool->{$idx}{$key}{$f};
|
||||
my $ct2 = ($ret2 =~ tr/=// // 0) / 10;
|
||||
$ret2 .= "\n " if($ct2 =~ /^([1-9])?$/);
|
||||
$ret2 .= "\n " if($ct2 =~ /^[1-9](.{1})?$/);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16026,8 +16143,7 @@ return $def;
|
||||
# rr1c - Gesamtniederschlag (1-stündig) letzte 1 Stunde kg/m2
|
||||
# temp - Außentemperatur
|
||||
# pvcorrf - PV Autokorrekturfaktoren (HASH),
|
||||
# - ohne Wertesummand: Faktoren bezogen auf Cloudcover
|
||||
# - 200 + sunalt: Faktoren bezogen auf Sonne Altitude
|
||||
# - <Sonne Altitude>.<Cloudcover>
|
||||
# lastTsMaxSocRchd - Timestamp des letzten Erreichens von SoC >= maxSoC
|
||||
# nextTsMaxSocChge - Timestamp bis zu dem die Batterie mindestens einmal maxSoC erreichen soll
|
||||
# days2care - verbleibende Tage bis der Batterie Pflege-SoC (default $maxSoCdef) erreicht sein soll
|
||||
@ -16063,107 +16179,75 @@ sub CircularVal {
|
||||
return $def;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Wert des Autokorrekturfaktors und dessen Qualität
|
||||
# für eine bestimmte Bewölkungs-Range aus dem circular-Hash
|
||||
# zurückliefern
|
||||
# Usage:
|
||||
# ($f,$q) = CircularCloudkorrVal ($hash, $hod, $crang, $def)
|
||||
###################################################################
|
||||
# Wert des Autokorrekturfaktors
|
||||
# für eine bestimmte Sun Altitude-Range aus dem Circular-Hash
|
||||
# zurückliefern
|
||||
# Usage:
|
||||
# $f = CircularSunCloudkorrVal ($hash, $hod, $sabin, $crang, $def)
|
||||
#
|
||||
# $f: Korrekturfaktor f. Stunde des Tages
|
||||
# $q: Qualität des Korrekturfaktors
|
||||
# $f: Korrekturfaktor f. Stunde des Tages
|
||||
#
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $crang: Range Bewölkung (1...100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $sabin: Sun Altitude Bin (0..90)
|
||||
# $crang: Bewölkung Bin (0..100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
#
|
||||
################################################################
|
||||
sub CircularCloudkorrVal {
|
||||
###################################################################
|
||||
sub CircularSunCloudkorrVal {
|
||||
my $hash = shift;
|
||||
my $hod = shift;
|
||||
my $sabin = shift;
|
||||
my $crang = shift;
|
||||
my $def = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $corrf = $def;
|
||||
my $qual = $def;
|
||||
my $idx = 'simple';
|
||||
|
||||
my $corrf = $def;
|
||||
my $quality = $def;
|
||||
if ($crang ne 'simple') {
|
||||
$idx = $sabin.'.'.$crang;
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}{$crang})) {
|
||||
$corrf = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$crang};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}{$idx})) {
|
||||
$corrf = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}{$crang})) {
|
||||
$quality = $data{$type}{$name}{circular}{$hod}{quality}{$crang};
|
||||
defined($data{$type}{$name}{circular}{$hod}{quality}{$idx})) {
|
||||
$qual = $data{$type}{$name}{circular}{$hod}{quality}{$idx};
|
||||
}
|
||||
|
||||
return ($corrf, $quality);
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Wert des Autokorrekturfaktors
|
||||
# für eine bestimmte Sun Altitude-Range aus dem Circular-Hash
|
||||
# zurückliefern
|
||||
# Usage:
|
||||
# $f = CircularSunaltkorrVal ($hash, $hod, $crang, $def)
|
||||
#
|
||||
# $f: Korrekturfaktor f. Stunde des Tages
|
||||
#
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $sabin: Range Sun Altitude (0..90)
|
||||
# $def: Defaultwert
|
||||
#
|
||||
################################################################
|
||||
sub CircularSunaltkorrVal {
|
||||
my $hash = shift;
|
||||
my $hod = shift;
|
||||
my $sunalt = shift;
|
||||
my $def = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $type = $hash->{TYPE};
|
||||
my $corrf = $def;
|
||||
|
||||
return $def if(!$sunalt);
|
||||
|
||||
my $sabin = sunalt2bin ($sunalt);
|
||||
$sabin = 200 + $sabin;
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvcorrf}{$sabin})) {
|
||||
$corrf = $data{$type}{$name}{circular}{$hod}{pvcorrf}{$sabin};
|
||||
}
|
||||
|
||||
return ($corrf);
|
||||
return ($corrf, $qual);
|
||||
}
|
||||
|
||||
########################################################################################################
|
||||
# Die durchschnittliche reale PV Erzeugung, PV Prognose und Tage
|
||||
# einer bestimmten Bewölkungs-Range aus dem circular-Hash zurückliefern
|
||||
# Usage:
|
||||
# ($pvrlsum, $pvfcsum, $dnumsum) = CircularSumVal ($hash, $hod, $crang, $def)
|
||||
# ($pvrlsum, $pvfcsum, $dnumsum) = CircularSumVal ($hash, $hod, $sabin, $crang, $def)
|
||||
#
|
||||
# $pvrlsum: Summe reale PV Erzeugung pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
# $pvfcsum: Summe PV Prognose pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
# $dnumsum: Anzahl Tage pro Bewölkungsbereich über die gesamte Laufzeit
|
||||
#
|
||||
# $hod: Stunde des Tages (01,02,...,24)
|
||||
# $crang: Range Bewölkung (1...100) oder "simple"
|
||||
# $hod: Stunde des Tages (01,02,..,24)
|
||||
# $sabin: Sun Altitude Bin (0..90)
|
||||
# $crang: Bewölkung Bin (1..100) oder "simple"
|
||||
# $def: Defaultwert
|
||||
#
|
||||
#######################################################################################################
|
||||
sub CircularSumVal {
|
||||
my $hash = shift;
|
||||
my $hod = shift;
|
||||
my $sabin = shift;
|
||||
my $crang = shift;
|
||||
my $def = shift;
|
||||
|
||||
@ -16173,26 +16257,31 @@ sub CircularSumVal {
|
||||
my $pvrlsum = $def;
|
||||
my $pvfcsum = $def;
|
||||
my $dnumsum = $def;
|
||||
my $idx = 'simple';
|
||||
|
||||
if ($crang ne 'simple') {
|
||||
$idx = $sabin.'.'.$crang;
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}{$crang})) {
|
||||
$pvrlsum = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$crang};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvrlsum}{$idx})) {
|
||||
$pvrlsum = $data{$type}{$name}{circular}{$hod}{pvrlsum}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}{$crang})) {
|
||||
$pvfcsum = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$crang};
|
||||
defined($data{$type}{$name}{circular}{$hod}{pvfcsum}{$idx})) {
|
||||
$pvfcsum = $data{$type}{$name}{circular}{$hod}{pvfcsum}{$idx};
|
||||
}
|
||||
|
||||
if (defined($data{$type}{$name}{circular}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}) &&
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}{$crang})) {
|
||||
$dnumsum = $data{$type}{$name}{circular}{$hod}{dnumsum}{$crang};
|
||||
defined($data{$type}{$name}{circular}{$hod}{dnumsum}{$idx})) {
|
||||
$dnumsum = $data{$type}{$name}{circular}{$hod}{dnumsum}{$idx};
|
||||
}
|
||||
|
||||
return ($pvrlsum, $pvfcsum, $dnumsum);
|
||||
@ -17522,6 +17611,8 @@ to ensure that the system configuration is correct.
|
||||
The hours 01 - 24 refer to the hour of the day, e.g. the hour 09 refers to the time from
|
||||
08 - 09 o'clock. <br>
|
||||
Hour 99 has a special function. <br>
|
||||
The values of the keys pvcorrf, quality, pvrlsum, pvfcsum and dnumsum are coded in the form
|
||||
<range sun elevation>.<cloud cover range>. <br>
|
||||
Explanation of the values: <br><br>
|
||||
|
||||
<ul>
|
||||
@ -18039,7 +18130,8 @@ to ensure that the system configuration is correct.
|
||||
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
||||
<tr><td> <b>graphic</b> </td><td>Module graphic information </td></tr>
|
||||
<tr><td> <b>notifyHandling</b> </td><td>Sequence of event processing in the module </td></tr>
|
||||
<tr><td> <b>pvCorrection</b> </td><td>Calculation and application PV correction factors </td></tr>
|
||||
<tr><td> <b>pvCorrectionRead</b> </td><td>Application of PV correction factors </td></tr>
|
||||
<tr><td> <b>pvCorrectionWrite</b> </td><td>Calculation of PV correction factors </td></tr>
|
||||
<tr><td> <b>radiationProcess</b> </td><td>Collection and processing of solar radiation data </td></tr>
|
||||
<tr><td> <b>saveData2Cache</b> </td><td>Data storage in internal memory structures </td></tr>
|
||||
</table>
|
||||
@ -19653,6 +19745,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
Die Stundenangaben 01 - 24 beziehen sich auf die Stunde des Tages, z.B. bezieht sich die Stunde 09 auf die Zeit von
|
||||
08 - 09 Uhr. <br>
|
||||
Die Stunde 99 hat eine Sonderfunktion. <br>
|
||||
Die Werte der Schlüssel pvcorrf, quality, pvrlsum, pvfcsum und dnumsum sind in der Form
|
||||
<Bereich Sonnenstand Höhe>.<Bewölkungsbreich> kodiert. <br>
|
||||
Erläuterung der Werte: <br><br>
|
||||
|
||||
<ul>
|
||||
@ -20171,7 +20265,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
||||
<tr><td> <b>graphic</b> </td><td>Informationen der Modulgrafik </td></tr>
|
||||
<tr><td> <b>notifyHandling</b> </td><td>Ablauf der Eventverarbeitung im Modul </td></tr>
|
||||
<tr><td> <b>pvCorrection</b> </td><td>Berechnung und Anwendung PV Korrekturfaktoren </td></tr>
|
||||
<tr><td> <b>pvCorrectionRead</b> </td><td>Anwendung PV Korrekturfaktoren </td></tr>
|
||||
<tr><td> <b>pvCorrectionWrite</b> </td><td>Berechnung PV Korrekturfaktoren </td></tr>
|
||||
<tr><td> <b>radiationProcess</b> </td><td>Sammlung und Verarbeitung der Solarstrahlungsdaten </td></tr>
|
||||
<tr><td> <b>saveData2Cache</b> </td><td>Datenspeicherung in internen Speicherstrukturen </td></tr>
|
||||
</table>
|
||||
|
Loading…
Reference in New Issue
Block a user