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 # Versions History intern
my %vNotesIntern = ( 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.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.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 ", "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 # Erstellung Batterie Ladefreigabe + SoC Prognose
################################################################ ################################################################
sub _batChargeMgmt { sub _batChargeMgmt {
my $paref = shift; my $paref = shift;
my $name = $paref->{name}; my $name = $paref->{name};
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $t = $paref->{t}; my $minute = $paref->{minute}; # aktuelle Minute (00-59)
my $t = $paref->{t};
return if(!isBatteryUsed ($name)); return if(!isBatteryUsed ($name));
@@ -11800,7 +11801,7 @@ sub _batChargeMgmt {
$spday = 0 if($spday < 0); # PV Überschuß Prognose bis Sonnenuntergang $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) $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 ## Steuerung nach Ladefreigabe
################################ ################################
@@ -11814,14 +11815,14 @@ sub _batChargeMgmt {
# Steuerhash für optimimierte Ladeleistung erstellen # 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 if ($strategy eq 'optPower' || $strategy eq 'loadRelease' && $today) { # bei loadRelease' nur den aktuellen Tag betrachten
$hsurp->{$fd}{$hod}{nhr} = $nhr; $hsurp->{$fd}{$hod}{nhr} = $nhr;
$hsurp->{$fd}{$hod}{speff} = $surpls; # effektiver PV Überschuß bzw. effektiver Verbrauch wenn < 0 $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}{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}{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}{batinstcap} = $batinstcap; # installierte Batteriekapazität (Wh)
$hsurp->{$fd}{$hod}{$bn}{goalwh} = $goalwh; # Ladeziel $hsurp->{$fd}{$hod}{$bn}{goalwh} = $goalwh; # Ladeziel
$hsurp->{$fd}{$hod}{$bn}{bpinmax} = $bpinmax; # max. mögliche Ladeleistung $hsurp->{$fd}{$hod}{$bn}{bpinmax} = $bpinmax; # max. mögliche Ladeleistung
@@ -11838,6 +11839,9 @@ sub _batChargeMgmt {
$hsurp->{$fd}{$hod}{$bn}{befficiency} = $befficiency; # Speicherwirkungsgrad $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 ## SOC-Prognose LR
#################### ####################
my $speff = $surpls; # effektiver PV Überschuß bzw. effektiver Verbrauch wenn < 0 my $speff = $surpls; # effektiver PV Überschuß bzw. effektiver Verbrauch wenn < 0
@@ -11904,9 +11908,11 @@ sub _batChargeMgmt {
# leistungsoptimierte (optPower) Beladungssteuerung # leistungsoptimierte (optPower) Beladungssteuerung
##################################################### #####################################################
my $trans = {}; # Übertrags-Hash Referenz
for my $lfd (0..max (0, keys %{$hsurp})) { for my $lfd (0..max (0, keys %{$hsurp})) {
$paref->{hsurp} = $hsurp->{$lfd}; $paref->{hsurp} = $hsurp->{$lfd};
my ($hopt, $otp) = __batChargeOptTargetPower ($paref); my ($hopt, $otp) = __batChargeOptTargetPower ($paref, $lfd, $trans);
delete $paref->{hsurp}; delete $paref->{hsurp};
## Debuglog OTP ## Debuglog OTP
@@ -11923,7 +11929,7 @@ sub _batChargeMgmt {
for my $bat (sort @batteries) { for my $bat (sort @batteries) {
next if(!defined $hopt->{$shod}{$bat}{batinstcap}); next if(!defined $hopt->{$shod}{$bat}{batinstcap});
my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-'; my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-';
## SOC-Prognose OTP ## SOC-Prognose OTP
##################### #####################
@@ -12018,6 +12024,9 @@ return;
################################################################ ################################################################
sub __batChargeOptTargetPower { sub __batChargeOptTargetPower {
my $paref = shift; my $paref = shift;
my $lfd = shift; # laufender Tag (1..X)
my $trans = shift; # Übertrags-Hash Referenz
my $name = $paref->{name}; my $name = $paref->{name};
my $hsurp = $paref->{hsurp}; # Hashref Überschußhash 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 @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 @batteries = grep { !/^(?:fd|speff|surplswh|nhr)$/xs } keys %{$hsurp->{24}};
my $otp; my $otp;
my $fcendwh;
for my $hod (sort { $a <=> $b } keys %{$hsurp}) { for my $hod (sort { $a <=> $b } keys %{$hsurp}) {
my $nhr = $hsurp->{$hod}{nhr}; my $nhr = $hsurp->{$hod}{nhr};
@@ -12034,22 +12044,29 @@ sub __batChargeOptTargetPower {
my @remaining_hods = grep { int $_ >= int $hod } @sortedhods; my @remaining_hods = grep { int $_ >= int $hod } @sortedhods;
for my $sbn (sort { $a <=> $b } @batteries) { # jede Batterie for my $sbn (sort { $a <=> $b } @batteries) { # jede Batterie
my $bpinmax = $hsurp->{$hod}{$sbn}{bpinmax}; # Bat max. mögliche Ladelesitung my $bpinmax = $hsurp->{$hod}{$sbn}{bpinmax}; # Bat max. mögliche Ladelesitung
my $sbatinstcap = $hsurp->{$hod}{$sbn}{batinstcap}; # Kapa dieser Batterie my $batinstcap = $hsurp->{$hod}{$sbn}{batinstcap}; # Kapa dieser Batterie
my $lowSocwh = $hsurp->{$hod}{$sbn}{lowSocwh}; # eingestellter lowSoc in Wh 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 $csocwh = $hsurp->{$hod}{$sbn}{csocwh}; # aktueller SoC in Wh
my $bpinreduced = $hsurp->{$hod}{$sbn}{bpinreduced}; # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid my $bpinreduced = $hsurp->{$hod}{$sbn}{bpinreduced}; # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid
my $befficiency = $hsurp->{$hod}{$sbn}{befficiency}; # Speicherwirkungsgrad my $befficiency = $hsurp->{$hod}{$sbn}{befficiency}; # Speicherwirkungsgrad
my $runwh = defined $hsurp->{$hod}{$sbn}{fcnextwh} ? # Auswahl des zu verwendenden Prognose-SOC (Wh) # Initialisierung / Fortschreibung Prognose-SOC (Wh)
$hsurp->{$hod}{$sbn}{fcnextwh} : ######################################################
( $nhr eq '00' ? my $fc_next_wh = $hsurp->{$hod}{$sbn}{fcnextwh};
$csocwh : my $init_soc_wh = $hsurp->{$hod}{$sbn}{initsocwh};
$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 $hsurp->{$hod}{$sbn}{runwh} = sprintf "%.0f", $runwh; # Startwert für DebugLog
## Ziel und dessen Erreichbarkeit ## Ziel und dessen Erreichbarkeit
@@ -12072,7 +12089,13 @@ sub __batChargeOptTargetPower {
$hsurp->{$hod}{$sbn}{pneedmin} = $bpinmax; $hsurp->{$hod}{$sbn}{pneedmin} = $bpinmax;
$runwh += $hsurp->{$hod}{speff} / $befficiency; # um Verbrauch reduzieren $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 $hsurp->{$nexthod}{$sbn}{fcnextwh} = $hsurp->{$hod}{$sbn}{fcendwh} if(defined $nextnhr); # Startwert kommende Stunde
if ($nhr eq '00') { if ($nhr eq '00') {
@@ -12120,20 +12143,28 @@ sub __batChargeOptTargetPower {
$otp->{$sbn}{target} = $target; $otp->{$sbn}{target} = $target;
} }
$fcendwh = min ($goalwh, $runwh # Endwert Prognose aktuelle Stunde
+ $befficiency
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", min ($goalwh, $runwh # Endwert Prognose aktuelle Stunde * ($nhr eq '00'
+ $befficiency ? $otp->{$sbn}{target}
* ($nhr eq '00' : $spls
? $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); return ($hsurp, $otp);
} }