76_SolarForecast: contrib version 1.59.4
git-svn-id: https://svn.fhem.de/fhem/trunk@30391 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -161,7 +161,7 @@ BEGIN {
|
|||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
"1.59.4" => "13.10.2025 new subs, ctrlBatSocManagementXX: new key loadTarget, replace __batCapShareFactor by __batDeficitShareFactor ".
|
"1.59.4" => "13.10.2025 new subs, ctrlBatSocManagementXX: new key loadTarget, replace __batCapShareFactor by __batDeficitShareFactor ".
|
||||||
"__batChargeOptTargetPower: use pinmax if achievable==0 ",
|
"__batChargeOptTargetPower: use pinmax if achievable==0, new ctrlBatSocManagementXX->stepSoC key ",
|
||||||
"1.59.3" => "10.10.2025 ___batChargeSaveResults: fix writing 'rcdchargebatXX' ",
|
"1.59.3" => "10.10.2025 ___batChargeSaveResults: fix writing 'rcdchargebatXX' ",
|
||||||
"1.59.2" => "09.10.2025 one more fix of color filling of svg icon ",
|
"1.59.2" => "09.10.2025 one more fix of color filling of svg icon ",
|
||||||
"1.59.1" => "08.10.2025 fixed transfer at day change, optimal SoC consideration in SoC forecast for optPower strategy ".
|
"1.59.1" => "08.10.2025 fixed transfer at day change, optimal SoC consideration in SoC forecast for optPower strategy ".
|
||||||
@@ -7532,6 +7532,7 @@ sub _attrBatSocManagement { ## no critic "not used"
|
|||||||
lowSoc => { comp => '(100|[1-9]?[0-9])', must => 1, act => 0 },
|
lowSoc => { comp => '(100|[1-9]?[0-9])', must => 1, act => 0 },
|
||||||
upSoC => { comp => '(100|[1-9]?[0-9])', must => 1, act => 0 },
|
upSoC => { comp => '(100|[1-9]?[0-9])', must => 1, act => 0 },
|
||||||
maxSoC => { comp => '(100|[1-9]?[0-9])', must => 0, act => 0 },
|
maxSoC => { comp => '(100|[1-9]?[0-9])', must => 0, act => 0 },
|
||||||
|
stepSoC => { comp => '[0-5]', must => 0, act => 0 },
|
||||||
careCycle => { comp => '\d+', must => 0, act => 0 },
|
careCycle => { comp => '\d+', must => 0, act => 0 },
|
||||||
lcSlot => { comp => '((?:[01]\d|2[0-3]):[0-5]\d-(?:[01]\d|2[0-3]):[0-5]\d)', must => 0, act => 1 },
|
lcSlot => { comp => '((?:[01]\d|2[0-3]):[0-5]\d-(?:[01]\d|2[0-3]):[0-5]\d)', must => 0, act => 1 },
|
||||||
careCycle => { comp => '\d+', must => 0, act => 0 },
|
careCycle => { comp => '\d+', must => 0, act => 0 },
|
||||||
@@ -11372,10 +11373,7 @@ sub _batSocTarget {
|
|||||||
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
my ($err, $badev, $h) = isDeviceValid ( { name => $name, obj => 'setupBatteryDev'.$bn, method => 'attr' } );
|
||||||
next if($err);
|
next if($err);
|
||||||
|
|
||||||
my $oldd2care = CircularVal ($name, 99, 'days2care'.$bn, 0);
|
my $batinstcap = BatteryVal ($name, $bn, 'binstcap', 0); # installierte Batteriekapazität Wh
|
||||||
my $ltsmsr = CircularVal ($name, 99, 'lastTsMaxSocRchd'.$bn, undef);
|
|
||||||
my $soc = BatteryVal ($name, $bn, 'bcharge', 0); # aktuelle Ladung in %
|
|
||||||
my $batinstcap = BatteryVal ($name, $bn, 'binstcap', 0); # installierte Batteriekapazität Wh
|
|
||||||
|
|
||||||
if (!$batinstcap) {
|
if (!$batinstcap) {
|
||||||
Log3 ($name, 1, "$name - WARNING - Attribute ctrlBatSocManagement${bn} is active, but required key 'cap' is not set. Go to Next...");
|
Log3 ($name, 1, "$name - WARNING - Attribute ctrlBatSocManagement${bn} is active, but required key 'cap' is not set. Go to Next...");
|
||||||
@@ -11386,17 +11384,37 @@ sub _batSocTarget {
|
|||||||
my $lowSoc = $parsed->{lowSoc};
|
my $lowSoc = $parsed->{lowSoc};
|
||||||
my $upSoc = $parsed->{upSoc};
|
my $upSoc = $parsed->{upSoc};
|
||||||
my $maxSoc = $parsed->{maxSoc};
|
my $maxSoc = $parsed->{maxSoc};
|
||||||
|
my $stepSoc = $parsed->{stepSoc};
|
||||||
my $careCycle = $parsed->{careCycle};
|
my $careCycle = $parsed->{careCycle};
|
||||||
|
|
||||||
if (!$lowSoc || !$upSoc) {
|
if (!$lowSoc || !$upSoc) {
|
||||||
Log3 ($name, 1, "$name - WARNING - Attribute ctrlBatSocManagement${bn} is active, but required keys 'lowSoc' and 'upSoC' are not set. Go to Next...");
|
Log3 ($name, 1, "$name - WARNING - Attribute ctrlBatSocManagement${bn} is active, but required keys 'lowSoc' and 'upSoC' are not set. Go to Next...");
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$stepSoc) {
|
||||||
|
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step1 - The SoC-Management is switched off. Battery_OptimumTargetSoC_$bn is set to lowSoC and Battery_ChargeRequest_$bn to '0'.");
|
||||||
|
|
||||||
|
## pvHistory/Readings schreiben
|
||||||
|
#################################
|
||||||
|
writeToHistory ( { paref => $paref, key => 'batsetsoc'.$bn, val => $lowSoc, hour => 99 } );
|
||||||
|
storeReading ('Battery_OptimumTargetSoC_'.$bn, $lowSoc.' %');
|
||||||
|
storeReading ('Battery_ChargeRequest_'.$bn, 0);
|
||||||
|
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $oldd2care = CircularVal ($name, 99, 'days2care'.$bn, 0);
|
||||||
|
my $ltsmsr = CircularVal ($name, 99, 'lastTsMaxSocRchd'.$bn, undef);
|
||||||
|
my $soc = BatteryVal ($name, $bn, 'bcharge', 0); # aktuelle Ladung in %
|
||||||
|
|
||||||
$paref->{batnmb} = $bn;
|
$paref->{batnmb} = $bn;
|
||||||
$paref->{careCycle} = $careCycle;
|
$paref->{careCycle} = $careCycle;
|
||||||
|
|
||||||
__batSaveSocKeyFigures ($paref) if(!$ltsmsr || $soc >= $maxSoc || $soc >= MAXSOCDEF || $oldd2care < 0);
|
__batSaveSocKeyFigures ($paref) if(!$ltsmsr || $soc >= $maxSoc || $soc >= MAXSOCDEF || $oldd2care < 0);
|
||||||
|
|
||||||
|
delete $paref->{batnmb};
|
||||||
|
delete $paref->{careCycle};
|
||||||
|
|
||||||
my $nt = '';
|
my $nt = '';
|
||||||
my $chargereq = 0; # Ladeanforderung wenn SoC unter Minimum SoC gefallen ist
|
my $chargereq = 0; # Ladeanforderung wenn SoC unter Minimum SoC gefallen ist
|
||||||
@@ -11406,8 +11424,8 @@ sub _batSocTarget {
|
|||||||
my $batymaxsoc = HistoryVal ($name, $yday, 99, 'batmaxsoc'.$bn, 0); # gespeicherter max. SOC des Vortages
|
my $batymaxsoc = HistoryVal ($name, $yday, 99, 'batmaxsoc'.$bn, 0); # gespeicherter max. SOC des Vortages
|
||||||
my $batysetsoc = HistoryVal ($name, $yday, 99, 'batsetsoc'.$bn, $lowSoc); # gespeicherter SOC Sollwert des Vortages
|
my $batysetsoc = HistoryVal ($name, $yday, 99, 'batsetsoc'.$bn, $lowSoc); # gespeicherter SOC Sollwert des Vortages
|
||||||
|
|
||||||
$target = $batymaxsoc < $maxSoc ? $batysetsoc + BATSOCCHGDAY :
|
$target = $batymaxsoc < $maxSoc ? $batysetsoc + $stepSoc :
|
||||||
$batymaxsoc >= $maxSoc ? $batysetsoc - BATSOCCHGDAY :
|
$batymaxsoc >= $maxSoc ? $batysetsoc - $stepSoc :
|
||||||
$batysetsoc; # neuer Min SOC für den laufenden Tag
|
$batysetsoc; # neuer Min SOC für den laufenden Tag
|
||||||
|
|
||||||
## erwartete PV ermitteln & Anteilsfaktor Bat anwenden
|
## erwartete PV ermitteln & Anteilsfaktor Bat anwenden
|
||||||
@@ -11422,14 +11440,14 @@ sub _batSocTarget {
|
|||||||
my $pvexpect = $sf * $pvexpraw;
|
my $pvexpect = $sf * $pvexpraw;
|
||||||
|
|
||||||
if ($debug =~ /batteryManagement/xs) {
|
if ($debug =~ /batteryManagement/xs) {
|
||||||
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Battery share factor of total capacity: $sf");
|
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Battery share factor of total required load: $sf");
|
||||||
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Expected energy for charging raw: $pvexpraw Wh");
|
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Expected energy for charging raw: $pvexpraw Wh");
|
||||||
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Expected energy for charging after application Share factor: $pvexpect Wh");
|
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - basics -> Expected energy for charging after application Share factor: $pvexpect Wh");
|
||||||
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - compare with SoC history -> preliminary new Target: $target %");
|
Log3 ($name, 1, "$name DEBUG> Bat $bn SoC Step1 - compare with SoC history -> preliminary new Target: $target %");
|
||||||
}
|
}
|
||||||
|
|
||||||
## Pflege-SoC (Soll SoC MAXSOCDEF bei BATSOCCHGDAY % Steigerung p. Tag)
|
## Pflege-SoC (Soll SoC MAXSOCDEF bei $stepSoc % Steigerung p. Tag)
|
||||||
###########################################################################
|
#####################################################################
|
||||||
my $sunset = CurrentVal ($name, 'sunsetTodayTs', $t);
|
my $sunset = CurrentVal ($name, 'sunsetTodayTs', $t);
|
||||||
my $delayts = $sunset - 5400; # Pflege-SoC/Erhöhung SoC erst ab 1,5h vor Sonnenuntergang berechnen/anwenden
|
my $delayts = $sunset - 5400; # Pflege-SoC/Erhöhung SoC erst ab 1,5h vor Sonnenuntergang berechnen/anwenden
|
||||||
my $la = '';
|
my $la = '';
|
||||||
@@ -11444,11 +11462,15 @@ sub _batSocTarget {
|
|||||||
$whneed = sprintf "%.0f", $whneed;
|
$whneed = sprintf "%.0f", $whneed;
|
||||||
|
|
||||||
if ($t > $delayts || $pvexpect < $whneed || !$days2care) {
|
if ($t > $delayts || $pvexpect < $whneed || !$days2care) {
|
||||||
|
$paref->{batnmb} = $bn;
|
||||||
$paref->{days2care} = $days2care;
|
$paref->{days2care} = $days2care;
|
||||||
|
|
||||||
__batSaveSocKeyFigures ($paref);
|
__batSaveSocKeyFigures ($paref);
|
||||||
|
|
||||||
delete $paref->{days2care};
|
delete $paref->{days2care};
|
||||||
|
delete $paref->{batnmb};
|
||||||
|
|
||||||
$careSoc = $maxSoc - ($days2care * BATSOCCHGDAY); # Pflege-SoC um rechtzeitig den $maxsoc zu erreichen bei BATSOCCHGDAY % Steigerung pro Tag
|
$careSoc = $maxSoc - ($days2care * $stepSoc); # Pflege-SoC um rechtzeitig den $maxsoc zu erreichen bei $stepSoc % Steigerung pro Tag
|
||||||
$careSoc = $careSoc < $lowSoc ? $lowSoc : $careSoc;
|
$careSoc = $careSoc < $lowSoc ? $lowSoc : $careSoc;
|
||||||
|
|
||||||
if ($careSoc >= $target) {
|
if ($careSoc >= $target) {
|
||||||
@@ -11513,14 +11535,14 @@ sub _batSocTarget {
|
|||||||
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step4 - basics -> docare: $docare, lowSoc: $lowSoc %, upSoc: $upSoc %");
|
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step4 - basics -> docare: $docare, lowSoc: $lowSoc %, upSoc: $upSoc %");
|
||||||
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step4 - observe low/up limits -> Target: $target %");
|
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step4 - observe low/up limits -> Target: $target %");
|
||||||
|
|
||||||
## auf BATSOCCHGDAY Schritte anpassen (40,45,50,...)
|
## auf $stepSoc Schritte anpassen (40,45,50,...)
|
||||||
######################################################
|
##################################################
|
||||||
my $flo = floor ($target / BATSOCCHGDAY);
|
my $flo = floor ($target / $stepSoc);
|
||||||
my $rmn = $target - ($flo * BATSOCCHGDAY);
|
my $rmn = $target - ($flo * $stepSoc);
|
||||||
my $add = $rmn <= 2.5 ? 0 : BATSOCCHGDAY;
|
my $add = $rmn <= 2.5 ? 0 : $stepSoc;
|
||||||
$target = ($flo * BATSOCCHGDAY) + $add;
|
$target = ($flo * $stepSoc) + $add;
|
||||||
|
|
||||||
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step5 - rounding the SoC to steps of ".BATSOCCHGDAY." % -> Target: $target %");
|
debugLog ($paref, 'batteryManagement', "Bat $bn SoC Step5 - rounding the SoC to steps of ".$stepSoc." % -> Target: $target %");
|
||||||
|
|
||||||
## Ladeanforderung
|
## Ladeanforderung
|
||||||
####################
|
####################
|
||||||
@@ -11536,9 +11558,6 @@ sub _batSocTarget {
|
|||||||
writeToHistory ( { paref => $paref, key => 'batsetsoc'.$bn, val => $target, hour => 99 } );
|
writeToHistory ( { paref => $paref, key => 'batsetsoc'.$bn, val => $target, hour => 99 } );
|
||||||
storeReading ('Battery_OptimumTargetSoC_'.$bn, $target.' %');
|
storeReading ('Battery_OptimumTargetSoC_'.$bn, $target.' %');
|
||||||
storeReading ('Battery_ChargeRequest_'.$bn, $chargereq);
|
storeReading ('Battery_ChargeRequest_'.$bn, $chargereq);
|
||||||
|
|
||||||
delete $paref->{batnmb};
|
|
||||||
delete $paref->{careCycle};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -11559,6 +11578,7 @@ sub __parseAttrBatSoc {
|
|||||||
lowSoc => $ph->{lowSoc},
|
lowSoc => $ph->{lowSoc},
|
||||||
upSoc => $ph->{upSoC},
|
upSoc => $ph->{upSoC},
|
||||||
maxSoc => $ph->{maxSoC} // MAXSOCDEF, # optional (default: MAXSOCDEF)
|
maxSoc => $ph->{maxSoC} // MAXSOCDEF, # optional (default: MAXSOCDEF)
|
||||||
|
stepSoc => $ph->{stepSoC} // BATSOCCHGDAY, # mögliche SoC-Änderung pro Tag
|
||||||
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},
|
||||||
@@ -27212,7 +27232,7 @@ to ensure that the system configuration is correct.
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
|
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
|
||||||
<li><b>ctrlBatSocManagementXX lowSoc=<Value> upSoC=<Value> [maxSoC=<Value>] [careCycle=<Value>]
|
<li><b>ctrlBatSocManagementXX lowSoc=<Value> upSoC=<Value> [maxSoC=<Value>] [stepSoC=<Value>] [careCycle=<Value>]
|
||||||
[lcSlot=<hh:mm>-<hh:mm>] [loadAbort=<SoC1>:<MinPwr>:<SoC2>]
|
[lcSlot=<hh:mm>-<hh:mm>] [loadAbort=<SoC1>:<MinPwr>:<SoC2>]
|
||||||
[safetyMargin=<Value>[:<Value>]] [loadStrategy=<Value>] [loadTarget=<Wert>]
|
[safetyMargin=<Value>[:<Value>]] [loadStrategy=<Value>] [loadTarget=<Wert>]
|
||||||
[weightOwnUse=<Wert>] </b> <br><br>
|
[weightOwnUse=<Wert>] </b> <br><br>
|
||||||
@@ -27246,6 +27266,11 @@ to ensure that the system configuration is correct.
|
|||||||
<tr><td> </td><td>in order to balance the charge in the storage network. </td></tr>
|
<tr><td> </td><td>in order to balance the charge in the storage network. </td></tr>
|
||||||
<tr><td> </td><td>The specification is optional (<= 100, default: 95) </td></tr>
|
<tr><td> </td><td>The specification is optional (<= 100, default: 95) </td></tr>
|
||||||
<tr><td> </td><td> </td></tr>
|
<tr><td> </td><td> </td></tr>
|
||||||
|
<tr><td> <b>stepSoC</b> </td><td>Optional step size for optimal SoC calculation (Battery_OptimumTargetSoC_XX) in %. </td></tr>
|
||||||
|
<tr><td> </td><td>The specification 'stepSoC=0' deactivates the SoC management and sets </td></tr>
|
||||||
|
<tr><td> </td><td>Battery_OptimumTargetSoC_XX to the value 'lowSoC'. </td></tr>
|
||||||
|
<tr><td> </td><td>Wert: <b>0..5</b>, default: 5 </td></tr>
|
||||||
|
<tr><td> </td><td> </td></tr>
|
||||||
<tr><td> <b>careCycle</b> </td><td>Maximum interval in days between two charge states of at least 'maxSoC' that should not be </td></tr>
|
<tr><td> <b>careCycle</b> </td><td>Maximum interval in days between two charge states of at least 'maxSoC' that should not be </td></tr>
|
||||||
<tr><td> </td><td>exceeded if possible. The specification is optional (default: 20) </td></tr>
|
<tr><td> </td><td>exceeded if possible. The specification is optional (default: 20) </td></tr>
|
||||||
<tr><td> </td><td> </td></tr>
|
<tr><td> </td><td> </td></tr>
|
||||||
@@ -29915,7 +29940,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
|
<a id="SolarForecast-attr-ctrlBatSocManagementXX" data-pattern="ctrlBatSocManagement.*"></a>
|
||||||
<li><b>ctrlBatSocManagementXX lowSoc=<Wert> upSoC=<Wert> [maxSoC=<Wert>] [careCycle=<Wert>]
|
<li><b>ctrlBatSocManagementXX lowSoc=<Wert> upSoC=<Wert> [maxSoC=<Wert>] [stepSoC=<Wert>] [careCycle=<Wert>]
|
||||||
[lcSlot=<hh:mm>-<hh:mm>] [loadAbort=<SoC1>:<MinPwr>:<SoC2>]
|
[lcSlot=<hh:mm>-<hh:mm>] [loadAbort=<SoC1>:<MinPwr>:<SoC2>]
|
||||||
[safetyMargin=<Wert>[:<Wert>]] [loadStrategy=<Wert>] [loadTarget=<Wert>]
|
[safetyMargin=<Wert>[:<Wert>]] [loadStrategy=<Wert>] [loadTarget=<Wert>]
|
||||||
[weightOwnUse=<Wert>] </b> <br><br>
|
[weightOwnUse=<Wert>] </b> <br><br>
|
||||||
@@ -29950,6 +29975,11 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<tr><td> </td><td>werden muß um den Ladungsausgleich im Speicherverbund auszuführen. </td></tr>
|
<tr><td> </td><td>werden muß um den Ladungsausgleich im Speicherverbund auszuführen. </td></tr>
|
||||||
<tr><td> </td><td>Die Angabe ist optional (<= 100, default: 95) </td></tr>
|
<tr><td> </td><td>Die Angabe ist optional (<= 100, default: 95) </td></tr>
|
||||||
<tr><td> </td><td> </td></tr>
|
<tr><td> </td><td> </td></tr>
|
||||||
|
<tr><td> <b>stepSoC</b> </td><td>Optionale Schrittweite zur optimalen SoC-Berechnung (Battery_OptimumTargetSoC_XX) in %. </td></tr>
|
||||||
|
<tr><td> </td><td>Mit der Angabe 'stepSoC=0' wird das SoC-Management deaktiviert und Battery_OptimumTargetSoC_XX </td></tr>
|
||||||
|
<tr><td> </td><td>auf den Wert 'lowSoC' gesetzt. </td></tr>
|
||||||
|
<tr><td> </td><td>Wert: <b>0..5</b>, default: 5 </td></tr>
|
||||||
|
<tr><td> </td><td> </td></tr>
|
||||||
<tr><td> <b>careCycle</b> </td><td>maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' </td></tr>
|
<tr><td> <b>careCycle</b> </td><td>maximaler Abstand in Tagen, der zwischen zwei Ladungszuständen von mindestens 'maxSoC' </td></tr>
|
||||||
<tr><td> </td><td>möglichst nicht überschritten werden soll. Die Angabe ist optional (default: 20) </td></tr>
|
<tr><td> </td><td>möglichst nicht überschritten werden soll. Die Angabe ist optional (default: 20) </td></tr>
|
||||||
<tr><td> </td><td> </td></tr>
|
<tr><td> </td><td> </td></tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user