feat(config): wire live phase-aware grid-charge safety entities (issue #831, Part 1) - #836
Open
woopstar wants to merge 1 commit into
Open
feat(config): wire live phase-aware grid-charge safety entities (issue #831, Part 1)#836woopstar wants to merge 1 commit into
woopstar wants to merge 1 commit into
Conversation
…#831, Part 1) Foundation-only PR for the live per-phase Huawei grid-charge safety limiter. No behavior change — the feature is off by default (hsem_phase_aware_charging_enabled = False) until Part 2 wires the actual limiter logic into the applier. Adds: - hsem_phase_aware_charging_enabled config toggle (power step) - hsem_huawei_solar_batteries_grid_charge_maximum_power entity picker (huawei_solar step) — the write target for the future limiter - hsem_huawei_solar_power_meter_phase_{a,b,c}_active_power entity pickers (power step) — live per-phase telemetry inputs - SensorConfig / LiveState fields and config_reader/state_collector wiring for all four entities - LiveState.grid_phase_power_w tuple, fails closed to None per phase when unavailable - extra_state_attributes exposure for diagnostics - docs/huawei_entities.md, docs/config-flow-reference.md, docs/sensors-reference.md updates - translations/en.json labels/descriptions in both config and options steps Both required Huawei entities (number.batteries_grid_charge_maximum_power, sensor.power_meter_phase_{a,b,c}_active_power) already exist and are documented in docs/huawei_entities.md; this PR only wires them into HSEM's config flow and live-state pipeline. Part of a 3-PR delivery plan tracked in issue #831: - Part 1 (this PR): foundation wiring - Part 2: live phase limiter core (utils/phase_power.py + custom_sensors/phase_charge_limiter.py, wired into applier.py) - Part 3: feedback-free floor + 45s fail-closed transition safety Tests: config flow schema round-trip (power + huawei_solar steps), validation of the new optional entity fields, config_reader field reads/defaults. All 2855 existing + new tests pass; lint/typing/quality gates clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part 1 of a 3-PR plan to build a live per-phase Huawei grid-charge safety limiter (issue #831 — port of the safety-relevant half of
Ambilights/hsem-ambilights#35, Huawei-only, no PowMr).Why: the MILP plans grid-charging against a forecast, but between solve time and the hardware write, another appliance on the same phase can spike load. Without a live check immediately before the write, HSEM can command Huawei to charge at a rate that pushes a phase over the main fuse rating. The fork author hit this on real hardware; this PR starts building the same protection for this repo's Huawei-only control path.
This PR is foundation-only — no behavior change. The feature is off by default (
hsem_phase_aware_charging_enabled = False) until Part 2 wires the actual limiter logic into the applier.What's in this PR
hsem_phase_aware_charging_enabled(power step), defaultFalse.hsem_huawei_solar_batteries_grid_charge_maximum_power(huawei_solar step) — the future limiter's write target. Maps tonumber.batteries_grid_charge_maximum_power, which already exists perdocs/huawei_entities.mdbut was unwired.hsem_huawei_solar_power_meter_phase_{a,b,c}_active_power(power step) — live per-phase telemetry inputs. Map tosensor.power_meter_phase_{a,b,c}_active_power, also already documented but unwired.SensorConfig/LiveStatefields for all four entities, read byconfig_reader.py/state_collector.py.LiveState.grid_phase_power_w: tuple[float | None, float | None, float | None]— fails closed toNoneper phase when a reading is unavailable/invalid, so the future limiter (Part 2) can't guess a missing phase.extra_state_attributeson the working-mode sensor (phase_aware_charging_enabled,grid_phase_power_w,huawei_batteries_grid_charge_max_power_w, plus entity-ID attributes underextended_attributes).docs/huawei_entities.md(marks both entities as used),docs/config-flow-reference.md,docs/sensors-reference.md.configandoptionssteps intranslations/en.json.Files changed
custom_components/hsem/const.pycustom_components/hsem/custom_sensors/config_reader.pycustom_components/hsem/custom_sensors/state_collector.pycustom_components/hsem/custom_sensors/working_mode_sensor.pycustom_components/hsem/flows/huawei_solar.pycustom_components/hsem/flows/power.pycustom_components/hsem/models/live_state.pycustom_components/hsem/models/sensor_config.pycustom_components/hsem/translations/en.jsondocs/config-flow-reference.md,docs/huawei_entities.md,docs/sensors-reference.mdtests/sensors/test_state_collector.py,tests/test_config_validation.pyDelivery plan (tracked in issue #831)
utils/phase_power.pygetscompute_phase_charge_limits(); newcustom_sensors/phase_charge_limiter.pycomputes a safe grid-charge cap from live phase telemetry; wired intoapplier.pyso Huawei's grid-charge cap is actually written per-cycle when the toggle is on.Tests
tests/test_config_validation.py: schema round-trip for both newpowerstep fields and the newhuawei_solarstep field; validation of the phase entity pickers (entity-not-found case); defaults-to-disabled case.tests/sensors/test_state_collector.py:build_sensor_configreads/defaults forphase_aware_charging_enabled,huawei_solar_batteries_grid_charge_maximum_power, and the three phase entities (including thevol.UNDEFINED→Nonenormalization case, matching the existing_optional_entity()pattern used for other optional Huawei entities).Test results
./scripts/quality.sh lint— pass (ruff format + check clean)./scripts/quality.sh typing— pass (0 mypy errors)./scripts/quality.sh quality— pass (0 pyright/vulture errors)./scripts/quality.sh test— 2855 passed (full suite, including the new tests)Known limitations
This PR only wires configuration and live-state plumbing. Enabling the toggle today has no runtime effect — Part 2 is required before the limiter actually computes and writes anything. This is intentional: it lets the config surface, translations, and data model land and be reviewed independently of the (larger, more safety-critical) limiter logic.
Part of #831.