76_SolarForecast: contrib version 1.59.6

git-svn-id: https://svn.fhem.de/fhem/trunk@30458 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
DS_Starter
2025-10-29 16:14:22 +00:00
parent 3ff97776ab
commit 9996636219

View File

@@ -160,12 +160,13 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.59.6" => "26.10.2025 ___ownSpecGetFWwidget: handling of line breaks in attributes & can hamdle a key=value pair separateley ". "1.59.6" => "28.10.2025 ___ownSpecGetFWwidget: handling of line breaks in attributes & can hamdle a key=value pair separateley ".
"Width of a text field in graphicHeaderOwnspec fixed to 10, edit commandref ". "Width of a text field in graphicHeaderOwnspec fixed to 10, edit commandref ".
"__batChargeOptTargetPower: use an average for the charging power if smartPower set and charging target are not achievable ". "__batChargeOptTargetPower: use an average for the charging power if smartPower set and charging target are not achievable ".
"__createOwnSpec: an empty field can be created within a line by simply using a colon (:). ". "__createOwnSpec: an empty field can be created within a line by simply using a colon (:). ".
"add new key pvshare to CustomerXX attributes -> __setConsRcmdState add PV share calculation ". "add new key pvshare to CustomerXX attributes -> __setConsRcmdState add PV share calculation ".
"___doPlanning: code improvements and implement PV share needed ", "___doPlanning: code improvements and implement PV share needed ".
" Task 2: chamge timestamp of day before to 24:00:00, _restorePlantConfig: fix problem with attr sequence ",
"1.59.5" => "15.10.2025 new sub ___batAdjustPowerByMargin: implement optPower Safety margin decreasing proportionally to the linear surplus ". "1.59.5" => "15.10.2025 new sub ___batAdjustPowerByMargin: implement optPower Safety margin decreasing proportionally to the linear surplus ".
"new Reading Battery_TargetAchievable_XX, _batSocTarget: minor code change ", "new Reading Battery_TargetAchievable_XX, _batSocTarget: minor code change ",
"1.59.4" => "14.10.2025 new subs, ctrlBatSocManagementXX: new key loadTarget, replace __batCapShareFactor by __batDeficitShareFactor ". "1.59.4" => "14.10.2025 new subs, ctrlBatSocManagementXX: new key loadTarget, replace __batCapShareFactor by __batDeficitShareFactor ".
@@ -626,14 +627,26 @@ my @aconfigs = qw( aiControl
ctrlSpecialReadings ctrlSpecialReadings
ctrlUserExitFn ctrlUserExitFn
disable disable
graphicHeaderOwnspec graphicHeaderOwnspecValForm graphicHeaderOwnspec
graphicHeaderOwnspecValForm
graphicHistoryHour graphicHistoryHour
graphicSelect graphicShowNight graphicShowWeather graphicSelect
graphicWeatherColor graphicWeatherColorNight graphicShowNight
setupMeterDev setupInverterStrings setupRadiationAPI setupStringPeak setupStringAzimuth setupStringDeclination graphicShowWeather
setupWeatherDev1 setupWeatherDev2 setupWeatherDev3 graphicWeatherColor
graphicWeatherColorNight
setupMeterDev
setupInverterStrings
setupRadiationAPI
setupStringPeak
setupStringAzimuth
setupStringDeclination
setupRoofTops setupRoofTops
); );
for my $wd (1..3) {
push @aconfigs, "setupWeatherDev${wd}"; # add Wetter Dev Attribute
}
for my $cn (1..MAXCONSUMER) { for my $cn (1..MAXCONSUMER) {
$cn = sprintf "%02d", $cn; $cn = sprintf "%02d", $cn;
@@ -8467,7 +8480,7 @@ sub readCacheFile {
my ($nr, $na); my ($nr, $na);
if ($plantcfg) { if ($plantcfg) {
($nr, $na) = _restorePlantConfig ($hash, $plantcfg); ($nr, $na) = _restorePlantConfig ($name, $plantcfg);
Log3 ($name, 3, qq{$name - cached data "$title" restored. Number of restored Readings/Attributes: $nr/$na}); Log3 ($name, 3, qq{$name - cached data "$title" restored. Number of restored Readings/Attributes: $nr/$na});
} }
@@ -8689,20 +8702,20 @@ return ($plantcfg, $nr, $na);
# Anlagenkonfiguration aus fileRetrieve wiederherstellen # Anlagenkonfiguration aus fileRetrieve wiederherstellen
################################################################ ################################################################
sub _restorePlantConfig { sub _restorePlantConfig {
my $hash = shift; my $name = shift;
my $plantcfg = shift; my $plantcfg = shift;
my $name = $hash->{NAME};
my ($nr, $na) = (0,0); my ($nr, $na) = (0,0);
while (my ($key, $val) = each %{$plantcfg}) { while (my ($key, $val) = each %{$plantcfg}) {
if (grep /^$key$/, @rconfigs) { # Reading wiederherstellen if (grep /^$key$/, @rconfigs) { # Readings wiederherstellen
CommandSetReading (undef,"$name $key $val"); CommandSetReading (undef,"$name $key $val");
$nr++; $nr++;
} }
if (grep /^$key$/, @aconfigs) { # Attribut wiederherstellen if (grep /^$key$/, @aconfigs) { # Attribute wiederherstellen
CommandAttr (undef, "$name $key $val"); # CommandAttr (undef, "$name $key $val");
$attr{$name}{$key} = $val;
$na++; $na++;
} }
} }
@@ -12071,11 +12084,13 @@ sub _batChargeMgmt {
if ($nhr eq '00') { if ($nhr eq '00') {
$pneedmin = $otp->{$bat}{target} // 0; $pneedmin = $otp->{$bat}{target} // 0;
my $ratio = $otp->{$bat}{ratio} // '<unknown>';
my $achievelog = $hopt->{$shod}{$bat}{achievelog}; my $achievelog = $hopt->{$shod}{$bat}{achievelog};
my $otpMargin = $hopt->{$shod}{$bat}{otpMargin}; my $otpMargin = $hopt->{$shod}{$bat}{otpMargin};
Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat - used safety margin: $otpMargin %"); Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat - used safety margin: $otpMargin %");
Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat - $achievelog"); Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat - $achievelog");
Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat - current Ratio of surplus / energy requirement to achieve the load target: $ratio %") if($strategy eq 'smartPower');
} }
Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat $ttt - hod:$shod/$nhr, lr/lc:$crel/$lcintime, SocS/E:$ssocwh/$fcendwh Wh, SurpH/D:$spls/$spday Wh, OTP:$pneedmin/$frefph W"); Log3 ($name, 1, "$name DEBUG> ChargeOTP Bat $bat $ttt - hod:$shod/$nhr, lr/lc:$crel/$lcintime, SocS/E:$ssocwh/$fcendwh Wh, SurpH/D:$spls/$spday Wh, OTP:$pneedmin/$frefph W");
@@ -12141,7 +12156,6 @@ sub __batChargeOptTargetPower {
## Surplus der Stunde 00 mit Zeitgewichtung in $replacement speichern ## Surplus der Stunde 00 mit Zeitgewichtung in $replacement speichern
####################################################################### #######################################################################
#my $spls00 = 0;
my $replacement; my $replacement;
for my $k (keys %$hsurp) { for my $k (keys %$hsurp) {
@@ -12151,10 +12165,8 @@ sub __batChargeOptTargetPower {
my $val = $hsurp->{$k}{surplswh}; my $val = $hsurp->{$k}{surplswh};
if (defined $val && $val =~ /^(\d+)\.(\w+)$/) { if (defined $val && $val =~ /^(\d+)\.(\w+)$/) {
#my $spls00 = $1;
$replacement = sprintf "%.0f", ($1 / 60 * (60 - int $minute)); # aktuelle (Rest)-Stunde -> zeitgewichteter PV-Überschuß $replacement = sprintf "%.0f", ($1 / 60 * (60 - int $minute)); # aktuelle (Rest)-Stunde -> zeitgewichteter PV-Überschuß
$replacement .= '.'.$2; $replacement .= '.'.$2;
#$hsurp->{$k}{surplswh} = $replacement;
} }
last; # da Stunde 00 nur einmal vorkommt, können wir abbrechen last; # da Stunde 00 nur einmal vorkommt, können wir abbrechen
@@ -12165,24 +12177,20 @@ sub __batChargeOptTargetPower {
my @batteries = grep { !/^(?:fd|speff|surplswh|nhr)$/xs } keys %{$hsurp->{24}}; my @batteries = grep { !/^(?:fd|speff|surplswh|nhr)$/xs } keys %{$hsurp->{24}};
my @sortedhods = sort { $hsurp->{$a}{surplswh} <=> $hsurp->{$b}{surplswh} } keys %{$hsurp}; # Stunden aufsteigend nach PV-Überschuß sortiert ohne Zeitgewichtung h 00 my @sortedhods = sort { $hsurp->{$a}{surplswh} <=> $hsurp->{$b}{surplswh} } keys %{$hsurp}; # Stunden aufsteigend nach PV-Überschuß sortiert ohne Zeitgewichtung h 00
my ($fcendwh, $diff); my ($fcendwh, $diff, $otp, $ratio);
my $otp;
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};
next if(!defined $nhr); next if(!defined $nhr);
my $spls = int ($hsurp->{$hod}{surplswh} // 0); my $spls = int ($hsurp->{$hod}{surplswh} // 0);
# $spls = $spls00 if($nhr eq '00'); # aktuelle Stunde: zeitgewichteter PV-Überschuß mit Original ersetzen
my $nexthod = sprintf "%02d", (int $hod + 1); my $nexthod = sprintf "%02d", (int $hod + 1);
my $nextnhr = $hsurp->{$nexthod}{nhr}; my $nextnhr = $hsurp->{$nexthod}{nhr};
my @remaining_hods = grep { int $_ >= int $hod } @sortedhods; my @remaining_hods = grep { int $_ >= int $hod } @sortedhods;
my $total = 0; my $total = 0;
# $total += $hsurp->{$_}{surplswh} for @remaining_hods; # Gesamtwert aller Stunden mit PV-Überschuß ermitteln
for my $h (@remaining_hods) { # Gesamtwert aller Stunden mit PV-Überschuß ermitteln for my $h (@remaining_hods) { # Gesamtwert PV-Überschuß aller Stunden mit PV-Überschuß ermitteln
my $val = $hsurp->{$h}{nhr} eq '00' my $val = $hsurp->{$h}{nhr} eq '00'
? $replacement // 0 ? $replacement // 0
: $hsurp->{$h}{surplswh}; : $hsurp->{$h}{surplswh};
@@ -12240,6 +12248,7 @@ sub __batChargeOptTargetPower {
if ($nhr eq '00') { if ($nhr eq '00') {
$diff = $diff / 60 * (60 - int $minute); # aktuelle (Rest)-Stunde -> zeitgewichteter Ladungsabfluß $diff = $diff / 60 * (60 - int $minute); # aktuelle (Rest)-Stunde -> zeitgewichteter Ladungsabfluß
$otp->{$sbn}{target} = $csocwh <= $lowSocwh ? $bpinreduced : $bpinmax; $otp->{$sbn}{target} = $csocwh <= $lowSocwh ? $bpinreduced : $bpinmax;
$otp->{$sbn}{ratio} = 0;
} }
$runwh += $diff / $befficiency; # um Verbrauch reduzieren $runwh += $diff / $befficiency; # um Verbrauch reduzieren
@@ -12259,8 +12268,6 @@ sub __batChargeOptTargetPower {
? min ($fref->{ph}, $spls) # Ladeleistung auf den kleineren Wert begrenzen (es kommen Nachberechnungen) ? min ($fref->{ph}, $spls) # Ladeleistung auf den kleineren Wert begrenzen (es kommen Nachberechnungen)
: $fref->{ph}; : $fref->{ph};
#Log3 ($name, 1, "$name - ph: $fref->{ph}") if($name eq "SolCast");
$limpower = $bpinmax if(!$hsurp->{$hod}{$sbn}{lcintime}); $limpower = $bpinmax if(!$hsurp->{$hod}{$sbn}{lcintime});
$limpower = max ($limpower, $bpinreduced); # Mindestladeleistung bpinreduced sicherstellen $limpower = max ($limpower, $bpinreduced); # Mindestladeleistung bpinreduced sicherstellen
@@ -12271,13 +12278,13 @@ sub __batChargeOptTargetPower {
my $pneedmin = $limpower * (1 + $otpMargin / 100); # optPower: Sicherheitsaufschlag my $pneedmin = $limpower * (1 + $otpMargin / 100); # optPower: Sicherheitsaufschlag
if ($strategy eq 'smartPower') { if ($strategy eq 'smartPower') {
$pneedmin = ___batAdjustPowerByMargin ($name, # smartPower: Sicherheitsaufschlag abfallend proportional zum linearen Überschuss ($pneedmin) = ___batAdjustPowerByMargin ($name, # smartPower: Sicherheitsaufschlag abfallend proportional zum linearen Überschuss
$limpower, $limpower,
$bpinmax, $bpinmax,
$runwhneed, $runwhneed,
$otpMargin, $otpMargin,
$hsurp->{$hod}{$sbn}{spday} $total
); );
} }
$pneedmin = sprintf "%.0f", $pneedmin; $pneedmin = sprintf "%.0f", $pneedmin;
@@ -12292,35 +12299,21 @@ sub __batChargeOptTargetPower {
if ($achievable) { # Tagesziel erreichbar: Basisziel um otpMargin% erhöhen if ($achievable) { # Tagesziel erreichbar: Basisziel um otpMargin% erhöhen
$target *= 1 + ($otpMargin / 100); # optPower: Sicherheitsaufschlag $target *= 1 + ($otpMargin / 100); # optPower: Sicherheitsaufschlag
#if ($strategy eq 'smartPower') { # smartPower: Sicherheitsaufschlag linear absenkend
# $target = ___batAdjustPowerByMargin ($name, # Sicherheitsaufschlag abfallend proportional zum linearen Überschuss
# $limpower,
# $bpinmax,
# $runwhneed,
# $otpMargin,
# $hsurp->{$hod}{$sbn}{spday}
# );
#}
} }
else { # Tagesziel nicht erreichbar: Aufschlag potenziert (zweifach wirksam) else { # Tagesziel nicht erreichbar: Aufschlag potenziert (zweifach wirksam)
$target *= (1 + $otpMargin / 100) ** 2; # optPower: Sicherheitsaufschlag $target *= (1 + $otpMargin / 100) ** 2; # optPower: Sicherheitsaufschlag
#if ($strategy eq 'smartPower') { # smartPower: agressivere Ladeleistung
# $hs2sunset -= 1;
# $target = $runwhneed > 0 && $hs2sunset > 0 ? $runwhneed / $hs2sunset : $target;
# $target *= 1 + ($otpMargin / 100);
#}
} }
if ($strategy eq 'smartPower') { # smartPower: Sicherheitsaufschlag linear absenkend if ($strategy eq 'smartPower') { # smartPower: Sicherheitsaufschlag linear absenkend
$target = ___batAdjustPowerByMargin ($name, # Sicherheitsaufschlag abfallend proportional zum linearen Überschuss ($target, $ratio) = ___batAdjustPowerByMargin ($name, # smartPower: agressivere Ladeleistung, Sicherheitsaufschlag abfallend proportional zum linearen Überschuss
$limpower, $limpower,
$bpinmax, $bpinmax,
$runwhneed, $runwhneed,
$otpMargin, $otpMargin,
$hsurp->{$hod}{$sbn}{spday} $total
); );
$otp->{$sbn}{ratio} = $ratio;
} }
my $gfeedin = CurrentVal ($name, 'gridfeedin', 0); # aktuelle Netzeinspeisung my $gfeedin = CurrentVal ($name, 'gridfeedin', 0); # aktuelle Netzeinspeisung
@@ -12362,17 +12355,17 @@ return ($hsurp, $otp);
# Forum: https://forum.fhem.de/index.php?msg=1349579 # Forum: https://forum.fhem.de/index.php?msg=1349579
################################################################ ################################################################
sub ___batAdjustPowerByMargin { sub ___batAdjustPowerByMargin {
my ($name, $limpower, $pinmax, $whneed, $otpMargin, $spday) = @_; my ($name, $limpower, $pinmax, $whneed, $otpMargin, $total) = @_;
my $ratio = 0; my $ratio = 0;
$ratio = $spday * 100 / $whneed if($whneed); $ratio = $total * 100 / $whneed if($whneed);
return $pinmax if($limpower == $pinmax || $ratio <= 100); return ($pinmax, $ratio) if($limpower == $pinmax || $ratio <= 100);
return $limpower * (1 + $otpMargin / 100) if($limpower == 0 || !$otpMargin || $ratio >= 100 + $otpMargin); return ($limpower * (1 + $otpMargin / 100), $ratio) if($limpower == 0 || !$otpMargin || $ratio >= 100 + $otpMargin);
my $pow = $pinmax - ($pinmax - $limpower) * ($ratio - 100) / $otpMargin; my $pow = $pinmax - ($pinmax - $limpower) * ($ratio - 100) / $otpMargin;
return $pow; return ($pow, $ratio);
} }
################################################################ ################################################################