Fix: EMS Ladestrom = PV-Überschuss + aktuelle Wallbox-Leistung
Goodwe misst Überschuss NACH Wallbox-Verbrauch. EMS muss deshalb bestehende Ladeleistung (total_power) addieren um Gesamtbudget zu kennen: new_current = (surplus + wallbox_power) / (230V × phases) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,16 +58,22 @@ class EmsController:
|
|||||||
t += timedelta(days=1)
|
t += timedelta(days=1)
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def _surplus_to_ma(self, surplus_w: float) -> int:
|
def _surplus_to_ma(self, surplus_w: float, wallbox_w: float = 0.0) -> int:
|
||||||
"""PV-Überschuss in Watt → Ladestrom in mA (pro Phase)."""
|
"""Gesamte verfügbare PV-Leistung → Ladestrom in mA (pro Phase).
|
||||||
current_a = surplus_w / (VOLTAGE_V * self.phases)
|
surplus_w: noch ins Netz eingespeister Überschuss
|
||||||
|
wallbox_w: aktuell von der Wallbox gezogene Leistung
|
||||||
|
Summe = gesamt verfügbar für Laden."""
|
||||||
|
total_w = surplus_w + wallbox_w
|
||||||
|
current_a = total_w / (VOLTAGE_V * self.phases)
|
||||||
ma = int(current_a * 1000)
|
ma = int(current_a * 1000)
|
||||||
return max(6000, min(32000, ma))
|
return max(6000, min(32000, ma))
|
||||||
|
|
||||||
def update(self, wallbox_reader, pv_surplus_w: float, charging_state: int) -> str:
|
def update(self, wallbox_reader, pv_surplus_w: float, charging_state: int,
|
||||||
|
wallbox_power_w: float = 0.0) -> str:
|
||||||
"""
|
"""
|
||||||
Wird vom Poll-Loop aufgerufen.
|
Wird vom Poll-Loop aufgerufen.
|
||||||
pv_surplus_w: positiv = PV exportiert ins Netz (verfügbar für Laden)
|
pv_surplus_w: positiv = PV exportiert ins Netz (verbleibender Überschuss)
|
||||||
|
wallbox_power_w: aktuell von der Wallbox gezogene Leistung (aus Meter-Daten)
|
||||||
Gibt eine kurze Status-Beschreibung zurück.
|
Gibt eine kurze Status-Beschreibung zurück.
|
||||||
"""
|
"""
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -98,9 +104,10 @@ class EmsController:
|
|||||||
if has_pv:
|
if has_pv:
|
||||||
self._no_pv_since = None
|
self._no_pv_since = None
|
||||||
self._forced_charging = False
|
self._forced_charging = False
|
||||||
ma = self._surplus_to_ma(pv_surplus_w)
|
ma = self._surplus_to_ma(pv_surplus_w, wallbox_power_w)
|
||||||
|
total_w = pv_surplus_w + wallbox_power_w
|
||||||
wallbox_reader.set_current(ma, self.phases)
|
wallbox_reader.set_current(ma, self.phases)
|
||||||
return f"PV-Laden {ma // 1000:.1f}A ({pv_surplus_w:.0f}W)"
|
return f"PV-Laden {ma / 1000:.1f}A ({total_w:.0f}W, Überschuss {pv_surplus_w:.0f}W)"
|
||||||
|
|
||||||
# Kein PV
|
# Kein PV
|
||||||
if self._no_pv_since is None:
|
if self._no_pv_since is None:
|
||||||
|
|||||||
@@ -228,7 +228,8 @@ def _poll_loop(inv_cfg: Dict[str, Any], stop: threading.Event):
|
|||||||
# 0x0060 manchmal nicht lesbar → 1 (EV Connected) annehmen,
|
# 0x0060 manchmal nicht lesbar → 1 (EV Connected) annehmen,
|
||||||
# damit EMS aktiviert; Wallbox ignoriert Befehle wenn kein Auto da
|
# damit EMS aktiviert; Wallbox ignoriert Befehle wenn kein Auto da
|
||||||
charging_state = int(values.get("charging_state", 1))
|
charging_state = int(values.get("charging_state", 1))
|
||||||
ems_status = ems.update(reader, pv_surplus, charging_state)
|
wallbox_power = values.get("total_power", 0.0)
|
||||||
|
ems_status = ems.update(reader, pv_surplus, charging_state, wallbox_power)
|
||||||
values["ems_status_code"] = float(charging_state)
|
values["ems_status_code"] = float(charging_state)
|
||||||
log.info("[%s] EMS: %s | PV-Überschuss: %.0fW", inv_id, ems_status, pv_surplus)
|
log.info("[%s] EMS: %s | PV-Überschuss: %.0fW", inv_id, ems_status, pv_surplus)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user