diff --git a/EaseeGateway/README.md b/EaseeGateway/README.md index 426ae66..79196b0 100644 --- a/EaseeGateway/README.md +++ b/EaseeGateway/README.md @@ -16,6 +16,12 @@ Jeder Aufruf der Ladestationsinstanz wird sofort als Version wird dabei `minutes: 0` gesendet. Das Gateway puffert, begrenzt oder wiederholt die Stromvorgabe nicht selbst. +Im Debug der Ladestations- und Gateway-Instanz werden der vollständige +Strombefehl, URL und Payload sowie HTTP-Status und Easee-Antwort ausgegeben. +Zusätzlich werden die Observations 48, 96, 111 bis 114 protokolliert. Damit ist +erkennbar, ob der Sollwert übernommen wurde und welches weitere Limit das Laden +verhindert. + Der benötigte WebSocket-Client wird nach dem Speichern der Easee-Zugangsdaten automatisch erstellt und konfiguriert. Im WebSocket-Client muss keine URL eingetragen werden. diff --git a/EaseeGateway/module.php b/EaseeGateway/module.php index b425f1b..5d430b0 100644 --- a/EaseeGateway/module.php +++ b/EaseeGateway/module.php @@ -499,7 +499,7 @@ class EaseeGateway extends IPSModule if ( $serialNumber !== "" && $valueExists && - ($observationID === 109 || $observationID === 120) + in_array($observationID, [48, 96, 109, 111, 112, 113, 114, 120], true) ) { $this->PublishObservation($serialNumber, $observationID, $value); } @@ -513,6 +513,17 @@ class EaseeGateway extends IPSModule private function PublishObservation(string $serialNumber, int $observationID, $value) { + $names = [ + 48 => "DynamicChargerCurrent", + 96 => "ReasonForNoCurrent", + 109 => "ChargerOpMode", + 111 => "DynamicCircuitCurrentP1", + 112 => "DynamicCircuitCurrentP2", + 113 => "DynamicCircuitCurrentP3", + 114 => "OutputCurrent", + 120 => "TotalPower", + ]; + $cache = $this->ReadAttributeArray("ObservationCache"); if (!isset($cache[$serialNumber]) || !is_array($cache[$serialNumber])) { $cache[$serialNumber] = []; @@ -521,6 +532,17 @@ class EaseeGateway extends IPSModule $cache[$serialNumber]["updated"] = time(); $this->WriteAttributeString("ObservationCache", json_encode($cache)); + $this->SendDebug( + "Easee Observation RX", + json_encode([ + "serialNumber" => $serialNumber, + "id" => $observationID, + "name" => $names[$observationID] ?? "Unknown", + "value" => $value, + ]), + 0 + ); + $this->SendDataToChildren(json_encode([ "DataID" => self::CHILD_EVENT_DATA_ID, "Buffer" => json_encode([ @@ -552,26 +574,41 @@ class EaseeGateway extends IPSModule return ["success" => false, "error" => "Strom muss zwischen 0 und 32 A liegen"]; } + $path = "/api/chargers/" . rawurlencode($serialNumber) . + "/commands/set_dynamic_charger_current"; + $body = '{"amps":' . $amps . ',"minutes":0}'; + $this->SendDebug( - "DynamicCurrent", + "Easee Command TX", json_encode([ - "serialNumber" => $serialNumber, - "amps" => $amps, - "minutes" => 0, - "command" => "send", + "method" => "POST", + "url" => self::API_BASE_URL . $path, + "contentType" => "application/*+json", + "body" => $body, ]), 0 ); - return $this->AuthorizedApiRequest( + $result = $this->AuthorizedApiRequest( "POST", - "/api/chargers/" . rawurlencode($serialNumber) . - "/commands/set_dynamic_charger_current", - json_encode([ - "amps" => $amps, - "minutes" => 0, - ]) + $path, + $body ); + + $this->SendDebug( + "Easee Command RX", + json_encode([ + "serialNumber" => $serialNumber, + "requestedAmps" => $amps, + "success" => (bool)($result["success"] ?? false), + "httpCode" => (int)($result["httpCode"] ?? 0), + "responseBody" => (string)($result["body"] ?? ""), + "error" => (string)($result["error"] ?? ""), + ]), + 0 + ); + + return $result; } private function AuthorizedApiRequest(string $method, string $path, string $body): array @@ -607,6 +644,7 @@ class EaseeGateway extends IPSModule "success" => false, "error" => $error, "httpCode" => $response["httpCode"], + "body" => $response["body"], ]; } diff --git a/Ladestation_v2/module.php b/Ladestation_v2/module.php index e1d02a5..ff9cc3e 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 ([109, 120] as $observationID) { + foreach ([48, 96, 109, 111, 112, 113, 114, 120] as $observationID) { $key = (string)$observationID; if (array_key_exists($key, $response["state"])) { $this->StoreEaseeObservation( @@ -519,7 +519,17 @@ class Ladestation_v2 extends IPSModule private function StoreEaseeObservation(int $observationID, $value, int $timestamp) { - if ($observationID !== 109 && $observationID !== 120) { + $names = [ + 48 => "DynamicChargerCurrent", + 96 => "ReasonForNoCurrent", + 109 => "ChargerOpMode", + 111 => "DynamicCircuitCurrentP1", + 112 => "DynamicCircuitCurrentP2", + 113 => "DynamicCircuitCurrentP3", + 114 => "OutputCurrent", + 120 => "TotalPower", + ]; + if (!isset($names[$observationID])) { return; } @@ -531,6 +541,17 @@ class Ladestation_v2 extends IPSModule $state["updated"] = $timestamp; $this->SetBuffer("EaseeGatewayState", json_encode($state)); + $this->SendDebug( + "Easee Observation", + json_encode([ + "id" => $observationID, + "name" => $names[$observationID], + "value" => $value, + "timestamp" => $timestamp, + ]), + 0 + ); + if ($observationID === 109) { $this->SetValue("Fahrzeugstatus", (int)$value); } elseif ($observationID === 120) { @@ -570,11 +591,25 @@ class Ladestation_v2 extends IPSModule private function SendEaseeCurrentToGateway(float $value) { - $response = $this->SendEaseeGatewayRequest([ + $request = [ "action" => "SetDynamicChargerCurrent", "serialNumber" => strtoupper(trim($this->ReadPropertyString("Seriennummer"))), "amps" => $value, - ]); + ]; + + $this->SendDebug( + "Easee Station TX", + json_encode($request), + 0 + ); + + $response = $this->SendEaseeGatewayRequest($request); + + $this->SendDebug( + "Easee Station RX", + json_encode($response), + 0 + ); if (!is_array($response) || !($response["success"] ?? false)) { $error = is_array($response) @@ -1090,10 +1125,45 @@ class Ladestation_v2 extends IPSModule $stationType = $this->ReadPropertyInteger("Ladestation"); if ($stationType === 5 || $stationType === 6) { + $lastValue = $this->GetBuffer("LastEaseeRequestedAmps"); + $transition = "unchanged"; + if ($lastValue === "") { + $transition = "initial"; + } elseif ((float)$lastValue <= 0 && $value > 0) { + $transition = "zero_to_positive"; + } elseif ((float)$lastValue > 0 && $value <= 0) { + $transition = "positive_to_zero"; + } elseif (abs((float)$lastValue - $value) > 0.01) { + $transition = "changed"; + } + $this->SetBuffer("LastEaseeRequestedAmps", (string)$value); + + $this->SendDebug( + "Easee Current Decision", + json_encode([ + "stationType" => $stationType, + "serialNumber" => strtoupper(trim($this->ReadPropertyString("Seriennummer"))), + "previousAmps" => $lastValue === "" ? null : (float)$lastValue, + "requestedAmps" => $value, + "transition" => $transition, + "powerWatts" => $this->GetValue("Aktuelle_Leistung"), + "isSinglePhase" => $this->GetValue("Is_1_ph"), + "chargerReady" => $this->GetValue("Ladebereit"), + "carDetected" => $this->GetValue("Car_detected"), + "chargerOpMode" => $this->GetValue("Fahrzeugstatus"), + ]), + 0 + ); + if ( $stationType === 5 && $this->ReadPropertyString("Username") != $this->GetValue("Letzer_User") ) { + $this->SendDebug( + "Easee Current Blocked", + "Benutzerkennung stimmt nicht mit Letzer_User überein", + 0 + ); return; } return $this->SendEaseeCurrentToGateway($value);