This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
final class LadestationRegler
|
||||
{
|
||||
public const PHASEN_UNBEKANNT = 0;
|
||||
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,
|
||||
];
|
||||
|
||||
/**
|
||||
* Die Schwelle, die Voll-Erkennung und der Zuschlag von 2.5 A stammen
|
||||
* aus der Enelix-1-Ladestation und bleiben bewusst kompatibel.
|
||||
*
|
||||
* @param array{Rohstatus: int, Istleistung_W: float} $rohstatus
|
||||
* @return array<string, int|float|bool>
|
||||
*/
|
||||
public static function normalisiereStatus(array $rohstatus, bool $warVerbunden): array
|
||||
{
|
||||
$verbunden = $rohstatus['Rohstatus'] !== 1;
|
||||
$leistung = max(0.0, $rohstatus['Istleistung_W']);
|
||||
$phasen = self::PHASEN_UNBEKANNT;
|
||||
$ladestrom = 0.0;
|
||||
$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;
|
||||
$ladestrom = $leistung / $nenner;
|
||||
$ermittelterMaximalstrom = 2.5 + $ladestrom;
|
||||
$geladen = $warVerbunden && $ermittelterMaximalstrom < 6.0;
|
||||
}
|
||||
|
||||
if (!$verbunden) {
|
||||
$fahrzeugstatus = 1;
|
||||
} elseif ($geladen) {
|
||||
$fahrzeugstatus = 4;
|
||||
} elseif ($leistung > 0.0) {
|
||||
$fahrzeugstatus = 3;
|
||||
} else {
|
||||
$fahrzeugstatus = 2;
|
||||
}
|
||||
|
||||
return [
|
||||
'FahrzeugVerbunden' => $verbunden,
|
||||
'FahrzeugGeladen' => $geladen,
|
||||
'Fahrzeugstatus' => $fahrzeugstatus,
|
||||
'Phasenzahl' => $phasen,
|
||||
'Istleistung_W' => $leistung,
|
||||
'Ladestrom_A' => $ladestrom,
|
||||
];
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
public static function leistungsangebot(
|
||||
bool $aktiv,
|
||||
bool $ladefreigabe,
|
||||
bool $verbunden,
|
||||
bool $geladen,
|
||||
int $phasenzahl,
|
||||
int $maximalerLadestrom,
|
||||
bool $solarladen,
|
||||
bool $peakbetrieb
|
||||
): array {
|
||||
if (!$aktiv || !$ladefreigabe || !$verbunden || $geladen) {
|
||||
return [0];
|
||||
}
|
||||
|
||||
$stufen = self::leistungsstufen($phasenzahl, $maximalerLadestrom);
|
||||
if ($stufen === []) {
|
||||
return [0];
|
||||
}
|
||||
if ($solarladen) {
|
||||
return $peakbetrieb ? [0] : array_merge([0], $stufen);
|
||||
}
|
||||
if ($peakbetrieb) {
|
||||
return array_merge([0], $stufen);
|
||||
}
|
||||
|
||||
return [$stufen[count($stufen) - 1]];
|
||||
}
|
||||
|
||||
public static function stromFuerLeistung(int $leistung, int $phasenzahl): int
|
||||
{
|
||||
if ($leistung <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$stufen = self::stufenFuerPhasen($phasenzahl);
|
||||
if ($leistung < $stufen[0]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$strom = 6;
|
||||
foreach ($stufen as $index => $schwelle) {
|
||||
if ($leistung < $schwelle) {
|
||||
break;
|
||||
}
|
||||
$strom = 6 + $index;
|
||||
}
|
||||
|
||||
return min(32, $strom);
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
private static function leistungsstufen(int $phasenzahl, int $maximalerLadestrom): array
|
||||
{
|
||||
if ($maximalerLadestrom < 6 || $maximalerLadestrom > 32) {
|
||||
throw new InvalidArgumentException('MaximalerLadestrom muss zwischen 6 und 32 A liegen.');
|
||||
}
|
||||
|
||||
return array_slice(self::stufenFuerPhasen($phasenzahl), 0, $maximalerLadestrom - 5);
|
||||
}
|
||||
|
||||
/** @return list<int> */
|
||||
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;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Phasenzahl muss 1 oder 3 sein.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user