SMA-2: each inverter is reached through a driver; GoodWe behaviour unchanged
checks / unit (pull_request) Successful in 23m14s
infra-pin / fresh (pull_request) Successful in 2s

app/drivers.py holds one Driver per roster entry (configured, actuator_id,
limits, read, write, release, probe, link_stale_s, batt_bound, settle_s, brand,
words). GoodWeEsphomeDriver makes the calls the code it replaced made, in the
same order. Inverter gets driver; has_writer, is_live and link_note read it. The
SoC/power read, the write, the device range (run_control, amain, the settings
panel), rule 2 per unit and the SAFETY-28 census go through it.

setpoint_entity is optional per entry beside driver, host, port, unit_id and
maintenance; only goodwe_esphome is selectable, the rest are checked and unused.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
glenn schrooyen
2026-11-07 11:28:47 +01:00
co-authored by Claude
parent 23ff9d0920
commit e56eeef8f0
18 changed files with 1238 additions and 65 deletions
+3 -1
View File
@@ -51,8 +51,10 @@ def coverage_problems(order, nested):
out += [f"{k} is not in config.yaml" for k in
set(placed) | set(L.DERIVED) | set(L.HIDDEN) if k not in order]
sub = [k.split(".", 1)[1] for k in KEYS if k.startswith("inverters.")]
# SMA-2: a per-entry key may instead be listed in L.ROSTER_HIDDEN (the
# driver keys the page does not draw), and then it must not also be a field.
out += [f"inverters.{k} has no card field" for k in nested.get("inverters", [])
if sub.count(k) != 1]
if sub.count(k) + (k in L.ROSTER_HIDDEN) != 1]
out += [f"inverters.{k} is not in config.yaml" for k in sub
if k not in nested.get("inverters", [])]
return out