3.0 KiB
SMA-2 - each inverter is reached through a driver
Status: for review. Tests: test_sma2_driver.py. Source: SMA-9 report
section 1.1. A pure refactor: no behaviour change for GoodWe, no change to a
command, a log line or a sentence the add-on shows.
Every place that read or steered an inverter used the GoodWe ESPHome entities
directly, so a second make meant touching all of them. app/drivers.py now
holds one Driver per roster entry (Inverter.driver): configured(),
actuator_id(), limits(), read(), write(), release(), probe(), and
link_stale_s, batt_bound, settle_s, brand, words. GoodWeEsphomeDriver
makes the same calls in the same order as the code it replaced; its
release() is write(0).
Moved to the driver: the SoC and power read (_read_unit), the write
(_write_unit, still under the SAFETY-28 gate, the clamp, shadow mode and the
write budget), the device range (run_control, amain, the settings panel),
liveness and its window (has_writer, is_live, link_note), the freshness
bound, the status rows' "is a source set" test, rule 2's per-unit range check
and SAFETY-28's census. Not moved: the clamp, the gate, the heartbeat and
command_site_zero(); stop is still 0 W for every unit, and nothing calls
release() yet (SMA-10). settle_s and the control constants are not read
from the driver yet either: with only GoodWe they would change nothing.
The seam is not TCP-shaped. The census asks each entry's driver for its
actuator id: the setpoint entity for GoodWe, host:port:unit_id for a driver
reached over a socket, so two units behind one gateway are two actuators and
one unit named twice is the SAFETY-28 refusal. The census still counts every
setpoint_entity key as before and adds the driver's own actuator to it (parity
with 23ff9d0 on 349 option shapes is a test). The driver binds its Home
Assistant on first use by the Controller, so a unit added later is wired too.
Schema. The brief says "setpoint_entity becomes optional" (SMA-2, "Schema per
inverter entry"; SMA-9 section 1.1): it is the GoodWe driver's own key, so a
driver reached by host and port has none. setpoint_entity is optional per entry
in config.yaml; rule 9(d) still refuses a GoodWe entry without it, with the same
sentence (test_sma2_driver.py part 6), beside driver (only goodwe_esphome),
host, port, unit_id, maintenance. The last four are checked for shape
and not read. The Supervisor shape probe was re-run (section K).
Checked against 23ff9d0: replay digests and a log of every Home Assistant
call are byte-identical at N=1 and N=2; the TEL-07 announce diff is 0/0/0; a
fake driver beside a GoodWe unit allocates, grades, drops and publishes per
unit; a call site that goes round the seam is caught.
Per-entry keys the page does not draw are listed in uilayout.ROSTER_HIDDEN;
test_uilayout and test_sma2_driver fail for a key that is neither a card field
nor hidden, and a save through the page keeps them (a test).