Repository navigation
feat(discovery): inverter records carry entities, capabilities and Predbat-named ratings (observe-only, piece 1) - #5228
Conversation
…and ratings Spec for piece 1 of moving automatic configuration into the coordinator: entities becomes the full per-device settings map (rw/r), capabilities an INVERTER_DEF-shaped bool dict, ratings keyed by Predbat setting name, and protocol detail derived from the entity map. Sections 2 and 3 are proposals awaiting review. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…uestions Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ection 3 keeps automatic_config untouched and settles Solis reserve Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s derive from inverter_mode; dummied settings stay out of entities Checking inverter.py while writing the plan: num_load_entities is read at inverter.py:1523 (it adds load_power_1.. into the load), so it is derived from the entity map; has_rest_api is the unread one. has_ge_inverter_mode / has_ge_eco_toggle are True on the GE/GEC rows, so they derive from the inverter_mode entity's domain rather than defaulting to False. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ates over it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…the piece-3 findings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ry (piece 1) Ten tasks: coordinator vocabulary and inverter_definition(), shared contract checks, the seven reporters, and retiring the transitional capability list. Every code block was verified on throwaway prototype branches: the combined branch passes the quick suite. Spec gains the soc_max reading of D14 and the no-HA-filter convention for inverter entities. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…scovery-record-vocabulary
…d inverter_definition() Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r reporters Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…edbat-named ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tity map and device-reported ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…edbat-named ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…redbat-named ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d Predbat-named ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nd Predbat-named ratings; GEC/GEE soc_units % Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d entities and Predbat-named ratings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ma 2 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…leep is 10 on the GE types; charge_rate_percent means power control Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Question about how the later pieces will handle inverters that have no discovery reporter. I'm running a LuxPower LXP 3600ACS through the LuxPower HA integration, configured manually in inverters: []
observations:
conflicts: []
resulting_config:
num_inverters: 1
inverter_type: '#5f01158e'Everything works fine today since this is observe-only. My question is for when discovery starts driving configuration: will a manual Happy to share the full (anonymised) discovery output if it helps. |
Piece 1 of moving automatic inverter configuration into the discovery coordinator. Observe-only: every inverter reporter's discovery record now carries enough to rebuild its
INVERTER_DEFrow and to reproduce what itsautomatic_config()binds, but nothing configures from it yet. Noautomatic_config(),inverter.pyor write path changes; each reporter'sautomatic_config()was checked byte-identical before commit.Design:
docs/superpowers/specs/2026-09-24-discovery-inverter-record-vocabulary-design.md(decisions D1-D15). Plan:docs/superpowers/plans/2026-09-24-discovery-inverter-record-vocabulary.md.What changes
coordinator.py, schema_version 1 -> 2)entities: every setting automatic configuration binds for the device, keyed by Predbat setting name. Each descriptor needsaccess(rwPredbat writes /rPredbat reads) and exactly one ofentity_idor a fixedvalue;invertreplaces the*_power_invertsettings.capabilities: a dict of the sevenINVERTER_DEFbehaviour keys (support_charge_freeze,support_discharge_freeze,support_feedin_first,can_span_midnight,charge_discharge_with_rate,charge_control_immediate,target_soc_used_for_discharge) -> bool. Replaces the old token list.ratingsunder Predbat setting names:inverter_limit,export_limit(configured grid export cap),import_limit,battery_rate_max,soc_max,battery_min_soc. Only figures the device reports - a value Predbat derives or the user overrides is an entity, not a rating (D14).inverter_definition(record, write_and_poll_sleep, base=None): a pure function that rebuilds anINVERTER_DEF-shaped dict from a record. Thehas_*presence flags, time formats, SoC units, charge-control mode and load-entity count are derived from the entity map rather than stated twice. Never mutatesINVERTER_DEF.automatic_ignore_pv(D11), and PV-only devices carry read-onlypv_power/pv_today(D12).tests/discovery_contract.py: shared checks every reporter's tests run - completeness (the record alone, with no row as a base, rebuilds itsINVERTER_DEFrow) and agreement in both directions (the record binds exactly what the unchangedautomatic_config()binds, apart from named per-device/opt-out extras).INVERTER_DEFchange: GEC and GEEsoc_units"kWh"->"%"(GE Cloud bindssoc_percent;inv_soc_unitsis never read). GE-familyclock_time_formatis left alone because those rows also serve the GivTCP add-on and GE Cloud templates; the GivTCP/GE Cloud records describe the ISO format their sensors really publish, with a named exception in the completeness test (D13).ComponentBase.WRITE_AND_POLL_SLEEP(2; GivTCP and GE Cloud 10) - read only by tests until piece 3.docs/discovery-catalogue.mdand the catalogue design spec updated for schema 2; a debug-journal entry on a worktree trap (running the harness in a fresh worktree withoutmanifest.yamlself-updates over tracked files).Visible effect: the discovery section of debug dumps and the
/discoverypage show the new shapes. GivTCP's entity map now lists only settings automatic configuration binds (so fewer entities than before).Testing
./run_all --quick: all tests pass (4 slow skipped, ~73s).--quick --shuffleover six seeds, all green.Known follow-ups (not blocking; items 1-2 should land before piece 3)
inverter_definition()preferssoc_kwoversoc_percent;inverter.pypreferssoc_percent(no reporter binds both today).export_limit/import_limitratings accept only numeric setting values; if livesettings/getreturns strings the rating is silently absent - needs a live capture.value: "0"not"True"and doesn't checkinvert;capture_automatic_config()doesn't restore a pre-existing instanceset_arg; AlphaESS/GE Cloud completeness loops don't assert a record was checked.Next: piece 2 (SolaX, Sigenergy, Enphase, Teslemetry, Gateway reporters), then piece 3 (the coordinator configures from records; the spec lists what piece 3 must handle).
🤖 Generated with Claude Code