feat(ladestation): Phasenerkennung und Schaltsperren erweitern
Tests / test (push) Successful in 45s
Tests / test (push) Successful in 45s
This commit is contained in:
@@ -91,7 +91,7 @@ final class LadestationAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float}
|
||||
* @return array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int}
|
||||
*/
|
||||
public static function dekodiereStatus(int $geraetetyp, string $antwort): array
|
||||
{
|
||||
@@ -121,11 +121,19 @@ final class LadestationAdapter
|
||||
&& is_numeric($daten['nrg'][6])
|
||||
) {
|
||||
$stromfaktor = $geraetetyp === self::GO_E_ALT ? 0.1 : 1.0;
|
||||
$status['Iststrom_A'] = max(
|
||||
(float) $daten['nrg'][4],
|
||||
(float) $daten['nrg'][5],
|
||||
(float) $daten['nrg'][6]
|
||||
) * $stromfaktor;
|
||||
$phasenstroeme = [
|
||||
(float) $daten['nrg'][4] * $stromfaktor,
|
||||
(float) $daten['nrg'][5] * $stromfaktor,
|
||||
(float) $daten['nrg'][6] * $stromfaktor,
|
||||
];
|
||||
$status['Iststrom_A'] = max($phasenstroeme);
|
||||
$aktivePhasen = count(array_filter(
|
||||
$phasenstroeme,
|
||||
static fn (float $strom): bool => $strom >= 1.0
|
||||
));
|
||||
if ($aktivePhasen > 0) {
|
||||
$status['Phasenzahl'] = $aktivePhasen >= 2 ? 3 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
|
||||
+36
-25
@@ -12,27 +12,15 @@ final class LadestationRegler
|
||||
public const PHASEN_EIN = 1;
|
||||
public const PHASEN_DREI = 3;
|
||||
|
||||
/** @var list<int> */
|
||||
private const LEISTUNGEN_EINPHASIG = [
|
||||
1450, 1690, 1930, 2170, 2410, 2650, 2890, 3130, 3370,
|
||||
3610, 3850, 4090, 4330, 4570, 4810, 5050, 5290, 5530,
|
||||
5770, 6010, 6250, 6490, 6730, 6970, 7210, 7450, 7690,
|
||||
];
|
||||
|
||||
/** @var list<int> */
|
||||
private const LEISTUNGEN_DREIPHASIG = [
|
||||
4150, 4850, 5550, 6250, 6950, 7600, 8300, 9000, 9700,
|
||||
10300, 11000, 11750, 12450, 13150, 13850, 14550, 15250,
|
||||
15900, 16600, 17300, 18000, 18700, 19400, 20100, 20800,
|
||||
21500, 22000,
|
||||
];
|
||||
private const LEISTUNG_PRO_AMPERE_EINPHASIG = 230;
|
||||
private const LEISTUNG_PRO_AMPERE_DREIPHASIG = 684;
|
||||
|
||||
/**
|
||||
* Die Schwelle und der Zuschlag von 2.5 A stammen aus der Enelix-1-Ladestation.
|
||||
* Ein Ladeende wird erst nach zuvor gemessener Ladeleistung angenommen, damit
|
||||
* die Anlaufzeit nach einer neuen Stromvorgabe nicht als volles Fahrzeug gilt.
|
||||
*
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float} $rohstatus
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int} $rohstatus
|
||||
* @return array<string, int|float|bool>
|
||||
*/
|
||||
public static function normalisiereStatus(
|
||||
@@ -40,7 +28,8 @@ final class LadestationRegler
|
||||
bool $warVerbunden,
|
||||
bool $warGeladen = false,
|
||||
bool $ladungErwartet = true,
|
||||
bool $ladeleistungWurdeErkannt = false
|
||||
bool $ladeleistungWurdeErkannt = false,
|
||||
int $bekanntePhasenzahl = self::PHASEN_UNBEKANNT
|
||||
): array {
|
||||
$verbunden = $rohstatus['Rohstatus'] !== 1;
|
||||
$leistung = max(0.0, $rohstatus['Istleistung_W']);
|
||||
@@ -49,11 +38,22 @@ final class LadestationRegler
|
||||
$geladen = false;
|
||||
|
||||
if ($verbunden) {
|
||||
$phasen = $leistung > 7500.0 ? self::PHASEN_DREI : self::PHASEN_EIN;
|
||||
$nenner = $phasen === self::PHASEN_EIN ? 230.0 : 1.71 * 400.0;
|
||||
if (in_array($bekanntePhasenzahl, [self::PHASEN_EIN, self::PHASEN_DREI], true)) {
|
||||
$phasen = $bekanntePhasenzahl;
|
||||
} elseif (isset($rohstatus['Phasenzahl'])
|
||||
&& in_array($rohstatus['Phasenzahl'], [self::PHASEN_EIN, self::PHASEN_DREI], true)
|
||||
) {
|
||||
$phasen = (int) $rohstatus['Phasenzahl'];
|
||||
} elseif ($leistung > 7500.0) {
|
||||
$phasen = self::PHASEN_DREI;
|
||||
}
|
||||
|
||||
$nenner = $phasen === self::PHASEN_DREI
|
||||
? self::LEISTUNG_PRO_AMPERE_DREIPHASIG
|
||||
: self::LEISTUNG_PRO_AMPERE_EINPHASIG;
|
||||
$ladestrom = isset($rohstatus['Iststrom_A'])
|
||||
? max(0.0, (float) $rohstatus['Iststrom_A'])
|
||||
: $leistung / $nenner;
|
||||
: ($phasen === self::PHASEN_UNBEKANNT ? 0.0 : $leistung / $nenner);
|
||||
$ermittelterMaximalstrom = 2.5 + $ladestrom;
|
||||
$geladen = $warGeladen
|
||||
|| ($warVerbunden
|
||||
@@ -94,7 +94,10 @@ final class LadestationRegler
|
||||
return null;
|
||||
}
|
||||
|
||||
$kandidat = max(6, min($konfigurierterMaximalstrom, (int) round($gemessenerStrom)));
|
||||
$kandidat = max(
|
||||
6,
|
||||
min($konfigurierterMaximalstrom, (int) floor($gemessenerStrom + 2.5))
|
||||
);
|
||||
if ($kandidat > $vorgegebenerStrom - 2 || $kandidat >= $konfigurierterMaximalstrom) {
|
||||
return null;
|
||||
}
|
||||
@@ -117,6 +120,10 @@ final class LadestationRegler
|
||||
return [0];
|
||||
}
|
||||
|
||||
if ($phasenzahl === self::PHASEN_UNBEKANNT) {
|
||||
return [0];
|
||||
}
|
||||
|
||||
$stufen = self::leistungsstufen($phasenzahl, $maximalerLadestrom);
|
||||
if ($stufen === []) {
|
||||
return [0];
|
||||
@@ -167,12 +174,16 @@ final class LadestationRegler
|
||||
private static function stufenFuerPhasen(int $phasenzahl): array
|
||||
{
|
||||
if ($phasenzahl === self::PHASEN_EIN) {
|
||||
return self::LEISTUNGEN_EINPHASIG;
|
||||
}
|
||||
if ($phasenzahl === self::PHASEN_DREI) {
|
||||
return self::LEISTUNGEN_DREIPHASIG;
|
||||
$leistungProAmpere = self::LEISTUNG_PRO_AMPERE_EINPHASIG;
|
||||
} elseif ($phasenzahl === self::PHASEN_DREI) {
|
||||
$leistungProAmpere = self::LEISTUNG_PRO_AMPERE_DREIPHASIG;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Phasenzahl muss 1 oder 3 sein.');
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Phasenzahl muss 1 oder 3 sein.');
|
||||
return array_map(
|
||||
static fn (int $strom): int => $strom * $leistungProAmpere,
|
||||
range(6, 32)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user