76_SolarForecast: contrib V1.59.1

git-svn-id: https://svn.fhem.de/fhem/trunk@30362 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
DS_Starter
2025-10-07 19:37:12 +00:00
parent 5c301333b5
commit 0744383100

View File

@@ -160,7 +160,7 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
"1.59.1" => "07.10.2025 ",
"1.59.1" => "07.10.2025 fixed transfer at day change, optimal SoC consideration in SoC forecast for optPower strategy ",
"1.59.0" => "06.10.2025 new sub __normIconInnerScale to fix problem with chromium engine > 140.x, Forum: https://forum.fhem.de/index.php?msg=1349058 ",
"1.58.8" => "06.10.2025 __batChargeOptTargetPower: minor Code change ",
"1.58.7" => "05.10.2025 fix negative SoC forecast when using optPower Forum: https://forum.fhem.de/index.php?msg=1348954 ",
@@ -11602,10 +11602,11 @@ return $sf;
# Erstellung Batterie Ladefreigabe + SoC Prognose
################################################################
sub _batChargeMgmt {
my $paref = shift;
my $name = $paref->{name};
my $chour = $paref->{chour};
my $t = $paref->{t};
my $paref = shift;
my $name = $paref->{name};
my $chour = $paref->{chour};
my $minute = $paref->{minute}; # aktuelle Minute (00-59)
my $t = $paref->{t};
return if(!isBatteryUsed ($name));
@@ -11800,7 +11801,7 @@ sub _batChargeMgmt {
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang
$confc *= (100 - $wou) / 100 if($pvfc > 0); # Gewichtung Prognose-Verbrauch als Anteil "Eigennutzung" (https://forum.fhem.de/index.php?msg=1348429)
my $surpls = sprintf "%.0f", ($pvfc - $confc); # PV-Überschuß der Stunde, wichtig keine Nachkommastellen!
my $surpls = $pvfc - $confc;
## Steuerung nach Ladefreigabe
################################
@@ -11814,14 +11815,14 @@ sub _batChargeMgmt {
# Steuerhash für optimimierte Ladeleistung erstellen
######################################################
my $surplswh = max (0, $surpls);
my $surplswh = max (0, (sprintf "%.0f", $surpls)); # wichtig keine Nachkommastellen!
if ($strategy eq 'optPower' || $strategy eq 'loadRelease' && $today) { # bei loadRelease' nur den aktuellen Tag betrachten
$hsurp->{$fd}{$hod}{nhr} = $nhr;
$hsurp->{$fd}{$hod}{speff} = $surpls; # effektiver PV Überschuß bzw. effektiver Verbrauch wenn < 0
$hsurp->{$fd}{$hod}{surplswh} = $surplswh.'.'.$hod; # absoluter Überschuß in Wh der Stunde mit Sortierhilfe
$hsurp->{$fd}{$hod}{$bn}{spday} = $spday; # (Rest)PV-Überschuß am laufenden Tag
$hsurp->{$fd}{$hod}{$bn}{initsocwh} = $socwh;
$hsurp->{$fd}{$hod}{$bn}{initsocwh} = $socwh; # durch LR fortgeschriebener SoC
$hsurp->{$fd}{$hod}{$bn}{batinstcap} = $batinstcap; # installierte Batteriekapazität (Wh)
$hsurp->{$fd}{$hod}{$bn}{goalwh} = $goalwh; # Ladeziel
$hsurp->{$fd}{$hod}{$bn}{bpinmax} = $bpinmax; # max. mögliche Ladeleistung
@@ -11838,6 +11839,9 @@ sub _batChargeMgmt {
$hsurp->{$fd}{$hod}{$bn}{befficiency} = $befficiency; # Speicherwirkungsgrad
}
$surpls = $surpls / 60 * (60 - int $minute) if(!$num); # aktuelle (Rest)-Stunde -> zeitgewichteter PV-Überschuß
$surpls = sprintf "%.0f", $surpls; # wichtig keine Nachkommastellen!
## SOC-Prognose LR
####################
my $speff = $surpls; # effektiver PV Überschuß bzw. effektiver Verbrauch wenn < 0
@@ -11904,9 +11908,11 @@ sub _batChargeMgmt {
# leistungsoptimierte (optPower) Beladungssteuerung
#####################################################
my $trans = {}; # Übertrags-Hash Referenz
for my $lfd (0..max (0, keys %{$hsurp})) {
$paref->{hsurp} = $hsurp->{$lfd};
my ($hopt, $otp) = __batChargeOptTargetPower ($paref);
my ($hopt, $otp) = __batChargeOptTargetPower ($paref, $lfd, $trans);
delete $paref->{hsurp};
## Debuglog OTP
@@ -11923,7 +11929,7 @@ sub _batChargeMgmt {
for my $bat (sort @batteries) {
next if(!defined $hopt->{$shod}{$bat}{batinstcap});
my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-';
my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-';
## SOC-Prognose OTP
#####################
@@ -12018,6 +12024,9 @@ return;
################################################################
sub __batChargeOptTargetPower {
my $paref = shift;
my $lfd = shift; # laufender Tag (1..X)
my $trans = shift; # Übertrags-Hash Referenz
my $name = $paref->{name};
my $hsurp = $paref->{hsurp}; # Hashref Überschußhash
@@ -12025,6 +12034,7 @@ sub __batChargeOptTargetPower {
my @sortedhods = sort { $hsurp->{$a}{surplswh} <=> $hsurp->{$b}{surplswh} } keys %{$hsurp}; # Stunden aufsteigend nach PV-Überschuß sortiert
my @batteries = grep { !/^(?:fd|speff|surplswh|nhr)$/xs } keys %{$hsurp->{24}};
my $otp;
my $fcendwh;
for my $hod (sort { $a <=> $b } keys %{$hsurp}) {
my $nhr = $hsurp->{$hod}{nhr};
@@ -12034,22 +12044,29 @@ sub __batChargeOptTargetPower {
my @remaining_hods = grep { int $_ >= int $hod } @sortedhods;
for my $sbn (sort { $a <=> $b } @batteries) { # jede Batterie
my $bpinmax = $hsurp->{$hod}{$sbn}{bpinmax}; # Bat max. mögliche Ladelesitung
my $sbatinstcap = $hsurp->{$hod}{$sbn}{batinstcap}; # Kapa dieser Batterie
for my $sbn (sort { $a <=> $b } @batteries) { # jede Batterie
my $bpinmax = $hsurp->{$hod}{$sbn}{bpinmax}; # Bat max. mögliche Ladelesitung
my $batinstcap = $hsurp->{$hod}{$sbn}{batinstcap}; # Kapa dieser Batterie
my $lowSocwh = $hsurp->{$hod}{$sbn}{lowSocwh}; # eingestellter lowSoc in Wh
my $batoptsocwh = $hsurp->{$hod}{$sbn}{batoptsocwh}; # optimaler SoC in Wh
my $csocwh = $hsurp->{$hod}{$sbn}{csocwh}; # aktueller SoC in Wh
my $bpinreduced = $hsurp->{$hod}{$sbn}{bpinreduced}; # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid
my $befficiency = $hsurp->{$hod}{$sbn}{befficiency}; # Speicherwirkungsgrad
my $runwh = defined $hsurp->{$hod}{$sbn}{fcnextwh} ? # Auswahl des zu verwendenden Prognose-SOC (Wh)
$hsurp->{$hod}{$sbn}{fcnextwh} :
( $nhr eq '00' ?
$csocwh :
$hsurp->{$hod}{$sbn}{initsocwh}
);
# Initialisierung / Fortschreibung Prognose-SOC (Wh)
######################################################
my $fc_next_wh = $hsurp->{$hod}{$sbn}{fcnextwh};
my $init_soc_wh = $hsurp->{$hod}{$sbn}{initsocwh};
my $transfer = $trans->{$sbn}{$lfd}{transfer};
$runwh = min ($runwh, $sbatinstcap);
my $runwh = do {
if (defined $fc_next_wh) { $fc_next_wh }
elsif ($nhr eq '00') { $csocwh }
elsif (defined $transfer) { delete $trans->{$sbn}{$lfd}{transfer} }
else { $init_soc_wh }
};
$runwh = min ($runwh, $batinstcap);
$hsurp->{$hod}{$sbn}{runwh} = sprintf "%.0f", $runwh; # Startwert für DebugLog
## Ziel und dessen Erreichbarkeit
@@ -12072,7 +12089,13 @@ sub __batChargeOptTargetPower {
$hsurp->{$hod}{$sbn}{pneedmin} = $bpinmax;
$runwh += $hsurp->{$hod}{speff} / $befficiency; # um Verbrauch reduzieren
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", max ($lowSocwh, $runwh); # untere Begrenzung auf lowSoC
$fcendwh = $runwh < $lowSocwh ? $lowSocwh : # fcendwh begrenzen
$runwh < $batoptsocwh ? $batoptsocwh :
$runwh > $batinstcap ? $batinstcap :
$runwh;
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", $fcendwh;
$hsurp->{$nexthod}{$sbn}{fcnextwh} = $hsurp->{$hod}{$sbn}{fcendwh} if(defined $nextnhr); # Startwert kommende Stunde
if ($nhr eq '00') {
@@ -12120,20 +12143,28 @@ sub __batChargeOptTargetPower {
$otp->{$sbn}{target} = $target;
}
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", min ($goalwh, $runwh # Endwert Prognose aktuelle Stunde
+ $befficiency
* ($nhr eq '00'
? $otp->{$sbn}{target}
: $spls
)
);
$fcendwh = min ($goalwh, $runwh # Endwert Prognose aktuelle Stunde
+ $befficiency
* ($nhr eq '00'
? $otp->{$sbn}{target}
: $spls
)
);
$fcendwh = $runwh < $lowSocwh ? $lowSocwh : # fcendwh begrenzen
$runwh < $batoptsocwh ? $batoptsocwh :
$runwh > $batinstcap ? $batinstcap :
$runwh;
$hsurp->{$nexthod}{$sbn}{fcnextwh} = $hsurp->{$hod}{$sbn}{fcendwh} if(defined $nextnhr); # Startwert kommende Stunde
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", $fcendwh;
$hsurp->{$nexthod}{$sbn}{fcnextwh} = $hsurp->{$hod}{$sbn}{fcendwh} if(defined $nextnhr); # Startwert kommende Stunde
}
}
for my $bat (sort { $a <=> $b } @batteries) {
$trans->{$bat}{$lfd + 1}{transfer} = $hsurp->{24}{$bat}{fcendwh}; # Übertrag SoC-Prognose für kommenden Tag
}
return ($hsurp, $otp);
}