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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|||||||
Reference in New Issue
Block a user