158 lines
5.2 KiB
PHP
158 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Belevo\EnelixEMS;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
final class EaseeLadestatus
|
|
{
|
|
public const BETRIEBSMODUS_EASEE = 0;
|
|
public const BETRIEBSMODUS_NUR_SOLAR = 1;
|
|
|
|
/**
|
|
* @param array<string, mixed> $beobachtungen
|
|
* @return array{
|
|
* StatusGueltig: bool,
|
|
* FahrzeugVerbunden: bool,
|
|
* FahrzeugGeladen: bool,
|
|
* Fahrzeugstatus: int,
|
|
* Phasenzahl: int,
|
|
* Istleistung_W: float,
|
|
* Ladestrom_A: float,
|
|
* ApiMaximalstrom_A: int,
|
|
* EaseeAktiviert: bool,
|
|
* AutorisierungErforderlich: bool,
|
|
* RemoteStartErforderlich: bool,
|
|
* SmartCharging: bool,
|
|
* GrundKeinLadestrom: int,
|
|
* Stoerung: bool,
|
|
* Stoertext: string
|
|
* }
|
|
*/
|
|
public static function ausBeobachtungen(array $beobachtungen, int $konfigurierterMaximalstrom): array
|
|
{
|
|
if ($konfigurierterMaximalstrom < 6 || $konfigurierterMaximalstrom > 32) {
|
|
throw new InvalidArgumentException(
|
|
'MaximalerLadestrom muss zwischen 6 und 32 A liegen.'
|
|
);
|
|
}
|
|
|
|
$rohBetriebszustand = $beobachtungen['109'] ?? null;
|
|
$statusGueltig = is_numeric($rohBetriebszustand)
|
|
&& floor((float) $rohBetriebszustand) === (float) $rohBetriebszustand
|
|
&& in_array((int) $rohBetriebszustand, [0, 1, 2, 3, 4, 5, 6, 7, 8], true);
|
|
$betriebszustand = $statusGueltig ? (int) $rohBetriebszustand : 0;
|
|
$verbunden = $statusGueltig
|
|
&& in_array($betriebszustand, [2, 3, 4, 5, 6, 7, 8], true);
|
|
$geladen = $betriebszustand === 4;
|
|
$fahrzeugstatus = self::fahrzeugstatus($betriebszustand);
|
|
|
|
$phasenzahl = $verbunden
|
|
? self::phasenzahl((int) ($beobachtungen['110'] ?? 0))
|
|
: 0;
|
|
|
|
$leistung = max(0.0, (float) ($beobachtungen['120'] ?? 0.0) * 1000.0);
|
|
$stroeme = [];
|
|
foreach ([182, 183, 184, 185] as $id) {
|
|
if (array_key_exists((string) $id, $beobachtungen)) {
|
|
$stroeme[] = abs((float) $beobachtungen[(string) $id]);
|
|
}
|
|
}
|
|
$ladestrom = $stroeme === [] ? 0.0 : max($stroeme);
|
|
|
|
$grenzen = [$konfigurierterMaximalstrom];
|
|
foreach ([47, 104] as $id) {
|
|
$grenze = (float) ($beobachtungen[(string) $id] ?? 0.0);
|
|
if ($grenze >= 6.0) {
|
|
$grenzen[] = (int) floor($grenze);
|
|
}
|
|
}
|
|
$apiMaximalstrom = max(6, min($grenzen));
|
|
$easeeAktiviert = !array_key_exists('31', $beobachtungen)
|
|
|| (bool) $beobachtungen['31'];
|
|
$autorisierungErforderlich = (bool) (
|
|
$beobachtungen['42'] ?? $beobachtungen['41'] ?? false
|
|
);
|
|
$remoteStartErforderlich = (bool) ($beobachtungen['43'] ?? false);
|
|
$smartCharging = (bool) ($beobachtungen['102'] ?? false);
|
|
$grundKeinLadestrom = is_numeric($beobachtungen['96'] ?? null)
|
|
? (int) $beobachtungen['96']
|
|
: 0;
|
|
|
|
$fehlercode = (int) ($beobachtungen['119'] ?? 0);
|
|
$stoerung = $betriebszustand === 5 || $fehlercode !== 0;
|
|
$stoertext = '';
|
|
if ($betriebszustand === 5) {
|
|
$stoertext = 'Easee meldet einen Fehlerzustand.';
|
|
}
|
|
if ($fehlercode !== 0) {
|
|
$stoertext .= ($stoertext === '' ? '' : ' ') . 'Easee-Fehlercode: ' . $fehlercode . '.';
|
|
}
|
|
|
|
return [
|
|
'StatusGueltig' => $statusGueltig,
|
|
'FahrzeugVerbunden' => $verbunden,
|
|
'FahrzeugGeladen' => $geladen,
|
|
'Fahrzeugstatus' => $fahrzeugstatus,
|
|
'Phasenzahl' => $phasenzahl,
|
|
'Istleistung_W' => $leistung,
|
|
'Ladestrom_A' => $ladestrom,
|
|
'ApiMaximalstrom_A' => $apiMaximalstrom,
|
|
'EaseeAktiviert' => $easeeAktiviert,
|
|
'AutorisierungErforderlich' => $autorisierungErforderlich,
|
|
'RemoteStartErforderlich' => $remoteStartErforderlich,
|
|
'SmartCharging' => $smartCharging,
|
|
'GrundKeinLadestrom' => $grundKeinLadestrom,
|
|
'Stoerung' => $stoerung,
|
|
'Stoertext' => trim($stoertext),
|
|
];
|
|
}
|
|
|
|
public static function solarladenErzwungen(int $betriebsmodus): bool
|
|
{
|
|
if (!in_array($betriebsmodus, [
|
|
self::BETRIEBSMODUS_EASEE,
|
|
self::BETRIEBSMODUS_NUR_SOLAR,
|
|
], true)) {
|
|
throw new InvalidArgumentException('Unbekannter Easee-Betriebsmodus.');
|
|
}
|
|
|
|
return $betriebsmodus === self::BETRIEBSMODUS_NUR_SOLAR;
|
|
}
|
|
|
|
private static function fahrzeugstatus(int $betriebszustand): int
|
|
{
|
|
if ($betriebszustand === 1) {
|
|
return 1;
|
|
}
|
|
if (in_array($betriebszustand, [2, 6, 7, 8], true)) {
|
|
return 2;
|
|
}
|
|
if ($betriebszustand === 3) {
|
|
return 3;
|
|
}
|
|
if ($betriebszustand === 4) {
|
|
return 4;
|
|
}
|
|
if ($betriebszustand === 5) {
|
|
return 5;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static function phasenzahl(int $ausgangsphase): int
|
|
{
|
|
if ($ausgangsphase >= 10 && $ausgangsphase <= 15) {
|
|
return 1;
|
|
}
|
|
if ($ausgangsphase === 30) {
|
|
return 3;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|