no message

This commit is contained in:
dh
2026-08-25 09:33:47 +02:00
parent 125cc14c94
commit f4ee0ea78a
7 changed files with 223 additions and 151 deletions
+3 -3
View File
@@ -17,6 +17,6 @@ Jeder Aufruf der Ladestationsinstanz wird sofort als
Version wird dabei `minutes: 0` gesendet. Das Gateway puffert, begrenzt oder
wiederholt die Stromvorgabe nicht selbst.
Der benötigte WebSocket-Client wird nach dem Speichern der Easee-Zugangsdaten
automatisch erstellt und konfiguriert. Im WebSocket-Client muss keine URL
eingetragen werden.
Der benötigte WebSocket-Client wird beim Erstellen des Gateways automatisch
und genau einmal angelegt. Nach dem Speichern der Easee-Zugangsdaten wird er
konfiguriert. Im WebSocket-Client muss keine URL eingetragen werden.
+14 -16
View File
@@ -37,6 +37,11 @@ class EaseeGateway extends IPSModule
'IPS_RequestAction(' . $this->InstanceID . ', "RefreshToken", 0);'
);
// Ein Splitter benötigt einen eigenen I/O-Parent. RequireParent()
// prüft zuerst die bestehende Verbindung und erzeugt daher beim
// Instanzieren keine zweite WebSocket-Verbindung.
$this->RequireParent(self::WEBSOCKET_MODULE_ID);
}
public function ApplyChanges()
@@ -88,28 +93,21 @@ class EaseeGateway extends IPSModule
$instance = IPS_GetInstance($this->InstanceID);
$parentID = (int)$instance["ConnectionID"];
if ($parentID > 0) {
$parent = IPS_GetInstance($parentID);
if ($parent["ModuleInfo"]["ModuleID"] === self::WEBSOCKET_MODULE_ID) {
return true;
}
IPS_DisconnectInstance($this->InstanceID);
}
$parentID = IPS_CreateInstance(self::WEBSOCKET_MODULE_ID);
if ($parentID <= 0) {
if ($parentID <= 0 && !$this->RequireParent(self::WEBSOCKET_MODULE_ID)) {
$this->SetLastError("WebSocket-Client konnte nicht erstellt werden");
return false;
}
IPS_SetName($parentID, "Easee SignalR WebSocket");
$objectParentID = IPS_GetParent($this->InstanceID);
if ($objectParentID > 0) {
IPS_SetParent($parentID, $objectParentID);
$instance = IPS_GetInstance($this->InstanceID);
$parentID = (int)$instance["ConnectionID"];
if ($parentID <= 0 || !IPS_InstanceExists($parentID)) {
$this->SetLastError("WebSocket-Client ist nicht verbunden");
return false;
}
if (!IPS_ConnectInstance($this->InstanceID, $parentID)) {
$this->SetLastError("WebSocket-Client konnte nicht verbunden werden");
$parent = IPS_GetInstance($parentID);
if ($parent["ModuleInfo"]["ModuleID"] !== self::WEBSOCKET_MODULE_ID) {
$this->SetLastError("Ungültige WebSocket-Schnittstelle");
return false;
}
+13 -9
View File
@@ -28,7 +28,7 @@ Das Gateway liefert:
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.
weiterhin die adaptive Soll-/Istleistungserkennung mit dem `Pending_Counter`.
Die Fahrzeugphasen werden anhand der tatsächlich gemessenen Leiterströme
erkannt; alte Phasenwerte werden beim Trennen oder Neuverbinden verworfen.
Während einer Ladepause mit 0 W bleibt die zuletzt erkannte Phasenanzahl
@@ -48,21 +48,25 @@ Go-e-Fahrzeugstatus. Die tatsächlich verwendeten Phasen werden aus den drei
gemessenen Strömen des `nrg`-Arrays bestimmt. Der maximale Ladestrom wird durch
die Stations-, Kabel- und Modulgrenze begrenzt.
`Auto fertig geladen` wird bei Go-E erst gesetzt, wenn die Ladung freigegeben
ist, der Fahrzeugstatus 4 anliegt und während 90 Sekunden weniger als 100 W
fließen. Bei einer durch das Modul angeforderten 0-W-Pause wird der
`Pending_Counter` zurückgesetzt. Die Easee-Erkennung bleibt davon unberührt.
Ist die angeforderte Ladeleistung während 90 Sekunden um den Faktor `1.11`
höher als die tatsächliche Leistung, wird der fahrzeugseitige Maximalstrom
aus dem Istwert neu berechnet. Fällt er unter 6 A, wird `Auto fertig geladen`
gesetzt. Bei einer durch das Modul angeforderten 0-W-Pause wird der
`Pending_Counter` zurückgesetzt. Zusätzlich muss bei Go-E die Ladung
freigegeben sein und der Fahrzeugstatus 4 anliegen.
### Smart-Me Pico
Typ 3 erkennt ein verbundenes Fahrzeug über den Pico-Ladestatus. Die
Phasenerkennung verwendet `CurrentL1`, `CurrentL2` und `CurrentL3` des
Smart-Me-Geräte-Endpunkts. Der maximale Stationsstrom wird direkt aus den
Pico-Ladedaten übernommen.
Pico-Ladedaten übernommen. Der fahrzeugseitige Maximalstrom und das Ladeende
werden weiterhin über den 90-Sekunden-Soll-/Istvergleich ermittelt.
Bei Typ 1 bis 3 entfällt die zeitbasierte Fahrzeug- und Phasenerkennung über
den `Pending_Counter`. Die Phasenzahl wird aktualisiert, sobald ein messbarer
Ladestrom fließt. Beim Abstecken werden die erkannten Phasen zurückgesetzt.
Bei Typ 1 bis 3 entfällt nur die frühere zeitbasierte Phasenerkennung. Die
Phasenzahl wird direkt aus den API-Messwerten aktualisiert, sobald ein
messbarer Ladestrom fließt. Beim Abstecken werden die erkannten Phasen
zurückgesetzt. Die adaptive Maximalstrom- und Ladeenderkennung bleibt aktiv.
Typ 4 bleibt unverändert.
+84 -53
View File
@@ -468,9 +468,11 @@ class Ladestation extends IPSModule
return $stationType === 5 || $stationType === 6;
}
private function UsesDirectStationDetection(int $stationType): bool
private function UsesAdaptiveCurrentDetection(int $stationType): bool
{
return in_array($stationType, [1, 2, 3, 5, 6], true);
// Easee (5/6) liefert den Ladeendestatus direkt über das Gateway.
// Alle anderen Typen benötigen weiterhin die Erkennung über Soll-/Istleistung.
return in_array($stationType, [1, 2, 3, 4], true);
}
private function ApplyEaseeGatewayResponse($response)
@@ -716,14 +718,15 @@ class Ladestation extends IPSModule
): bool {
$wasDetected = $this->GetValue("Car_detected");
$wasOnePhase = $this->GetValue("Is_1_ph");
$currentMax = (float)$this->GetValue("Max_Current");
if ($resetPendingCounter) {
$this->SetValue("Pending_Counter", 0);
}
$this->SetValue("Max_Current", $maxCurrent);
if (!$carDetected) {
$this->SetValue("Pending_Counter", 0);
$this->SetValue("Max_Current", $maxCurrent);
$this->SetValue("Car_detected", false);
$this->SetValue("Car_is_full", false);
$this->SetValue("Leistung_Delta", 0);
@@ -740,10 +743,18 @@ class Ladestation extends IPSModule
$this->SetValue("Is_1_ph", $isOnePhase);
}
$phaseChanged = $wasOnePhase !== $this->GetValue("Is_1_ph");
if (!$wasDetected || $phaseChanged || $currentMax <= 0) {
$this->SetValue("Max_Current", $maxCurrent);
} else {
// Einen vom Soll-/Istvergleich gelernten Fahrzeuggrenzwert nicht
// bei jedem API-Abruf wieder mit dem Stationsgrenzwert überschreiben.
$this->SetValue("Max_Current", min($currentMax, $maxCurrent));
}
$this->SetValue("Car_detected", true);
$this->SetValue("Car_is_full", $carIsFull);
$phaseChanged = $wasOnePhase !== $this->GetValue("Is_1_ph");
if (!$wasDetected || $phaseChanged) {
if ($this->GetValue("Is_1_ph")) {
$power = $this->GetValue("Mindestaldestrom") * 230;
@@ -813,7 +824,6 @@ class Ladestation extends IPSModule
is_numeric($chargingPowerWatts) &&
abs((float)$chargingPowerWatts) >= 100
) {
$this->SetValue("Pending_Counter", 0);
return false;
}
@@ -828,21 +838,15 @@ class Ladestation extends IPSModule
!is_numeric($chargingPowerWatts) ||
abs((float)$chargingPowerWatts) >= 100
) {
$this->SetValue("Pending_Counter", 0);
return false;
}
$counter = $this->GetValue("Pending_Counter") + 1;
$this->SetValue("Pending_Counter", $counter);
$interval = max(1, $this->ReadPropertyInteger("Interval"));
$requiredCycles = max(1, (int)ceil(90 / $interval));
if ($counter < $requiredCycles) {
return false;
}
$this->SetValue("Pending_Counter", 0);
return true;
// Der zentrale Soll-/Istvergleich setzt Max_Current nach 90 Sekunden.
// Unter 6 A entspricht dies der bisherigen Erkennung "Auto geladen".
$learnedMaxCurrent = (float)$this->GetValue("Max_Current");
return $this->GetValue("Car_detected") &&
$learnedMaxCurrent > 0 &&
$learnedMaxCurrent < 6;
}
private function DetectGoECar(int $stationType): bool
@@ -862,6 +866,10 @@ class Ladestation extends IPSModule
}
$this->SetValue("Fahrzeugstatus", $carState);
$this->SetBuffer(
"GoEChargingEnabledFromStatus",
$this->IsGoEChargingEnabled($data, $stationType) ? "1" : "0"
);
$isOnePhase = null;
$chargingPowerWatts = null;
@@ -887,18 +895,23 @@ class Ladestation extends IPSModule
}
$carDetected = in_array($carState, [2, 3, 4, 5], true);
$stationMaxCurrent = $this->GetGoEMaxCurrent($data);
$wasFull = $this->GetValue("Car_is_full");
$carIsFull = $carDetected && $this->DetectGoEFullCharge(
$data,
$stationType,
$carState,
$chargingPowerWatts
);
if ($wasFull && !$carIsFull) {
$this->SetValue("Max_Current", $stationMaxCurrent);
}
return $this->ApplyDirectStationDetection(
$carDetected,
$carIsFull,
$isOnePhase,
$this->GetGoEMaxCurrent($data),
$stationMaxCurrent,
false
);
}
@@ -932,10 +945,12 @@ class Ladestation extends IPSModule
$chargingPower = $chargingData["ActiveChargingPower"] ??
$chargingData["activeChargingPower"] ?? null;
$chargingPowerWatts = null;
if (is_numeric($chargingPower)) {
$chargingPowerWatts = (float)$chargingPower * 1000;
$this->SetValue(
"Ladeleistung_Effektiv",
round((float)$chargingPower * 1000)
round($chargingPowerWatts)
);
}
@@ -968,11 +983,22 @@ class Ladestation extends IPSModule
}
}
$carDetected = in_array($stationState, [2, 3, 4, 6], true);
$carIsFull = $this->GetValue("Car_is_full");
if (!$carIsFull) {
$learnedMaxCurrent = (float)$this->GetValue("Max_Current");
$carIsFull = $carDetected &&
$this->GetValue("Car_detected") &&
$learnedMaxCurrent > 0 &&
$learnedMaxCurrent < 6;
}
return $this->ApplyDirectStationDetection(
in_array($stationState, [2, 3, 4, 6], true),
false,
$carDetected,
$carIsFull,
$isOnePhase,
$maxCurrent
$maxCurrent,
false
);
}
@@ -1475,43 +1501,48 @@ class Ladestation extends IPSModule
// PowerSteps in der RegisterVariable speichern
SetValue($this->GetIDForIdent("PowerSteps"), json_encode($powerSteps));
// Rückgabe der Powersteps
if (!$this->UsesDirectStationDetection($this->ReadPropertyInteger("Ladestation"))) {
$counter = $this->GetValue("Pending_Counter");
$stationType = $this->ReadPropertyInteger("Ladestation");
if ($this->UsesAdaptiveCurrentDetection($stationType)) {
$requestedPower = max(0, (float)$this->GetValue("Aktuelle_Leistung"));
$actualPower = abs((float)$this->GetValue("Ladeleistung_Effektiv"));
$availableSteps = $this->Get_Array_From_Current(
$this->GetValue("Is_1_ph"),
$this->GetValue("Max_Current"),
$this->GetValue("Aktuelle_Leistung"),
$this->GetValue("IsTimerActive_Null_Timer")
);
$maxAvailablePower = count($availableSteps) > 0
? max($availableSteps)
: 0;
$maxPowerStep = count($powerSteps) > 0 ? max($powerSteps) : 0;
$goEEnabled = !in_array($stationType, [1, 2], true) ||
$this->GetBuffer("GoEChargingEnabledFromStatus") === "1";
$canEvaluate = $ladebereit &&
$this->GetValue("Car_detected") &&
!$this->GetValue("Car_is_full") &&
$requestedPower > 0 &&
$maxPowerStep > 0 &&
$goEEnabled;
if($this->GetValue("Aktuelle_Leistung")>(1.11*$this->GetValue("Ladeleistung_Effektiv"))){
$this->SetValue("Pending_Counter", $counter+1);
}elseif(max($this->Get_Array_From_Current($this->GetValue("Is_1_ph"),$this->GetValue("Max_Current"), $this->GetValue("Aktuelle_Leistung"), $this->GetValue("IsTimerActive_Null_Timer")))<(1.11*$this->GetValue("Ladeleistung_Effektiv"))){ // diesen elseif ggf wieder rauslöschen
$this->SetValue("Pending_Counter", $counter+1);
}
else{
$this->SetValue("Pending_Counter", 0);
}
if($counter>(90/($this->ReadPropertyInteger("Interval")))){
$this->SetValue("Pending_Counter", 0);
if((max(json_decode($this->GetValue("PowerSteps")))) >0){
if($this->GetValue("Aktuelle_Leistung")>(1.11*$this->GetValue("Ladeleistung_Effektiv"))) {
$this->Calc_Max_Current($this->GetValue("Is_1_ph"));
$requestedMismatch = $requestedPower > (1.11 * $actualPower);
$availableMismatch = $maxAvailablePower < (1.11 * $actualPower);
if ($canEvaluate && ($requestedMismatch || $availableMismatch)) {
$counter = $this->GetValue("Pending_Counter") + 1;
$this->SetValue("Pending_Counter", $counter);
$interval = max(1, $this->ReadPropertyInteger("Interval"));
$requiredCycles = max(1, (int)ceil(90 / $interval));
if ($counter >= $requiredCycles) {
$this->SetValue("Pending_Counter", 0);
if ($requestedMismatch) {
$this->Calc_Max_Current($this->GetValue("Is_1_ph"));
}
}
} else {
$this->SetValue("Pending_Counter", 0);
}
} elseif (!in_array(
$this->ReadPropertyInteger("Ladestation"),
[1, 2],
true
)) {
} else {
$this->SetValue("Pending_Counter", 0);
}
+15 -9
View File
@@ -28,7 +28,7 @@ Das Gateway liefert:
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.
weiterhin die adaptive Soll-/Istleistungserkennung mit dem `Pending_Counter`.
Die Fahrzeugphasen werden anhand der tatsächlich gemessenen Leiterströme
erkannt; alte Phasenwerte werden beim Trennen oder Neuverbinden verworfen.
Während einer Ladepause mit 0 W bleibt die zuletzt erkannte Phasenanzahl
@@ -48,21 +48,25 @@ Go-e-Fahrzeugstatus. Die tatsächlich verwendeten Phasen werden aus den drei
gemessenen Strömen des `nrg`-Arrays bestimmt. Der maximale Ladestrom wird durch
die Stations-, Kabel- und Modulgrenze begrenzt.
`Auto fertig geladen` wird bei Go-E erst gesetzt, wenn die Ladung freigegeben
ist, der Fahrzeugstatus 4 anliegt und während 90 Sekunden weniger als 100 W
fließen. Bei einer durch das Modul angeforderten 0-W-Pause wird der
`Pending_Counter` zurückgesetzt. Die Easee-Erkennung bleibt davon unberührt.
Ist die angeforderte Ladeleistung während 90 Sekunden um den Faktor `1.11`
höher als die tatsächliche Leistung, wird der fahrzeugseitige Maximalstrom
aus dem Istwert neu berechnet. Fällt er unter 6 A, wird `Auto fertig geladen`
gesetzt. Bei einer durch das Modul angeforderten 0-W-Pause wird der
`Pending_Counter` zurückgesetzt. Zusätzlich muss bei Go-E die Ladung
freigegeben sein und der Fahrzeugstatus 4 anliegen.
### Smart-Me Pico
Typ 3 erkennt ein verbundenes Fahrzeug über den Pico-Ladestatus. Die
Phasenerkennung verwendet `CurrentL1`, `CurrentL2` und `CurrentL3` des
Smart-Me-Geräte-Endpunkts. Der maximale Stationsstrom wird direkt aus den
Pico-Ladedaten übernommen.
Pico-Ladedaten übernommen. Der fahrzeugseitige Maximalstrom und das Ladeende
werden weiterhin über den 90-Sekunden-Soll-/Istvergleich ermittelt.
Bei Typ 1 bis 3 entfällt die zeitbasierte Fahrzeug- und Phasenerkennung über
den `Pending_Counter`. Die Phasenzahl wird aktualisiert, sobald ein messbarer
Ladestrom fließt. Beim Abstecken werden die erkannten Phasen zurückgesetzt.
Bei Typ 1 bis 3 entfällt nur die frühere zeitbasierte Phasenerkennung. Die
Phasenzahl wird direkt aus den API-Messwerten aktualisiert, sobald ein
messbarer Ladestrom fließt. Beim Abstecken werden die erkannten Phasen
zurückgesetzt. Die adaptive Maximalstrom- und Ladeenderkennung bleibt aktiv.
Typ 4 bleibt unverändert.
@@ -75,3 +79,5 @@ Typ 4 bleibt unverändert.
`Schnittstelle ändern` die gewünschte Gateway-Instanz auswählen.
Mehrere Easee-Ladestationen desselben Kontos verwenden gemeinsam ein Gateway.
Beim Erstellen einer weiteren Instanz wird ein vorhandenes Gateway automatisch
verwendet; es wird keine zweite Parent-Verbindung erzeugt.
+93 -60
View File
@@ -113,6 +113,10 @@ class Ladestation_v2 extends IPSModule
$this->RegisterVariableInteger("Mindestaldestrom", "Mindestaldestrom", "", 0);
$this->EnableAction("Mindestaldestrom");
// Vorhandenes Gateway verwenden; nur wenn keines existiert, wird eines
// erstellt. ConnectParent() ist auch bei bereits gesetztem Parent sicher.
$this->ConnectParent(self::EASEE_GATEWAY_MODULE_ID);
}
public function Migrate($JSONData)
@@ -286,14 +290,12 @@ class Ladestation_v2 extends IPSModule
$instance = IPS_GetInstance($this->InstanceID);
$parentID = (int)$instance["ConnectionID"];
// Eine in Version 1.2/1.3 gespeicherte Gateway-Auswahl wieder als
// normale IP-Symcon-Schnittstelle verbinden.
// Bei einer aktualisierten, bisher noch unverbundenen Bestandsinstanz
// die normale IP-Symcon-Parent-Verbindung nachziehen.
if ($parentID <= 0) {
$storedGatewayID = $this->GetConfiguredEaseeGatewayID();
if ($storedGatewayID > 0) {
IPS_ConnectInstance($this->InstanceID, $storedGatewayID);
$parentID = $storedGatewayID;
}
$this->ConnectParent(self::EASEE_GATEWAY_MODULE_ID);
$instance = IPS_GetInstance($this->InstanceID);
$parentID = (int)$instance["ConnectionID"];
}
if ($usesEaseeGateway && $this->IsEaseeGatewayInstance($parentID)) {
@@ -486,9 +488,11 @@ class Ladestation_v2 extends IPSModule
return $stationType === 5 || $stationType === 6;
}
private function UsesDirectStationDetection(int $stationType): bool
private function UsesAdaptiveCurrentDetection(int $stationType): bool
{
return in_array($stationType, [1, 2, 3, 5, 6], true);
// Easee (5/6) liefert den Ladeendestatus direkt über das Gateway.
// Alle anderen Typen benötigen weiterhin die Erkennung über Soll-/Istleistung.
return in_array($stationType, [1, 2, 3, 4], true);
}
private function ApplyEaseeGatewayResponse($response)
@@ -734,14 +738,15 @@ class Ladestation_v2 extends IPSModule
): bool {
$wasDetected = $this->GetValue("Car_detected");
$wasOnePhase = $this->GetValue("Is_1_ph");
$currentMax = (float)$this->GetValue("Max_Current");
if ($resetPendingCounter) {
$this->SetValue("Pending_Counter", 0);
}
$this->SetValue("Max_Current", $maxCurrent);
if (!$carDetected) {
$this->SetValue("Pending_Counter", 0);
$this->SetValue("Max_Current", $maxCurrent);
$this->SetValue("Car_detected", false);
$this->SetValue("Car_is_full", false);
$this->SetValue("Leistung_Delta", 0);
@@ -758,10 +763,18 @@ class Ladestation_v2 extends IPSModule
$this->SetValue("Is_1_ph", $isOnePhase);
}
$phaseChanged = $wasOnePhase !== $this->GetValue("Is_1_ph");
if (!$wasDetected || $phaseChanged || $currentMax <= 0) {
$this->SetValue("Max_Current", $maxCurrent);
} else {
// Einen vom Soll-/Istvergleich gelernten Fahrzeuggrenzwert nicht
// bei jedem API-Abruf wieder mit dem Stationsgrenzwert überschreiben.
$this->SetValue("Max_Current", min($currentMax, $maxCurrent));
}
$this->SetValue("Car_detected", true);
$this->SetValue("Car_is_full", $carIsFull);
$phaseChanged = $wasOnePhase !== $this->GetValue("Is_1_ph");
if (!$wasDetected || $phaseChanged) {
if ($this->GetValue("Is_1_ph")) {
$power = $this->GetValue("Mindestaldestrom") * 230;
@@ -831,7 +844,6 @@ class Ladestation_v2 extends IPSModule
is_numeric($chargingPowerWatts) &&
abs((float)$chargingPowerWatts) >= 100
) {
$this->SetValue("Pending_Counter", 0);
return false;
}
@@ -846,21 +858,15 @@ class Ladestation_v2 extends IPSModule
!is_numeric($chargingPowerWatts) ||
abs((float)$chargingPowerWatts) >= 100
) {
$this->SetValue("Pending_Counter", 0);
return false;
}
$counter = $this->GetValue("Pending_Counter") + 1;
$this->SetValue("Pending_Counter", $counter);
$interval = max(1, $this->ReadPropertyInteger("Interval"));
$requiredCycles = max(1, (int)ceil(90 / $interval));
if ($counter < $requiredCycles) {
return false;
}
$this->SetValue("Pending_Counter", 0);
return true;
// Der zentrale Soll-/Istvergleich setzt Max_Current nach 90 Sekunden.
// Unter 6 A entspricht dies der bisherigen Erkennung "Auto geladen".
$learnedMaxCurrent = (float)$this->GetValue("Max_Current");
return $this->GetValue("Car_detected") &&
$learnedMaxCurrent > 0 &&
$learnedMaxCurrent < 6;
}
private function DetectGoECar(int $stationType): bool
@@ -880,6 +886,10 @@ class Ladestation_v2 extends IPSModule
}
$this->SetValue("Fahrzeugstatus", $carState);
$this->SetBuffer(
"GoEChargingEnabledFromStatus",
$this->IsGoEChargingEnabled($data, $stationType) ? "1" : "0"
);
$isOnePhase = null;
$chargingPowerWatts = null;
@@ -905,18 +915,23 @@ class Ladestation_v2 extends IPSModule
}
$carDetected = in_array($carState, [2, 3, 4, 5], true);
$stationMaxCurrent = $this->GetGoEMaxCurrent($data);
$wasFull = $this->GetValue("Car_is_full");
$carIsFull = $carDetected && $this->DetectGoEFullCharge(
$data,
$stationType,
$carState,
$chargingPowerWatts
);
if ($wasFull && !$carIsFull) {
$this->SetValue("Max_Current", $stationMaxCurrent);
}
return $this->ApplyDirectStationDetection(
$carDetected,
$carIsFull,
$isOnePhase,
$this->GetGoEMaxCurrent($data),
$stationMaxCurrent,
false
);
}
@@ -950,10 +965,12 @@ class Ladestation_v2 extends IPSModule
$chargingPower = $chargingData["ActiveChargingPower"] ??
$chargingData["activeChargingPower"] ?? null;
$chargingPowerWatts = null;
if (is_numeric($chargingPower)) {
$chargingPowerWatts = (float)$chargingPower * 1000;
$this->SetValue(
"Ladeleistung_Effektiv",
round((float)$chargingPower * 1000)
round($chargingPowerWatts)
);
}
@@ -986,11 +1003,22 @@ class Ladestation_v2 extends IPSModule
}
}
$carDetected = in_array($stationState, [2, 3, 4, 6], true);
$carIsFull = $this->GetValue("Car_is_full");
if (!$carIsFull) {
$learnedMaxCurrent = (float)$this->GetValue("Max_Current");
$carIsFull = $carDetected &&
$this->GetValue("Car_detected") &&
$learnedMaxCurrent > 0 &&
$learnedMaxCurrent < 6;
}
return $this->ApplyDirectStationDetection(
in_array($stationState, [2, 3, 4, 6], true),
false,
$carDetected,
$carIsFull,
$isOnePhase,
$maxCurrent
$maxCurrent,
false
);
}
@@ -1486,43 +1514,48 @@ class Ladestation_v2 extends IPSModule
// PowerSteps in der RegisterVariable speichern
SetValue($this->GetIDForIdent("PowerSteps"), json_encode($powerSteps));
// Rückgabe der Powersteps
if (!$this->UsesDirectStationDetection($this->ReadPropertyInteger("Ladestation"))) {
$counter = $this->GetValue("Pending_Counter");
$stationType = $this->ReadPropertyInteger("Ladestation");
if ($this->UsesAdaptiveCurrentDetection($stationType)) {
$requestedPower = max(0, (float)$this->GetValue("Aktuelle_Leistung"));
$actualPower = abs((float)$this->GetValue("Ladeleistung_Effektiv"));
$availableSteps = $this->Get_Array_From_Current(
$this->GetValue("Is_1_ph"),
$this->GetValue("Max_Current"),
$this->GetValue("Aktuelle_Leistung"),
$this->GetValue("IsTimerActive_Null_Timer")
);
$maxAvailablePower = count($availableSteps) > 0
? max($availableSteps)
: 0;
$maxPowerStep = count($powerSteps) > 0 ? max($powerSteps) : 0;
$goEEnabled = !in_array($stationType, [1, 2], true) ||
$this->GetBuffer("GoEChargingEnabledFromStatus") === "1";
$canEvaluate = $ladebereit &&
$this->GetValue("Car_detected") &&
!$this->GetValue("Car_is_full") &&
$requestedPower > 0 &&
$maxPowerStep > 0 &&
$goEEnabled;
if($this->GetValue("Aktuelle_Leistung")>(1.11*$this->GetValue("Ladeleistung_Effektiv"))){
$this->SetValue("Pending_Counter", $counter+1);
}elseif(max($this->Get_Array_From_Current($this->GetValue("Is_1_ph"),$this->GetValue("Max_Current"), $this->GetValue("Aktuelle_Leistung"), $this->GetValue("IsTimerActive_Null_Timer")))<(1.11*$this->GetValue("Ladeleistung_Effektiv"))){ // diesen elseif ggf wieder rauslöschen
$this->SetValue("Pending_Counter", $counter+1);
}
else{
$this->SetValue("Pending_Counter", 0);
}
if($counter>(90/($this->ReadPropertyInteger("Interval")))){
$this->SetValue("Pending_Counter", 0);
if((max(json_decode($this->GetValue("PowerSteps")))) >0){
if($this->GetValue("Aktuelle_Leistung")>(1.11*$this->GetValue("Ladeleistung_Effektiv"))) {
$this->Calc_Max_Current($this->GetValue("Is_1_ph"));
$requestedMismatch = $requestedPower > (1.11 * $actualPower);
$availableMismatch = $maxAvailablePower < (1.11 * $actualPower);
if ($canEvaluate && ($requestedMismatch || $availableMismatch)) {
$counter = $this->GetValue("Pending_Counter") + 1;
$this->SetValue("Pending_Counter", $counter);
$interval = max(1, $this->ReadPropertyInteger("Interval"));
$requiredCycles = max(1, (int)ceil(90 / $interval));
if ($counter >= $requiredCycles) {
$this->SetValue("Pending_Counter", 0);
if ($requestedMismatch) {
$this->Calc_Max_Current($this->GetValue("Is_1_ph"));
}
}
} else {
$this->SetValue("Pending_Counter", 0);
}
} elseif (!in_array(
$this->ReadPropertyInteger("Ladestation"),
[1, 2],
true
)) {
} else {
$this->SetValue("Pending_Counter", 0);
}
+1 -1
View File
@@ -2,7 +2,7 @@
"id": "{89CAF37C-8E6E-5312-8195-6DA8AB7E5E70}",
"name": "Manager",
"author": "Daniel Haefliger",
"url": "https://git.belevo.ch/dh/Symcon_Belevo_Energiemanagement",
"url": "https://git.belevo.ch/dh/Symcon_Belevo_Energiemanagement_testing",
"compatibility": {
"version": "8.0"
},