feat(batterie): stufenlose Leistungsbereiche unterstützen
Tests / test (push) Successful in 49s

This commit is contained in:
dh
2026-09-27 08:46:17 +00:00
parent 72d96aeb81
commit f47c908798
10 changed files with 132 additions and 91 deletions
+23 -48
View File
@@ -17,38 +17,6 @@ final class BatterieRegler
public const STEUERUNG_WECHSELRICHTER = 1;
public const STEUERUNG_ENELIX = 2;
/**
* Erzeugt das bisherige Raster: 250-W-Grundschritte und
* 50-W-Feinschritte im Bereich von -200 W bis +200 W.
*
* @return list<int>
*/
public static function leistungsraster(float $maxLadenW, float $maxEntladenW): array
{
self::pruefeLeistungsgrenzen($maxLadenW, $maxEntladenW);
$maxLaden = (int) floor($maxLadenW / 50.0) * 50;
$maxEntladen = (int) floor($maxEntladenW / 50.0) * 50;
$werte = [0];
for ($leistung = -$maxEntladen; $leistung <= 0; $leistung += 250) {
$werte[] = $leistung;
}
for ($leistung = 0; $leistung <= $maxLaden; $leistung += 250) {
$werte[] = $leistung;
}
for ($leistung = -200; $leistung <= 200; $leistung += 50) {
if ($leistung >= -$maxEntladen && $leistung <= $maxLaden) {
$werte[] = $leistung;
}
}
$werte = array_values(array_unique($werte));
sort($werte, SORT_NUMERIC);
return $werte;
}
public static function hystereseAktiv(
float $ladezustand,
float $reserve,
@@ -68,9 +36,10 @@ final class BatterieRegler
}
/**
* Bildet das zustands- und betriebsartabhaengige Angebot aus Enelix 1 ab.
* Bildet das zustands- und betriebsartabhaengige Angebot als
* durchgaengige Leistungsbereiche in ganzen Watt ab.
*
* @return list<int>
* @return list<int|array{Von_W: int, Bis_W: int}>
*/
public static function leistungsangebot(
bool $aktiv,
@@ -97,7 +66,8 @@ final class BatterieRegler
return [0];
}
$raster = self::leistungsraster($maxLadenW, $maxEntladenW);
$maxLaden = (int) floor($maxLadenW);
$maxEntladen = (int) floor($maxEntladenW);
if ($peakbetrieb) {
if ($ladezustand > $reserve && !$hystereseAktiv) {
$ziel = $netzleistungW > 0.0
@@ -107,26 +77,26 @@ final class BatterieRegler
return [self::begrenzeLeistung($ziel, $maxLadenW, $maxEntladenW)];
}
if ($ladezustand > $reserve && $hystereseAktiv) {
return self::filtere($raster, static fn (int $wert): bool => $wert <= 0);
return self::leistungsbereich(-$maxEntladen, 0);
}
if ($ladezustand > $minimum) {
return $raster;
return self::leistungsbereich(-$maxEntladen, $maxLaden);
}
return self::filtere($raster, static fn (int $wert): bool => $wert >= 0);
return self::leistungsbereich(0, $maxLaden);
}
if ($ladezustand > 99.0) {
return self::filtere($raster, static fn (int $wert): bool => $wert <= 0);
return self::leistungsbereich(-$maxEntladen, 0);
}
if ($ladezustand > $reserve && !$hystereseAktiv) {
return $raster;
return self::leistungsbereich(-$maxEntladen, $maxLaden);
}
if ($ladezustand >= $reserve && $hystereseAktiv) {
return self::filtere($raster, static fn (int $wert): bool => $wert >= 0);
return self::leistungsbereich(0, $maxLaden);
}
return [(int) round($maxLadenW)];
return [$maxLaden];
}
/**
@@ -220,12 +190,14 @@ final class BatterieRegler
return 1;
}
/** @param list<int> $werte
* @return list<int>
*/
private static function filtere(array $werte, callable $filter): array
/** @return list<int|array{Von_W: int, Bis_W: int}> */
private static function leistungsbereich(int $vonW, int $bisW): array
{
return array_values(array_filter($werte, $filter));
if ($vonW === $bisW) {
return [$vonW];
}
return [['Von_W' => $vonW, 'Bis_W' => $bisW]];
}
private static function begrenzeLeistung(
@@ -233,7 +205,10 @@ final class BatterieRegler
float $maxLadenW,
float $maxEntladenW
): int {
return (int) round(min($maxLadenW, max(-$maxEntladenW, $leistungW)));
$maxLaden = (int) floor($maxLadenW);
$maxEntladen = (int) floor($maxEntladenW);
return (int) round(min($maxLaden, max(-$maxEntladen, $leistungW)));
}
private static function pruefeLeistungsgrenzen(float $maxLadenW, float $maxEntladenW): void
+27
View File
@@ -70,6 +70,33 @@ final class Nachrichtenvertrag
self::pruefeZustand($daten['Zustand']);
}
/**
* @param list<int|array{Von_W: int, Bis_W: int}> $leistungswerte
*/
public static function enthaeltLeistungswert(array $leistungswerte, int $leistung): bool
{
foreach ($leistungswerte as $eintrag) {
if (is_int($eintrag)) {
if ($eintrag === $leistung) {
return true;
}
continue;
}
if (is_array($eintrag)
&& isset($eintrag['Von_W'], $eintrag['Bis_W'])
&& is_int($eintrag['Von_W'])
&& is_int($eintrag['Bis_W'])
&& $leistung >= $eintrag['Von_W']
&& $leistung <= $eintrag['Bis_W']
) {
return true;
}
}
return false;
}
/**
* @param mixed $kopf
*/