Skip to content

fix(inverter): cap the max discharge power at the number entity's own maximum - #1292

Merged
woopstar merged 1 commit into
mainfrom
fix/1291-cap-max-discharge-at-entity-max
Oct 12, 2026
Merged

woopstar merged 1 commit into
mainfrom
fix/1291-cap-max-discharge-at-entity-max

Conversation

@woopstar

@woopstar woopstar commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

HSEM no longer commands, or plans, more battery discharge power than the Huawei Maximum discharging power number entity accepts.

Fixes #1291

6.3.x backport: #1293

What happened

Reported in #978: a 10 kWh battery whose discharge number entity has the range 0–4400 W. Every apply cycle that wanted the full limit failed with Value 5000.0 ... is outside valid range 0.0 - 4400, and the entity stayed on an earlier 2000 W cap.

HSEM took the limit from the rated capacity alone: get_max_discharge_power() maps 10000 Wh to 5000 W. The applier wrote that value to the entity, and the planner used it as the horizon-wide discharge limit. The Huawei Solar integration sets the entity's max from the hardware's own maximum-discharge-power register, so the entity knows a limit the capacity table cannot.

Reproduced through async_apply_battery_settings (discharge slot, 10 kWh battery, entity state 2000 W):

Entity max Written before Written after
4400 W 5000 W (rejected by Home Assistant) 4400 W
4400 W, state already 4400 W 5000 W (rejected) nothing
5000 W or 6000 W 5000 W 5000 W
missing or 0 5000 W 5000 W

What changed

  • utils/misc.py: new resolve_max_discharge_power(rated_capacity_wh, entity_max_w) returns the lower of the table value and the entity's maximum. A missing, non-finite or non-positive maximum leaves the table value. A fractional maximum rounds down.
  • custom_sensors/applier.py and coordinator_builder.py: both use that helper, so the written limit and PlannerInput.battery_max_discharge_power_w are the same number. The EV cap, the wait-mode reserve cap and the forcible-discharge power all start from it and inherit the bound.
  • models/live_state.py: new field huawei_batteries_max_discharge_power_limit_w for the entity's max attribute. It is separate from the entity's state, which is a commanded value and still never becomes the planner's limit (v6.0.0 Feedback & Bug Reports #592).
  • custom_sensors/discharge_power_inputs.py (new): reads the state and the max attribute of the entity. The state read moved here unchanged from state_collector.py, which had 69 bytes left under the 30 KiB file-size limit.
  • utils/ha_helpers.py: new entity_attribute_float(), next to entity_unit().
  • translations/{en,da,de,es}.json: the option's description said to select "the sensor that provides the maximum discharging power", which reads as a limit HSEM takes from it. It now says HSEM writes the discharge limit to this number entity and never above the entity's own maximum. Both the config and the options block.
  • docs/planner-spec.md, docs/planner-guide.md, docs/config-flow-reference.md, .github/memories.md: describe the bound.

Tests

  • tests/sensors/test_applier_max_discharge_entity_limit.py (new): the reported case writes 4400 W; an entity already at 4400 W is not rewritten; a missing, zero, equal or higher maximum keeps 5000 W; the EV cap, the wait-mode reserve cap and the forcible-discharge power stay at 4400 W.
  • tests/sensors/test_discharge_power_inputs.py (new): state and max land on separate fields, also through async_collect_live_state; an unusable max is None and not a missing entity; an unreadable state is still a critical missing entity.
  • tests/test_coordinator_builder.py: the planner limit is 4400 W; a capped entity state (2000 W) does not lower it; PlannerInput carries the bounded value.
  • tests/utils/test_max_discharge_power.py, tests/test_ha_helpers.py: the helper and the attribute reader.

With the bound removed from resolve_max_discharge_power(), 11 of the new tests fail.

./scripts/quality.sh all: passed (7175 tests, 1 skipped, 99 % coverage, every module at or above the 95 % floor, pyright 0 errors, translations 0 errors). Three doc lines were edited after that run; ./scripts/quality.sh format-check passed afterwards.

Known limitations

  • Not tried against a real inverter. The reporter's entity range is taken from their error message, and the tests use a stand-in entity with that range.
  • Why this installation is limited to 4400 W is not confirmed; the reporter has not named their inverter model.
  • The charging side is untouched. HSEM reads the charging-power number entity's state as the planner's charge limit and does not write to it.
  • With no rated capacity available, the planner still falls back to the entity's state, as before.

Configuration changes

None. The option keeps its key and its selector; only its description changed.

Branch: fix/1291-cap-max-discharge-at-entity-max

🤖 Generated with Claude Code

… maximum - Fixes #1291

HSEM derived the battery's maximum discharge power from the rated capacity
alone (10 kWh -> 5000 W) and wrote it to the Huawei maximum_discharging_power
number entity. On an installation whose entity accepts at most 4400 W, Home
Assistant rejected every write, the applier reported failed, and the entity
stayed on the last lower cap. The planner used the same 5000 W.

The entity's `max` attribute is now read into its own LiveState field and
bounds the table value through one helper, resolve_max_discharge_power(),
used by both the applier and the planner input. The entity's state is a
commanded value and still never becomes the limit (issue #592).

The option's description said HSEM reads a limit from the entity; it now says
HSEM writes the limit to it (en, da, de, es).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the bug Something isn't working label Oct 12, 2026
@woopstar
woopstar merged commit 503043f into main Oct 12, 2026
22 checks passed
@woopstar
woopstar deleted the fix/1291-cap-max-discharge-at-entity-max branch October 12, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(inverter): cap the max discharge power at the number entity's own maximum

1 participant