This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Belevo\EnelixEMS;
|
||||
|
||||
final class EaseeGatewayProtokoll
|
||||
{
|
||||
/** @var list<int> */
|
||||
public const BEOBACHTUNGEN = [
|
||||
47, 48, 100, 104, 109, 110, 119, 120, 182, 183, 184, 185, 250,
|
||||
];
|
||||
|
||||
public static function seriennummer(string $wert): string
|
||||
{
|
||||
return strtoupper(trim($wert));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $knoten
|
||||
* @param list<string> $abonnements
|
||||
* @return list<array{Seriennummer: string, ID: int, Wert: mixed}>
|
||||
*/
|
||||
public static function extrahiereBeobachtungen(
|
||||
$knoten,
|
||||
array $abonnements,
|
||||
string $seriennummer = '',
|
||||
int $tiefe = 0
|
||||
): array {
|
||||
if (!is_array($knoten) || $tiefe > 12) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$abonnements = array_values(array_unique(array_map(
|
||||
[self::class, 'seriennummer'],
|
||||
$abonnements
|
||||
)));
|
||||
foreach (['serialNumber', 'SerialNumber', 'chargerId', 'ChargerId', 'mid', 'Mid'] as $feld) {
|
||||
if (!isset($knoten[$feld]) || !is_scalar($knoten[$feld])) {
|
||||
continue;
|
||||
}
|
||||
$kandidat = self::seriennummer((string) $knoten[$feld]);
|
||||
if (in_array($kandidat, $abonnements, true)) {
|
||||
$seriennummer = $kandidat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self::istListe($knoten)) {
|
||||
foreach ($knoten as $wert) {
|
||||
if (!is_string($wert)) {
|
||||
continue;
|
||||
}
|
||||
$kandidat = self::seriennummer($wert);
|
||||
if (in_array($kandidat, $abonnements, true)) {
|
||||
$seriennummer = $kandidat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$id = null;
|
||||
foreach (['id', 'Id', 'observationId', 'ObservationId'] as $feld) {
|
||||
if (array_key_exists($feld, $knoten) && is_numeric($knoten[$feld])) {
|
||||
$id = (int) $knoten[$feld];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$wertVorhanden = false;
|
||||
$wert = null;
|
||||
foreach (['value', 'Value'] as $feld) {
|
||||
if (array_key_exists($feld, $knoten)) {
|
||||
$wertVorhanden = true;
|
||||
$wert = $knoten[$feld];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ergebnis = [];
|
||||
if (
|
||||
$seriennummer !== ''
|
||||
&& $wertVorhanden
|
||||
&& in_array($id, self::BEOBACHTUNGEN, true)
|
||||
) {
|
||||
$ergebnis[] = [
|
||||
'Seriennummer' => $seriennummer,
|
||||
'ID' => $id,
|
||||
'Wert' => $wert,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($knoten as $kind) {
|
||||
if (is_array($kind)) {
|
||||
$ergebnis = array_merge(
|
||||
$ergebnis,
|
||||
self::extrahiereBeobachtungen(
|
||||
$kind,
|
||||
$abonnements,
|
||||
$seriennummer,
|
||||
$tiefe + 1
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $ergebnis;
|
||||
}
|
||||
|
||||
/** @param array<mixed> $wert */
|
||||
private static function istListe(array $wert): bool
|
||||
{
|
||||
$index = 0;
|
||||
foreach ($wert as $schluessel => $_) {
|
||||
if ($schluessel !== $index++) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?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,
|
||||
* 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));
|
||||
|
||||
$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,
|
||||
'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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user