Do not latch full on transient zero current; require explicit completion. Validate go-e errors and Pico status/timestamps, keep historical events diagnostic, and preserve faults until a fresh successful poll. Budget the 6 A phase probe through the manager and correct stale phase counts conservatively. Add adapter, regulator, isolated runtime and Symcon regression cases plus migration documentation. Verified: composer check (402 tests, 1875 assertions), 92 pure-function assertions in Symcon 8.0, git diff --check. No plant deployment or hardware commands.
This commit is contained in:
+22
-15
@@ -11,6 +11,7 @@ final class LadestationRegler
|
||||
public const PHASEN_UNBEKANNT = 0;
|
||||
public const PHASEN_EIN = 1;
|
||||
public const PHASEN_DREI = 3;
|
||||
public const PHASENERKENNUNGSLEISTUNG = 4104;
|
||||
|
||||
private const LEISTUNG_PRO_AMPERE_EINPHASIG = 230;
|
||||
private const LEISTUNG_PRO_AMPERE_DREIPHASIG = 684;
|
||||
@@ -26,17 +27,20 @@ final class LadestationRegler
|
||||
throw new InvalidArgumentException('Erkennungsstrom muss zwischen 6 und 32 A liegen.');
|
||||
}
|
||||
|
||||
if ($leistung < 5.5 * self::LEISTUNG_PRO_AMPERE_EINPHASIG) {
|
||||
return self::PHASEN_UNBEKANNT;
|
||||
}
|
||||
$trennleistung = 2 * self::LEISTUNG_PRO_AMPERE_EINPHASIG * $angeforderterStrom;
|
||||
|
||||
return $leistung > $trennleistung ? self::PHASEN_DREI : self::PHASEN_EIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Ladepausen sind kein Ladeende. Nur ein expliziter aktueller Geraetestatus
|
||||
* darf "geladen" melden; alte, aus Niedrigstrom abgeleitete Werte verfallen.
|
||||
* Die bisherigen Verlaufsparameter bleiben fuer Aufrufer kompatibel.
|
||||
*
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int} $rohstatus
|
||||
* @param array{Rohstatus: int, Istleistung_W: float, Iststrom_A?: float, Phasenzahl?: int, LadeendeBestaetigt?: bool} $rohstatus
|
||||
* @return array<string, int|float|bool>
|
||||
*/
|
||||
public static function normalisiereStatus(
|
||||
@@ -54,14 +58,17 @@ final class LadestationRegler
|
||||
$geladen = false;
|
||||
|
||||
if ($verbunden) {
|
||||
if (in_array($bekanntePhasenzahl, [self::PHASEN_EIN, self::PHASEN_DREI], true)) {
|
||||
$phasen = $bekanntePhasenzahl;
|
||||
if ($leistung > 7500.0 || ($warVerbunden && $bekanntePhasenzahl === self::PHASEN_DREI)) {
|
||||
// Einzelne momentan unbelastete Phasen duerfen das Budget nicht verkleinern.
|
||||
$phasen = self::PHASEN_DREI;
|
||||
} 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;
|
||||
} elseif ($warVerbunden
|
||||
&& in_array($bekanntePhasenzahl, [self::PHASEN_EIN, self::PHASEN_DREI], true)
|
||||
) {
|
||||
$phasen = $bekanntePhasenzahl;
|
||||
}
|
||||
|
||||
$nenner = $phasen === self::PHASEN_DREI
|
||||
@@ -70,12 +77,8 @@ final class LadestationRegler
|
||||
$ladestrom = isset($rohstatus['Iststrom_A'])
|
||||
? max(0.0, (float) $rohstatus['Iststrom_A'])
|
||||
: ($phasen === self::PHASEN_UNBEKANNT ? 0.0 : $leistung / $nenner);
|
||||
$ermittelterMaximalstrom = 2.5 + $ladestrom;
|
||||
$geladen = $warGeladen
|
||||
|| ($warVerbunden
|
||||
&& $ladungErwartet
|
||||
&& $ladeleistungWurdeErkannt
|
||||
&& $ermittelterMaximalstrom < 6.0);
|
||||
$geladen = ($rohstatus['LadeendeBestaetigt'] ?? false) === true
|
||||
&& $ladestrom < 1.0 && $leistung < 100.0;
|
||||
}
|
||||
|
||||
if (!$verbunden) {
|
||||
@@ -137,7 +140,8 @@ final class LadestationRegler
|
||||
}
|
||||
|
||||
if ($phasenzahl === self::PHASEN_UNBEKANNT) {
|
||||
return [0];
|
||||
// 6 A mit konservativem Dreiphasenbudget, niemals ein direkter Probebefehl.
|
||||
return $solarladen && $peakbetrieb ? [0] : [0, self::PHASENERKENNUNGSLEISTUNG];
|
||||
}
|
||||
|
||||
$stufen = self::leistungsstufen($phasenzahl, $maximalerLadestrom);
|
||||
@@ -159,6 +163,9 @@ final class LadestationRegler
|
||||
if ($leistung <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if ($phasenzahl === self::PHASEN_UNBEKANNT) {
|
||||
return $leistung >= self::PHASENERKENNUNGSLEISTUNG ? 6 : 0;
|
||||
}
|
||||
|
||||
$stufen = self::stufenFuerPhasen($phasenzahl);
|
||||
if ($leistung < $stufen[0]) {
|
||||
|
||||
Reference in New Issue
Block a user