diff --git a/EaseeGateway/README.md b/EaseeGateway/README.md index 5880104..acfa1aa 100644 --- a/EaseeGateway/README.md +++ b/EaseeGateway/README.md @@ -2,7 +2,7 @@ Das Gateway hält eine gemeinsame SignalR-Verbindung zum Easee-Konto und verteilt die Observations 47 (Max Charger Current), 109 (Charger Op Mode), 110 -(Output Phase) und 120 (Total Power) an alle verbundenen +(Output Phase), 120 (Total Power) und 182 bis 185 (gemessene Leiterströme) an alle verbundenen Ladestation_v2-Instanzen. Benutzername und Passwort werden ausschließlich im Gateway eingetragen. Mehrere diff --git a/EaseeGateway/module.php b/EaseeGateway/module.php index e2c44f2..171c89b 100644 --- a/EaseeGateway/module.php +++ b/EaseeGateway/module.php @@ -499,7 +499,7 @@ class EaseeGateway extends IPSModule if ( $serialNumber !== "" && $valueExists && - in_array($observationID, [47, 109, 110, 120], true) + in_array($observationID, [47, 109, 110, 120, 182, 183, 184, 185], true) ) { $this->PublishObservation($serialNumber, $observationID, $value); } @@ -517,6 +517,16 @@ class EaseeGateway extends IPSModule if (!isset($cache[$serialNumber]) || !is_array($cache[$serialNumber])) { $cache[$serialNumber] = []; } + + if ($observationID === 109) { + $previousMode = (int)($cache[$serialNumber]["109"] ?? -1); + if ((int)$value === 1 || $previousMode === 1) { + foreach ([110, 182, 183, 184, 185] as $sessionObservationID) { + $cache[$serialNumber][(string)$sessionObservationID] = 0; + } + } + } + $cache[$serialNumber][(string)$observationID] = $value; $cache[$serialNumber]["updated"] = time(); $this->WriteAttributeString("ObservationCache", json_encode($cache)); diff --git a/Ladestation_v2/README.md b/Ladestation_v2/README.md index 6f401df..3d25df6 100644 --- a/Ladestation_v2/README.md +++ b/Ladestation_v2/README.md @@ -21,13 +21,16 @@ Das Gateway liefert: - Observation 47: maximaler Ladestrom der Station - Observation 109: Fahrzeug-/Ladestatus -- Observation 110: aktive Ausgangsphase +- Observation 110: freigegebene Ausgangsphase - Observation 120: aktuelle Gesamtleistung in kW +- Observations 182 bis 185: gemessene Leiterströme Bei Easee erfolgt die Fahrzeug- und Phasenerkennung ohne den zeitbasierten `Pending_Counter`. Der maximale Ladestrom wird aus Observation 47 übernommen und zusätzlich durch `Max_Current_abs` begrenzt. Die Typen 1 bis 4 verwenden weiterhin unverändert die bisherige zeit- und leistungsbasierte Erkennung. +Die Fahrzeugphasen werden anhand der tatsächlich gemessenen Leiterströme +erkannt; alte Phasenwerte werden beim Trennen oder Neuverbinden verworfen. Stromvorgaben von 0 bis 32 A werden ebenfalls über das Gateway gesendet. diff --git a/Ladestation_v2/module.php b/Ladestation_v2/module.php index 951df27..a4e97f5 100644 --- a/Ladestation_v2/module.php +++ b/Ladestation_v2/module.php @@ -505,7 +505,7 @@ class Ladestation_v2 extends IPSModule } $updated = (int)($response["state"]["updated"] ?? time()); - foreach ([47, 109, 110, 120] as $observationID) { + foreach ([47, 109, 110, 120, 182, 183, 184, 185] as $observationID) { $key = (string)$observationID; if (array_key_exists($key, $response["state"])) { $this->StoreEaseeObservation( @@ -519,7 +519,7 @@ class Ladestation_v2 extends IPSModule private function StoreEaseeObservation(int $observationID, $value, int $timestamp) { - if (!in_array($observationID, [47, 109, 110, 120], true)) { + if (!in_array($observationID, [47, 109, 110, 120, 182, 183, 184, 185], true)) { return; } @@ -527,6 +527,16 @@ class Ladestation_v2 extends IPSModule if (!is_array($state)) { $state = []; } + + if ($observationID === 109) { + $previousMode = (int)($state["109"] ?? -1); + if ((int)$value === 1 || $previousMode === 1) { + foreach ([110, 182, 183, 184, 185] as $sessionObservationID) { + $state[(string)$sessionObservationID] = 0; + } + } + } + $state[(string)$observationID] = $value; $state["updated"] = $timestamp; $this->SetBuffer("EaseeGatewayState", json_encode($state)); @@ -563,6 +573,7 @@ class Ladestation_v2 extends IPSModule private function DetectEaseeCar(int $carType): bool { $wasDetected = $this->GetValue("Car_detected"); + $wasOnePhase = $this->GetValue("Is_1_ph"); $carDetected = $this->Get_Car_Status($carType); $state = json_decode($this->GetBuffer("EaseeGatewayState"), true); if (!is_array($state)) { @@ -571,20 +582,8 @@ class Ladestation_v2 extends IPSModule $this->SetValue("Pending_Counter", 0); - // Observation 110: 10-15 = einphasig, 20-22 = zweiphasig, - // 30 = dreiphasig. Das bestehende Modul unterscheidet nur 1/3 Phasen; - // zweiphasig wird deshalb wie mehrphasig behandelt. - if (array_key_exists("110", $state)) { - $outputPhase = (int)$state["110"]; - if ($outputPhase >= 10 && $outputPhase <= 15) { - $this->SetValue("Is_1_ph", true); - } elseif ( - ($outputPhase >= 20 && $outputPhase <= 22) || - $outputPhase === 30 - ) { - $this->SetValue("Is_1_ph", false); - } - } + $this->DetectEaseePhases($state); + $phaseChanged = $wasOnePhase !== $this->GetValue("Is_1_ph"); // Observation 47 ist der nichtflüchtige maximale Ladestrom der // Station. Die lokal konfigurierte Obergrenze bleibt zusätzlich aktiv. @@ -615,7 +614,7 @@ class Ladestation_v2 extends IPSModule $this->SetValue("Car_detected", true); $this->SetValue("Car_is_full", (int)($state["109"] ?? 0) === 4); - if (!$wasDetected) { + if (!$wasDetected || $phaseChanged) { if ($this->GetValue("Is_1_ph")) { $power = $this->GetValue("Mindestaldestrom") * 230; } else { @@ -627,6 +626,39 @@ class Ladestation_v2 extends IPSModule return true; } + private function DetectEaseePhases(array $state) + { + $outputPhase = (int)($state["110"] ?? 0); + + // Ein explizit einphasiger Easee-Ausgang ist auch in IT-Netzen + // einphasig, obwohl dort Strom auf zwei Leitern gemessen wird. + if ($outputPhase >= 10 && $outputPhase <= 15) { + $this->SetValue("Is_1_ph", true); + return; + } + + $activePhaseConductors = 0; + foreach ([183, 184, 185] as $observationID) { + if (abs((float)($state[(string)$observationID] ?? 0)) >= 1.0) { + $activePhaseConductors++; + } + } + + // Bei einem dreiphasig freigegebenen Ausgang kann ein einphasiges Auto + // trotzdem nur auf einem Leiter Strom beziehen. Observation 110 allein + // kann diesen Fahrzeugwechsel deshalb nicht erkennen. + if ($activePhaseConductors === 1) { + $this->SetValue("Is_1_ph", true); + } elseif ($activePhaseConductors >= 2) { + $this->SetValue("Is_1_ph", false); + } elseif ( + ($outputPhase >= 20 && $outputPhase <= 22) || + $outputPhase === 30 + ) { + $this->SetValue("Is_1_ph", false); + } + } + private function SendEaseeCurrentToGateway(float $value) { $response = $this->SendEaseeGatewayRequest([