76_SolarForecast: contrib V1.58.6

git-svn-id: https://svn.fhem.de/fhem/trunk@30345 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
DS_Starter
2025-10-03 09:07:20 +00:00
parent 6212da542d
commit 471923fd89

View File

@@ -160,9 +160,9 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.58.6" => "01.10.2025 __batChargeMgmt code changed, new sub ___batChargeSaveResults, remove reading Battery_ChargeRecommended_XX ". "1.58.6" => "03.10.2025 __batChargeMgmt code changed, new sub ___batChargeSaveResults, remove reading Battery_ChargeRecommended_XX ".
"_calcReadingsTomorrowPVFc: bugfix generating readings of tomorrow ". "_calcReadingsTomorrowPVFc: bugfix generating readings of tomorrow ".
"__batChargeOptTargetPower: complete rework, Attr ctrlBatSocManagementXX new key 'loadStrategy' ", "__batChargeOptTargetPower: complete rework, Attr ctrlBatSocManagementXX new keys 'loadStrategy', 'weightOwnUse' ",
"1.58.5" => "24.09.2025 __batChargeOptTargetPower: fix if battery load control is deactivated ", "1.58.5" => "24.09.2025 __batChargeOptTargetPower: fix if battery load control is deactivated ",
"1.58.4" => "23.09.2025 __batChargeOptTargetPower: user a better surplus value, excess based on average removed & some other code optimization ", "1.58.4" => "23.09.2025 __batChargeOptTargetPower: user a better surplus value, excess based on average removed & some other code optimization ",
"1.58.3" => "17.09.2025 __batChargeOptTargetPower: minor code change, consider bpinmax & lcintime ", "1.58.3" => "17.09.2025 __batChargeOptTargetPower: minor code change, consider bpinmax & lcintime ",
@@ -7526,6 +7526,7 @@ sub _attrBatSocManagement { ## no critic "not used"
loadAbort => { comp => '(?:100|[1-9]?[0-9]):\d+(?::(?:100|[1-9]?[0-9]))?', must => 0, act => 0 }, loadAbort => { comp => '(?:100|[1-9]?[0-9]):\d+(?::(?:100|[1-9]?[0-9]))?', must => 0, act => 0 },
safetyMargin => { comp => '(?:100|[1-9]?\d)(?::(?:100|[1-9]?\d))?', must => 0, act => 0 }, safetyMargin => { comp => '(?:100|[1-9]?\d)(?::(?:100|[1-9]?\d))?', must => 0, act => 0 },
loadStrategy => { comp => '(loadRelease|optPower)', must => 0, act => 0 }, loadStrategy => { comp => '(loadRelease|optPower)', must => 0, act => 0 },
weightOwnUse => { comp => '(?:100|[1-9]?\d)(?::(?:100|[1-9]?\d))?', must => 0, act => 0 },
}; };
my ($a, $h) = parseParams ($aVal); my ($a, $h) = parseParams ($aVal);
@@ -11534,9 +11535,9 @@ sub __parseAttrBatSoc {
my $name = shift; my $name = shift;
my $cgbt = shift // return; my $cgbt = shift // return;
my ($urMargin, $otpMargin); my ($lrMargin, $otpMargin);
my ($pa, $ph) = parseParams ($cgbt); my ($pa, $ph) = parseParams ($cgbt);
($urMargin, $otpMargin) = split ':', $ph->{safetyMargin} if(defined $ph->{safetyMargin}); ($lrMargin, $otpMargin) = split ':', $ph->{safetyMargin} if(defined $ph->{safetyMargin});
my $parsed = { my $parsed = {
lowSoc => $ph->{lowSoc}, lowSoc => $ph->{lowSoc},
@@ -11545,8 +11546,9 @@ sub __parseAttrBatSoc {
careCycle => $ph->{careCycle} // CARECYCLEDEF, # Ladungszyklus (Maintenance) für maxSoC in Tagen careCycle => $ph->{careCycle} // CARECYCLEDEF, # Ladungszyklus (Maintenance) für maxSoC in Tagen
lcslot => $ph->{lcSlot}, lcslot => $ph->{lcSlot},
loadAbort => $ph->{loadAbort}, loadAbort => $ph->{loadAbort},
loadStrategy => $ph->{loadStrategy}, loadStrategy => $ph->{loadStrategy},
urMargin => $urMargin, weightOwnUse => $ph->{weightOwnUse},
lrMargin => $lrMargin,
otpMargin => $otpMargin, otpMargin => $otpMargin,
}; };
@@ -11649,35 +11651,38 @@ sub _batChargeMgmt {
next; next;
} }
my $maxfctim = timestringToTimestamp (ReadingsVal ($name, 'Today_MaxPVforecastTime', '')) // $t; my $maxfctim = timestringToTimestamp (ReadingsVal ($name, 'Today_MaxPVforecastTime', '')) // $t;
my $rodpvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Prognose Rest des Tages my $rodpvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); # PV Prognose Rest des Tages
my $tompvfc = ReadingsNum ($name, 'Tomorrow_PVforecast', 0); # PV Prognose nächster Tag my $tompvfc = ReadingsNum ($name, 'Tomorrow_PVforecast', 0); # PV Prognose nächster Tag
my $tomconfc = ReadingsNum ($name, 'Tomorrow_ConsumptionForecast', 0); # Verbrauchsprognose nächster Tag my $tomconfc = ReadingsNum ($name, 'Tomorrow_ConsumptionForecast', 0); # Verbrauchsprognose nächster Tag
my $batoptsoc = ReadingsNum ($name, 'Battery_OptimumTargetSoC_'.$bn, 0); # aktueller optimierter SoC my $batoptsoc = ReadingsNum ($name, 'Battery_OptimumTargetSoC_'.$bn, 0); # aktueller optimierter SoC
my $confcss = CurrentVal ($name, 'tdConFcTillSunset', 0); # Verbrauchsprognose bis Sonnenuntergang my $confcss = CurrentVal ($name, 'tdConFcTillSunset', 0); # Verbrauchsprognose bis Sonnenuntergang
my $csoc = BatteryVal ($name, $bn, 'bcharge', 0); # aktuelle Ladung in % my $csoc = BatteryVal ($name, $bn, 'bcharge', 0); # aktuelle Ladung in %
my $csocwh = BatteryVal ($name, $bn, 'bchargewh', 0); # aktuelle Ladung in Wh my $csocwh = BatteryVal ($name, $bn, 'bchargewh', 0); # aktuelle Ladung in Wh
my $bpinmax = BatteryVal ($name, $bn, 'bpinmax', INFINITE); # max. mögliche Ladeleistung W my $bpinmax = BatteryVal ($name, $bn, 'bpinmax', INFINITE); # max. mögliche Ladeleistung W
my $bpoutmax = BatteryVal ($name, $bn, 'bpoutmax', INFINITE); # max. mögliche Entladeleistung W my $bpoutmax = BatteryVal ($name, $bn, 'bpoutmax', INFINITE); # max. mögliche Entladeleistung W
my $bpowerin = BatteryVal ($name, $bn, 'bpowerin', INFINITE); # aktuelle Ladeleistung W my $bpowerin = BatteryVal ($name, $bn, 'bpowerin', INFINITE); # aktuelle Ladeleistung W
my $cgbt = AttrVal ($name, 'ctrlBatSocManagement'.$bn, undef); my $bpinreduced = BatteryVal ($name, $bn, 'bpinreduced', 0); # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid
my $sf = __batCapShareFactor ($hash, $bn); # Anteilsfaktor der Batterie XX Kapazität an Gesamtkapazität my $cgbt = AttrVal ($name, 'ctrlBatSocManagement'.$bn, undef);
my $strategy = 'loadRelease'; # 'loadRelease' oder 'optPower' my $sf = __batCapShareFactor ($hash, $bn); # Anteilsfaktor der Batterie XX Kapazität an Gesamtkapazität
my $lowSoc = 0; my $strategy = 'loadRelease'; # 'loadRelease' oder 'optPower'
my $loadAbort = ''; my $wou = 0; # Gewichtung Prognose-Verbrauch als Anteil "Eigennutzung" (https://forum.fhem.de/index.php?msg=1348429)
my ($lcslot, $urMargin, $otpMargin); my $lowSoc = 0;
my $loadAbort = '';
my $lrMargin = SFTYMARGIN_50;
my $otpMargin = SFTYMARGIN_20;
my $lcslot;
if ($cgbt) { if ($cgbt) {
my $parsed = __parseAttrBatSoc ($name, $cgbt); my $parsed = __parseAttrBatSoc ($name, $cgbt);
$lowSoc = $parsed->{lowSoc} // 0; $lowSoc = $parsed->{lowSoc} // 0;
$lcslot = $parsed->{lcslot}; $lcslot = $parsed->{lcslot};
$loadAbort = $parsed->{loadAbort}; $loadAbort = $parsed->{loadAbort};
$urMargin = $parsed->{urMargin}; $lrMargin = $parsed->{lrMargin} // $lrMargin; # Sicherheitszuschlag LR (%)
$otpMargin = $parsed->{otpMargin}; $otpMargin = $parsed->{otpMargin} // $otpMargin; # Sicherheitszuschlag OTP (%)
$strategy = $parsed->{loadStrategy} // $strategy; $strategy = $parsed->{loadStrategy} // $strategy;
$wou = $parsed->{weightOwnUse} // $wou;
} }
my $margin = defined $urMargin ? $urMargin : SFTYMARGIN_50; # Sicherheitszuschlag (%)
## generelle Ladeabbruchbedingung evaluieren ## generelle Ladeabbruchbedingung evaluieren
############################################## ##############################################
@@ -11717,7 +11722,8 @@ sub _batChargeMgmt {
Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - control time Slot - Slot start: $lcstart, Slot end: $lcend"); Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - control time Slot - Slot start: $lcstart, Slot end: $lcend");
Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - Installed Battery capacity: $batinstcap Wh, Percentage of total capacity: ".(sprintf "%.1f", $sf*100)." %"); Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - Installed Battery capacity: $batinstcap Wh, Percentage of total capacity: ".(sprintf "%.1f", $sf*100)." %");
Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - The PV generation, consumption and surplus listed below are based on the battery's share of total installed capacity!"); Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeMgmt - The PV generation, consumption and surplus listed below are based on the battery's share of total installed capacity!");
Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeLR - used safety margin: $margin %"); Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeLR - used safety margin: $lrMargin %");
Log3 ($name, 1, "$name DEBUG> Bat $bn ChargeLR - weighted self-consumption: $wou %");
} }
## Auswertung für jede kommende Stunde ## Auswertung für jede kommende Stunde
@@ -11782,56 +11788,63 @@ 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)
my $surpls = sprintf "%.0f", ($pvfc - $confc); # PV-Überschuß der Stunde, wichtig keine Nachkommastellen! my $surpls = sprintf "%.0f", ($pvfc - $confc); # PV-Überschuß der Stunde, wichtig keine Nachkommastellen!
## Steuerung nach Ladefreigabe ## Steuerung nach Ladefreigabe
################################ ################################
if ( $whneed * (1 + ($margin / 100)) >= $spday ) {$crel = 1} # Ladefreigabe wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag if ( $whneed * (1 + ($lrMargin / 100)) >= $spday ) {$crel = 1} # Ladefreigabe wenn benötigte Ladeenergie >= Restüberschuß des Tages zzgl. Sicherheitsaufschlag
if ( !$num && ($pvCu - $curcon) >= $inplim ) {$crel = 1} # Ladefreigabe wenn akt. PV Leistung - Abschläge >= WR-Leistungsbegrenzung if ( !$num && ($pvCu - $curcon) >= $inplim ) {$crel = 1} # Ladefreigabe wenn akt. PV Leistung - Abschläge >= WR-Leistungsbegrenzung
if ( !$bpin && $gfeedin > $feedinlim ) {$crel = 1} # V 1.49.6 Ladefreigabe wenn akt. keine Bat-Ladung UND akt. Einspeisung > Einspeiselimit der Anlage if ( !$bpin && $gfeedin > $feedinlim ) {$crel = 1} # V 1.49.6 Ladefreigabe wenn akt. keine Bat-Ladung UND akt. Einspeisung > Einspeiselimit der Anlage
if ( $bpin && ($gfeedin - $bpin) > $feedinlim ) {$crel = 1} # V 1.49.6 Ladefreigabe wenn akt. Bat-Ladung UND Eispeisung - Bat-Ladung > Einspeiselimit der Anlage if ( $bpin && ($gfeedin - $bpin) > $feedinlim ) {$crel = 1} # V 1.49.6 Ladefreigabe wenn akt. Bat-Ladung UND Eispeisung - Bat-Ladung > Einspeiselimit der Anlage
if ( !$cgbt ) {$crel = 1} # Ladefreigabe wenn kein BatSoc-Management if ( !$cgbt ) {$crel = 1} # Ladefreigabe wenn kein BatSoc-Management
if ( !$lcintime ) {$crel = 1} # Ladefreigabe wenn nicht innerhalb Zeitslot für Ladesteuerung if ( !$lcintime ) {$crel = 1} # Ladefreigabe wenn nicht innerhalb Zeitslot für Ladesteuerung
if ( $labortCond ) {$crel = 0} # keine Ladefreigabe bei genereller Abbruchbedingung if ( $labortCond ) {$crel = 0} # keine Ladefreigabe bei genereller Abbruchbedingung
# Steuerhash für optimimierte Ladeleistung erstellen # Steuerhash für optimimierte Ladeleistung erstellen
###################################################### ######################################################
my $surplswh = max (0, $surpls); my $surplswh = max (0, $surpls);
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;
$hsurp->{$fd}{$hod}{$bn}{batinstcap} = $batinstcap; # installierte Batteriekapazität (Wh) $hsurp->{$fd}{$hod}{$bn}{batinstcap} = $batinstcap; # installierte Batteriekapazität (Wh)
$hsurp->{$fd}{$hod}{$bn}{bpinmax} = $bpinmax; # max. mögliche Ladeleistung $hsurp->{$fd}{$hod}{$bn}{bpinmax} = $bpinmax; # max. mögliche Ladeleistung
$hsurp->{$fd}{$hod}{$bn}{bpoutmax} = $bpoutmax; # max. mögliche Entladeleistung $hsurp->{$fd}{$hod}{$bn}{bpinreduced} = $bpinreduced; # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid
$hsurp->{$fd}{$hod}{$bn}{lowSocwh} = $lowSocwh; # eingestellter lowSoC in Wh $hsurp->{$fd}{$hod}{$bn}{bpoutmax} = $bpoutmax; # max. mögliche Entladeleistung
$hsurp->{$fd}{$hod}{$bn}{csocwh} = $csocwh; # aktueller SoC in Wh $hsurp->{$fd}{$hod}{$bn}{lowSocwh} = $lowSocwh; # eingestellter lowSoC in Wh
$hsurp->{$fd}{$hod}{$bn}{otpMargin} = $otpMargin; # Sicherheitszuschlag für Berechnungen $hsurp->{$fd}{$hod}{$bn}{batoptsocwh} = $batoptsocwh; # optimaler SoC in Wh
$hsurp->{$fd}{$hod}{$bn}{lcintime} = $lcintime; # Ladesteuerung "In Time" oder "nicht In Time" $hsurp->{$fd}{$hod}{$bn}{csocwh} = $csocwh; # aktueller SoC in Wh
$hsurp->{$fd}{$hod}{$bn}{stt} = $stt; # Day/Time für Debuglog $hsurp->{$fd}{$hod}{$bn}{otpMargin} = $otpMargin; # Sicherheitszuschlag für Berechnungen
$hsurp->{$fd}{$hod}{$bn}{strategy} = $strategy; # Ladestrategie $hsurp->{$fd}{$hod}{$bn}{lcintime} = $lcintime; # Ladesteuerung "In Time" oder "nicht In Time"
$hsurp->{$fd}{$hod}{$bn}{stt} = $stt; # Day/Time für Debuglog
$hsurp->{$fd}{$hod}{$bn}{strategy} = $strategy; # Ladestrategie
$hsurp->{$fd}{$hod}{$bn}{weightOwnUse} = $wou; # Gewichtung Prognose-Verbrauch als Anteil "Eigennutzung" (https://forum.fhem.de/index.php?msg=1348429)
} }
## 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
$speff = $speff > 0 ? ($speff >= $bpinmax ? $bpinmax : $speff) : $speff = $speff > 0 ? ($speff >= $bpinmax ? $bpinmax : $speff) :
$speff < 0 ? ($speff <= $bpoutmax * -1 ? $bpoutmax * -1 : $speff) : $speff < 0 ? ($speff <= -$bpoutmax ? -$bpoutmax : $speff) :
$speff; $speff;
my $delta = $speff > 0 ? ($crel ? $speff * STOREFFDEF : 0) : # PV Überschuß (d.h. Aufladung) nur einbeziehen wenn Ladefreigabe
$speff < 0 ? $speff / STOREFFDEF : # Verbrauch einbeziehen
0;
$socwh += $crel ? ($speff > 0 ? $speff * STOREFFDEF : $speff / STOREFFDEF) : $socwh += $delta;
($speff > 0 ? 0 : $speff / STOREFFDEF); # PV Überschuß (d.h. Aufladung) nur einbeziehen wenn Ladefreigabe
$socwh = $socwh < $lowSocwh ? $lowSocwh : $socwh = $socwh < $lowSocwh ? $lowSocwh : # SoC begrenzen
$socwh < $batoptsocwh ? $batoptsocwh : # SoC Prognose in Wh $socwh < $batoptsocwh ? $batoptsocwh :
$socwh > $batinstcap ? $batinstcap : $socwh > $batinstcap ? $batinstcap :
$socwh; $socwh;
$socwh = sprintf "%.0f", $socwh; $socwh = sprintf "%.0f", $socwh; # SoC Prognose in Wh
$progsoc = sprintf "%.1f", (100 * $socwh / $batinstcap); # Prognose SoC in % $progsoc = sprintf "%.1f", (100 * $socwh / $batinstcap); # Prognose SoC in %
## Debuglog LR ## Debuglog LR
@@ -11897,6 +11910,9 @@ sub _batChargeMgmt {
for my $bat (sort @batteries) { for my $bat (sort @batteries) {
my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-'; my $ssocwh = $hopt->{$shod}{$bat}{runwh} // '-';
## SOC-Prognose OTP
#####################
my $fcendwh = $hopt->{$shod}{$bat}{fcendwh} // 0; my $fcendwh = $hopt->{$shod}{$bat}{fcendwh} // 0;
$progsoc = sprintf "%.1f", (100 * $fcendwh / $hopt->{$shod}{$bat}{batinstcap}); # Prognose SoC in % $progsoc = sprintf "%.1f", (100 * $fcendwh / $hopt->{$shod}{$bat}{batinstcap}); # Prognose SoC in %
@@ -11911,6 +11927,7 @@ sub _batChargeMgmt {
hod => $shod, hod => $shod,
loopid => 'OTP', loopid => 'OTP',
strategy => $hopt->{$shod}{$bat}{strategy}, strategy => $hopt->{$shod}{$bat}{strategy},
crel => 1,
}; };
___batChargeSaveResults ($paref, $values); ___batChargeSaveResults ($paref, $values);
@@ -11924,11 +11941,12 @@ sub _batChargeMgmt {
my $ttt = $hopt->{$shod}{$bat}{stt}; my $ttt = $hopt->{$shod}{$bat}{stt};
if ($nhr eq '00') { if ($nhr eq '00') {
$pneedmin = $otp->{$bat}{target} // 0; $pneedmin = $otp->{$bat}{target} // 0;
my $achievable = $hopt->{$shod}{$bat}{achievable}; my $achievable = $hopt->{$shod}{$bat}{achievable};
my $otpMargin = $hopt->{$shod}{$bat}{otpMargin}; my $otpMargin = $hopt->{$shod}{$bat}{otpMargin};
my $margin = defined $otpMargin ? $otpMargin : SFTYMARGIN_20; my $weightOwnUse = $hopt->{$shod}{$bat}{weightOwnUse};
Log3 ($name, 1, "$name DEBUG> Bat $bat ChargeOTP - used safety margin: $margin %"); Log3 ($name, 1, "$name DEBUG> Bat $bat ChargeOTP - used safety margin: $otpMargin %");
Log3 ($name, 1, "$name DEBUG> Bat $bat ChargeOTP - weighted self-consumption: $weightOwnUse %");
Log3 ($name, 1, "$name DEBUG> Bat $bat ChargeOTP - is the charging goal likely to be achieved? - $achievable"); Log3 ($name, 1, "$name DEBUG> Bat $bat ChargeOTP - is the charging goal likely to be achieved? - $achievable");
} }
@@ -12006,7 +12024,7 @@ sub __batChargeOptTargetPower {
my $sbatinstcap = $hsurp->{$hod}{$sbn}{batinstcap}; # Kapa dieser Batterie my $sbatinstcap = $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 $csocwh = $hsurp->{$hod}{$sbn}{csocwh}; # aktueller SoC in Wh my $csocwh = $hsurp->{$hod}{$sbn}{csocwh}; # aktueller SoC in Wh
my $bpinreduced = BatteryVal ($name, $sbn, 'bpinreduced', 0); # Standardwert wenn z.B. kein Überschuß oder Zwangsladung vom Grid my $bpinreduced = $hsurp->{$hod}{$sbn}{bpinreduced}; # Standardwert bei <=lowSoC -> Anforderungsladung vom Grid
my $runwh = defined $hsurp->{$hod}{$sbn}{fcnextwh} ? # Auswahl des zu verwendenden Prognose-SOC (Wh) my $runwh = defined $hsurp->{$hod}{$sbn}{fcnextwh} ? # Auswahl des zu verwendenden Prognose-SOC (Wh)
$hsurp->{$hod}{$sbn}{fcnextwh} : $hsurp->{$hod}{$sbn}{fcnextwh} :
@@ -12016,12 +12034,14 @@ sub __batChargeOptTargetPower {
); );
$runwh = min ($runwh, $sbatinstcap); $runwh = min ($runwh, $sbatinstcap);
$hsurp->{$hod}{$sbn}{runwh} = sprintf "%.0f", $runwh; $hsurp->{$hod}{$sbn}{runwh} = sprintf "%.0f", $runwh; # Startwert für DebugLog
if (!$spls || !$hsurp->{$hod}{$sbn}{lcintime}) { # Ladesteuerung nicht "In Time" if (!$spls) { # Ladesteuerung nicht "In Time"
$hsurp->{$hod}{$sbn}{achievable} = 'undetermined'; $hsurp->{$hod}{$sbn}{achievable} = 'undetermined, calculation is starting with next hour with surplus';
$hsurp->{$hod}{$sbn}{pneedmin} = $bpinmax; $hsurp->{$hod}{$sbn}{pneedmin} = $bpinmax;
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", $runwh;
$runwh += $hsurp->{$hod}{speff} / STOREFFDEF; # um Verbrauch reduzieren
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", $runwh;
if ($nhr eq '00') { if ($nhr eq '00') {
$otp->{$sbn}{target} = $csocwh <= $lowSocwh ? $bpinreduced : $bpinmax; $otp->{$sbn}{target} = $csocwh <= $lowSocwh ? $bpinreduced : $bpinmax;
@@ -12031,21 +12051,26 @@ sub __batChargeOptTargetPower {
} }
my $otpMargin = $hsurp->{$hod}{$sbn}{otpMargin}; my $otpMargin = $hsurp->{$hod}{$sbn}{otpMargin};
my $margin = defined $otpMargin ? $otpMargin : SFTYMARGIN_20;
my $runwhneed = $sbatinstcap - $runwh; my $runwhneed = $sbatinstcap - $runwh;
my $fref = ___batFindMinPhWh ($hsurp, \@remaining_hods, $runwhneed); my $fref = ___batFindMinPhWh ($hsurp, \@remaining_hods, $runwhneed);
my $needraw = min ($fref->{ph}, $spls); # Ladeleistung auf Surplus begrenzen my $needraw = min ($fref->{ph}, $spls); # Ladeleistung auf Surplus begrenzen
$needraw *= 1 + ($margin / 100); # 1. Sicherheitsaufschlag $needraw *= 1 + ($otpMargin / 100); # 1. Sicherheitsaufschlag
$needraw = $bpinmax if(!$hsurp->{$hod}{$sbn}{lcintime});
$needraw = sprintf "%.0f", $needraw; $needraw = sprintf "%.0f", $needraw;
my $pneedmin = max ($needraw, $bpinreduced); # Mindestladeleistung bpinreduced sicherstellen $needraw = max ($needraw, $bpinreduced); # Mindestladeleistung bpinreduced sicherstellen
$needraw = min ($needraw, $bpinmax); # Begrenzung auf max. mögliche Batterieleistung
$hsurp->{$hod}{$sbn}{achievable} = 'goal: '.(sprintf "%.0f", $runwhneed).' Wh -> '.($fref->{achievable} ? 'yes' : 'no'); $hsurp->{$hod}{$sbn}{pneedmin} = $needraw;
$hsurp->{$hod}{$sbn}{pneedmin} = min ($pneedmin, $hsurp->{$hod}{$sbn}{bpinmax}); # Begrenzung auf max. mögliche Batterieleistung $hsurp->{$hod}{$sbn}{achievable} = 'goal: '.(sprintf "%.0f", $runwhneed).' Wh -> '.($fref->{achievable} ? 'yes' : 'no');
## NextHour 00 bearbeiten
###########################
if ($nhr eq '00') { if ($nhr eq '00') {
my $target = max ($bpinreduced, $hsurp->{$hod}{$sbn}{pneedmin}); my $target = max ($bpinreduced, $hsurp->{$hod}{$sbn}{pneedmin});
$target *= 1 + ($margin / 100); # 2. Sicherheitsaufschlag $target *= 1 + ($otpMargin / 100); # 2. Sicherheitsaufschlag
my $gfeedin = CurrentVal ($name, 'gridfeedin', 0); # aktuelle Netzeinspeisung my $gfeedin = CurrentVal ($name, 'gridfeedin', 0); # aktuelle Netzeinspeisung
my $bpin = CurrentVal ($name, 'batpowerinsum', 0); # aktuelle Batterie Ladeleistung (Summe über alle Batterien) my $bpin = CurrentVal ($name, 'batpowerinsum', 0); # aktuelle Batterie Ladeleistung (Summe über alle Batterien)
@@ -12059,6 +12084,8 @@ sub __batChargeOptTargetPower {
$otp->{$sbn}{target} = $target; $otp->{$sbn}{target} = $target;
} }
$hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", min ($sbatinstcap, $runwh + ($nhr eq '00' ? # Endwert Prognose aktuelle Stunde $hsurp->{$hod}{$sbn}{fcendwh} = sprintf "%.0f", min ($sbatinstcap, $runwh + ($nhr eq '00' ? # Endwert Prognose aktuelle Stunde
$otp->{$sbn}{target} : $otp->{$sbn}{target} :
$hsurp->{$hod}{$sbn}{pneedmin} $hsurp->{$hod}{$sbn}{pneedmin}
@@ -12071,6 +12098,17 @@ sub __batChargeOptTargetPower {
return ($hsurp, $otp); return ($hsurp, $otp);
} }
################################################################
# Weiterschreibung übergebenen SoC in Wh, Rückgabe
# weitergeschriebenen SoC in %
################################################################
sub ___batSocWhForecast {
my $paref = shift;
return;
}
############################################################################################### ###############################################################################################
# Errechnet minimal benötigte konstante Ladeleistung: $ph Wh via Binärsuche Iteration # Errechnet minimal benötigte konstante Ladeleistung: $ph Wh via Binärsuche Iteration
# #
@@ -12150,7 +12188,7 @@ sub ___batChargeSaveResults {
## in Schleife 'loadRelease' setzen ## in Schleife 'loadRelease' setzen
##################################### #####################################
if ($loopid eq 'LR') { # nur in Schleife 'loadRelease' setzen if ($loopid eq 'LR') {
$data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $crel; $data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $crel;
$data{$name}{nexthours}{'NextHour'.$nhr}{'lcintimebat'.$bn} = $lcintime if($cgbt); # nur einmal bei 'loadRelease' setzen -> Ladesteuerung "In Time", "nicht In Time" oder nicht verwendet $data{$name}{nexthours}{'NextHour'.$nhr}{'lcintimebat'.$bn} = $lcintime if($cgbt); # nur einmal bei 'loadRelease' setzen -> Ladesteuerung "In Time", "nicht In Time" oder nicht verwendet
$data{$name}{nexthours}{'NextHour'.$nhr}{'strategybat'.$bn} = $strategy; $data{$name}{nexthours}{'NextHour'.$nhr}{'strategybat'.$bn} = $strategy;
@@ -12169,7 +12207,9 @@ sub ___batChargeSaveResults {
## in Schleife 'optPower' setzen ## in Schleife 'optPower' setzen
################################## ##################################
if ($loopid eq 'OTP') { if ($loopid eq 'OTP') {
if ($nhr eq '00') { # Target für aktuelle Stunde $data{$name}{nexthours}{'NextHour'.$nhr}{'rcdchargebat'.$bn} = $crel; # immer Freigabe bei optPower (für Anzeige)
if ($nhr eq '00') { # Target für aktuelle Stunde
my $needmin = $otp->{$bn}{target} // 0; my $needmin = $otp->{$bn}{target} // 0;
storeReading ('Battery_ChargeOptTargetPower_'.$bn, $needmin.' W'); storeReading ('Battery_ChargeOptTargetPower_'.$bn, $needmin.' W');
} }
@@ -27041,7 +27081,7 @@ to ensure that the system configuration is correct.
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a> <a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
<li><b>ctrlBatSocManagementXX lowSoc=&lt;Value&gt; upSoC=&lt;Value&gt; [maxSoC=&lt;Value&gt;] [careCycle=&lt;Value&gt;] <li><b>ctrlBatSocManagementXX lowSoc=&lt;Value&gt; upSoC=&lt;Value&gt; [maxSoC=&lt;Value&gt;] [careCycle=&lt;Value&gt;]
[lcSlot=&lt;hh:mm&gt;-&lt;hh:mm&gt;] [loadAbort=&lt;SoC1&gt;:&lt;MinPwr&gt;:&lt;SoC2&gt;] [lcSlot=&lt;hh:mm&gt;-&lt;hh:mm&gt;] [loadAbort=&lt;SoC1&gt;:&lt;MinPwr&gt;:&lt;SoC2&gt;]
[safetyMargin=&lt;Value&gt;[:&lt;Value&gt;]] [loadStrategy=&lt;Value&gt;] </b> <br><br> [safetyMargin=&lt;Value&gt;[:&lt;Value&gt;]] [loadStrategy=&lt;Value&gt;] [weightOwnUse=&lt;Wert&gt;] </b> <br><br>
If a battery device (setupBatteryDevXX) is installed, this attribute activates the battery SoC and charge management If a battery device (setupBatteryDevXX) is installed, this attribute activates the battery SoC and charge management
for this battery device. <br> for this battery device. <br>
@@ -27086,6 +27126,11 @@ to ensure that the system configuration is correct.
<tr><td> </td><td>If the current SoC falls below the specified SoC2, the <b>Battery_ChargeAbort_XX=0</b> is set. </td></tr> <tr><td> </td><td>If the current SoC falls below the specified SoC2, the <b>Battery_ChargeAbort_XX=0</b> is set. </td></tr>
<tr><td> </td><td>If SoC2 is not specified, SoC2=SoC1. </td></tr> <tr><td> </td><td>If SoC2 is not specified, SoC2=SoC1. </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>loadStrategy</b> </td><td>The selected charging strategy is taken into account when displaying the battery in bar graph. </td></tr>
<tr><td> </td><td>The generation of tax readings is not affected. The specification is optional. </td></tr>
<tr><td> </td><td>For more information on selecting a strategy, see german <a href="https://wiki.fhem.de/wiki/SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Welche_Ladestrategie_soll_ich_w%C3%A4hlen?_-_eine_M%C3%B6glichkeit_zur_Best-Practice_Findung_mit_Codebeispiel">Wiki</a>. </td></tr>
<tr><td> </td><td>Value: <b>loadRelease or optPower</b>, default: loadRelease </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> <b>safetyMargin</b> </td><td>When calculating the load clearance and optimized load capacity, safety margins are taken </td></tr> <tr><td> <b>safetyMargin</b> </td><td>When calculating the load clearance and optimized load capacity, safety margins are taken </td></tr>
<tr><td> </td><td>into account in the predicted load requirements. </td></tr> <tr><td> </td><td>into account in the predicted load requirements. </td></tr>
<tr><td> </td><td>Deviating from the default, this parameter can be used to specify individual safety margins </td></tr> <tr><td> </td><td>Deviating from the default, this parameter can be used to specify individual safety margins </td></tr>
@@ -27094,11 +27139,11 @@ to ensure that the system configuration is correct.
<tr><td> </td><td>surcharge used to calculate the optimized load capacity. Both values are percentages. </td></tr> <tr><td> </td><td>surcharge used to calculate the optimized load capacity. Both values are percentages. </td></tr>
<tr><td> </td><td>Value: <b>0..100[:0..100]</b> (integers) </td></tr> <tr><td> </td><td>Value: <b>0..100[:0..100]</b> (integers) </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>loadStrategy</b> </td><td>The selected charging strategy is taken into account when displaying the battery in bar graph. </td></tr> <tr><td> <b>weightOwnUse</b> </td><td>Optional weighting of the hourly consumption forecast as an additional usable portion for </td></tr>
<tr><td> </td><td>The generation of tax readings is not affected. The specification is optional. </td></tr> <tr><td> </td><td>battery charging in %. Technically, the available PV surplus is increased to calculate the </td></tr>
<tr><td> </td><td>For more information on selecting a strategy, see german <a href="https://wiki.fhem.de/wiki/SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Welche_Ladestrategie_soll_ich_w%C3%A4hlen?_-_eine_M%C3%B6glichkeit_zur_Best-Practice_Findung_mit_Codebeispiel">Wiki</a>. </td></tr> <tr><td> </td><td>optimized charging power by reducing the calculated consumption by the specified percentage. </td></tr>
<tr><td> </td><td>Value: <b>loadRelease or optPower</b>, default: loadRelease </td></tr> <tr><td> </td><td>Value: <b>0..100</b> default: 0 </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
</table> </table>
</ul> </ul>
<br> <br>
@@ -27106,7 +27151,7 @@ to ensure that the system configuration is correct.
All SoC values are whole numbers in %. The following applies: 'lowSoc' &lt; 'upSoC' &lt; 'maxSoC'. <br><br> All SoC values are whole numbers in %. The following applies: 'lowSoc' &lt; 'upSoC' &lt; 'maxSoC'. <br><br>
<b>Example: </b> <br> <b>Example: </b> <br>
attr &lt;name&gt; ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=99 careCycle=25 lcSlot=11:00-17:30 loadAbort=99:40:90 safetyMargin=30 <br> attr &lt;name&gt; ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=99 careCycle=25 lcSlot=11:00-17:30 loadAbort=99:40:90 safetyMargin=30 weightOwnUse=20 <br>
</li> </li>
<br> <br>
@@ -29725,7 +29770,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a> <a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
<li><b>ctrlBatSocManagementXX lowSoc=&lt;Wert&gt; upSoC=&lt;Wert&gt; [maxSoC=&lt;Wert&gt;] [careCycle=&lt;Wert&gt;] <li><b>ctrlBatSocManagementXX lowSoc=&lt;Wert&gt; upSoC=&lt;Wert&gt; [maxSoC=&lt;Wert&gt;] [careCycle=&lt;Wert&gt;]
[lcSlot=&lt;hh:mm&gt;-&lt;hh:mm&gt;] [loadAbort=&lt;SoC1&gt;:&lt;MinPwr&gt;:&lt;SoC2&gt;] [lcSlot=&lt;hh:mm&gt;-&lt;hh:mm&gt;] [loadAbort=&lt;SoC1&gt;:&lt;MinPwr&gt;:&lt;SoC2&gt;]
[safetyMargin=&lt;Wert&gt;[:&lt;Wert&gt;]] [loadStrategy=&lt;Wert&gt;] </b> <br><br> [safetyMargin=&lt;Wert&gt;[:&lt;Wert&gt;]] [loadStrategy=&lt;Wert&gt;] [weightOwnUse=&lt;Wert&gt;] </b> <br><br>
Sofern ein Batterie Device (setupBatteryDevXX) installiert ist, aktiviert dieses Attribut das Batterie Sofern ein Batterie Device (setupBatteryDevXX) installiert ist, aktiviert dieses Attribut das Batterie
SoC- und Lade-Management für dieses Batteriegerät. <br> SoC- und Lade-Management für dieses Batteriegerät. <br>
@@ -29771,6 +29816,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td>Fällt der aktuelle SoC wieder unter den SoC2, wird <b>Battery_ChargeAbort_XX=0</b> gesetzt. </td></tr> <tr><td> </td><td>Fällt der aktuelle SoC wieder unter den SoC2, wird <b>Battery_ChargeAbort_XX=0</b> gesetzt. </td></tr>
<tr><td> </td><td>Ist SoC2 nicht angegeben, gilt SoC2=SoC1. </td></tr> <tr><td> </td><td>Ist SoC2 nicht angegeben, gilt SoC2=SoC1. </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>loadStrategy</b> </td><td>Bei der Anzeige der Batterie in der Balkengrafik wird die gewählte Ladestrategie berücksichtigt.</td></tr>
<tr><td> </td><td>Die Generierung der Steuerreadings wird nicht beeinflusst. Die Angabe ist optional. </td></tr>
<tr><td> </td><td>Weitere Informationen zur Auswahl der Strategie siehe <a href="https://wiki.fhem.de/wiki/SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Welche_Ladestrategie_soll_ich_w%C3%A4hlen?_-_eine_M%C3%B6glichkeit_zur_Best-Practice_Findung_mit_Codebeispiel">Wiki</a>. </td></tr>
<tr><td> </td><td>Wert: <b>loadRelease oder optPower</b>, default: loadRelease </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> <b>safetyMargin</b> </td><td>Bei der Berechnung der Ladefreigabe und optimierten Ladeleistung werden Sicherheitszuschläge </td></tr> <tr><td> <b>safetyMargin</b> </td><td>Bei der Berechnung der Ladefreigabe und optimierten Ladeleistung werden Sicherheitszuschläge </td></tr>
<tr><td> </td><td>auf den prognostizierten Ladungsbedarf berücksichtigt. </td></tr> <tr><td> </td><td>auf den prognostizierten Ladungsbedarf berücksichtigt. </td></tr>
<tr><td> </td><td>Abweichend vom Default können mit diesem Parameter individuelle Sicherheitszuschläge getrennt </td></tr> <tr><td> </td><td>Abweichend vom Default können mit diesem Parameter individuelle Sicherheitszuschläge getrennt </td></tr>
@@ -29779,11 +29829,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td>Zuschlag bei der Berechnung der optimierten Ladeleistung. Beide Angaben sind Prozentwerte. </td></tr> <tr><td> </td><td>Zuschlag bei der Berechnung der optimierten Ladeleistung. Beide Angaben sind Prozentwerte. </td></tr>
<tr><td> </td><td>Wert: <b>0..100[:0..100]</b> (Ganzzahlen) </td></tr> <tr><td> </td><td>Wert: <b>0..100[:0..100]</b> (Ganzzahlen) </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
<tr><td> <b>loadStrategy</b> </td><td>Bei der Anzeige der Batterie in der Balkengrafik wird die gewählte Ladestrategie berücksichtigt.</td></tr> <tr><td> <b>weightOwnUse</b> </td><td>Optionale Gewichtung der stündlichen Verbrauchsprognose als zusätzlich verwendbaren Anteil zur </td></tr>
<tr><td> </td><td>Die Generierung der Steuerreadings wird nicht beeinflusst. Die Angabe ist optional. </td></tr> <tr><td> </td><td>Batterieladung in %. Technisch wird der verfügbare PV-Überschuß zur Berechnung der optimierten </td></tr>
<tr><td> </td><td>Weitere Informationen zur Auswahl der Strategie siehe <a href="https://wiki.fhem.de/wiki/SolarForecast_-_Solare_Prognose_(PV_Erzeugung)_und_Verbrauchersteuerung#Welche_Ladestrategie_soll_ich_w%C3%A4hlen?_-_eine_M%C3%B6glichkeit_zur_Best-Practice_Findung_mit_Codebeispiel">Wiki</a>. </td></tr> <tr><td> </td><td>Ladeleistung erhöht indem der kalkulierte Verbrauch um den angegebenen Prozentsatz gesenkt wird.</td></tr>
<tr><td> </td><td>Wert: <b>loadRelease oder optPower</b>, default: loadRelease </td></tr> <tr><td> </td><td>Wert: <b>0..100</b> default: 0 </td></tr>
<tr><td> </td><td> </td></tr> <tr><td> </td><td> </td></tr>
</table> </table>
</ul> </ul>
<br> <br>
@@ -29791,7 +29841,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
Alle SoC-Werte sind ganze Zahlen in %. Dabei gilt: 'lowSoc' &lt; 'upSoC' &lt; 'maxSoC'. <br><br> Alle SoC-Werte sind ganze Zahlen in %. Dabei gilt: 'lowSoc' &lt; 'upSoC' &lt; 'maxSoC'. <br><br>
<b>Beispiel: </b> <br> <b>Beispiel: </b> <br>
attr &lt;name&gt; ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=99 careCycle=25 lcSlot=11:00-17:30 loadAbort=99:40:90 safetyMargin=30 <br> attr &lt;name&gt; ctrlBatSocManagement01 lowSoc=10 upSoC=50 maxSoC=99 careCycle=25 lcSlot=11:00-17:30 loadAbort=99:40:90 safetyMargin=30 weightOwnUse=20 <br>
</li> </li>
<br> <br>