Fix: Wallbox-Read resilient gegen IllegalAddress, Relais-Matrix ergänzt

- wallbox_client: Bei Reg-Fehler Range überspringen statt komplett abbrechen
  → Meter-Daten kommen weiter wenn EVSE-Block (0x0060) nicht verfügbar
- wallbox_client: set_current() schreibt jetzt auch EMS_RELAIS_REG (0x00A1)
  mit korrekter Phasen-Bitmaske (1→0x0001, 2→0x0003, 3→0x0007)
- ems_controller: phases wird an set_current() und Zwangsladen übergeben

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
retr0
2026-04-28 12:17:52 +02:00
parent a09bbdd25d
commit 30f2667589
2 changed files with 20 additions and 12 deletions
+18 -10
View File
@@ -11,11 +11,14 @@ from inverters import Inverter, Sensor
log = logging.getLogger(__name__)
SLAVE = 0 # Kathrein: Unit-ID 0 (Broadcast)
EMS_CTRL_REG = 0x00A0
EMS_CTRL_REG = 0x00A0
EMS_RELAIS_REG = 0x00A1
EMS_CURRENT_REG = 0x00A2
EMS_ENABLE = 0x8000
MIN_CURRENT_MA = 6000
MAX_CURRENT_MA = 32000
EMS_ENABLE = 0x8000
MIN_CURRENT_MA = 6000
MAX_CURRENT_MA = 32000
_PHASE_MASK = {1: 0x0001, 2: 0x0003, 3: 0x0007}
class WallboxReader:
@@ -45,21 +48,22 @@ class WallboxReader:
return None
reg_cache: Dict[int, int] = {}
any_ok = False
for start, length in inverter.read_ranges:
try:
result = self._client.read_holding_registers(start, count=length, slave=SLAVE)
if result.isError():
log.error("[Wallbox] FC03 Fehler Reg 0x%04X: %s", start, result)
self._disconnect()
return None
log.warning("[Wallbox] FC03 Reg 0x%04X nicht verfügbar: %s", start, result)
continue
for i, val in enumerate(result.registers):
reg_cache[start + i] = val
any_ok = True
except ModbusException as e:
log.error("[Wallbox] Modbus Ausnahme: %s", e)
self._disconnect()
return None
return _extract(inverter.sensors, reg_cache)
return _extract(inverter.sensors, reg_cache) if any_ok else None
def enable_ems(self) -> bool:
if not self._connect():
@@ -71,16 +75,20 @@ class WallboxReader:
log.error("[Wallbox] EMS enable Fehler: %s", e)
return False
def set_current(self, ma: int) -> bool:
def set_current(self, ma: int, phases: int = 3) -> bool:
"""Ladestrom setzen. ma=0 → Pause, ma=0xFFFF → Abbruch."""
if not self._connect():
return False
val = 0 if ma == 0 else max(MIN_CURRENT_MA, min(MAX_CURRENT_MA, ma))
relais = _PHASE_MASK.get(phases, 0x0007)
try:
r = self._client.write_register(EMS_RELAIS_REG, relais, slave=SLAVE)
if r.isError():
log.warning("[Wallbox] Relais-Matrix Fehler: %s", r)
r = self._client.write_register(EMS_CURRENT_REG, val, slave=SLAVE)
ok = not r.isError()
if ok:
log.info("[Wallbox] Strom gesetzt: %d mA", val)
log.info("[Wallbox] Strom gesetzt: %d mA (%d Phase(n))", val, phases)
return ok
except ModbusException as e:
log.error("[Wallbox] set_current Fehler: %s", e)