Skip to content

fix(inverter): seed the dummy reserve of a register-less inverter in percent, not kWh (#5850) - #5870

Merged
springfall2008 merged 2 commits into
mainfrom
fix/dummy-reserve-percent-seed-5850
Nov 1, 2026
Merged

springfall2008 merged 2 commits into
mainfrom
fix/dummy-reserve-percent-seed-5850

Conversation

@springfall2008

Copy link
Copy Markdown
Owner

This is an automated draft PR generated from issue #5850 — a maintainer should review it before merging.

Fixes #5850

Summary

For inverter types with no reserve register (has_reserve_soc: False — GS, SE, SX4, SF, SFMB, HU, SK, SIG, SIGCLOUD), refresh_config() seeded the dummy reserve entity with self.reserve (kWh) while labelling it %. The next refresh read that back as reserve_percent_current, which balance_inverters() uses for its above-reserve check.

  • The dummy (and the matching create_missing_arg default) is now seeded with self.reserve_percent.
  • create_entity() never overwrites an existing state, so an install that already has the kWh seed would keep it. After creating the entity, if what it reads back (via the same get_arg(..., required_unit="%") that line 774 uses) differs from reserve_percent, the percent is written. Nothing on the device needs preserving: these inverters have no reserve register, so Predbat owns the value. With set_reserve_enable forced off for these types (execute.py:1460), the only writes Predbat makes to this entity are adjust_reserve(0) on the calibration and reset paths, and those are clamped up to reserve_percent anyway.

Testing

  • coverage/./run_pre_commit: all hooks passed, and the --quick suite it then runs passed.

  • New test_reserve_dummy_percent in tests/test_inverter.py, with two cases. Both use an HU inverter with soc_max 10 kWh, set_reserve_min 50 and battery_min_soc 3. battery_min_soc is set low because the triage found its floor hides the kWh value in default configs.

    • reserve_dummy_seeded_percent: a fresh dummy.
    • reserve_dummy_kwh_seed_corrected: a dummy that already holds the old kWh seed of 5.0.

    Both cases check the dummy's own state and unit (50, %) and reserve_percent_current == 50 after a refresh.

  • Fails without the fix, passes with it. With only inverter.py stashed, tools/triage_test.sh inverter failed on both cases (dummy reserve should be 50 % got 5.0 %, reserve_percent_current should be 50 got 5). With the fix restored, the whole inverter module passes.

Notes

  • The correction happens where the dummy is created, which is after line 774 reads reserve_percent_current. On the first refresh that corrects an old kWh seed, that refresh's reserve_percent_current is still the stale value. It reads correctly from the next refresh, one plan cycle later. I chose not to also overwrite reserve_percent_current in the same pass, because reserve_literal_huawei (GH#5003) deliberately expects a hard-wired apps.yaml reserve literal to be reported as the current reserve on construction.
  • The inverter self_test() calls adjust_reserve(100/6/4). On these types the next refresh now resets the dummy back to reserve_percent. Since the dummy controls no device, that seems right.
  • Blast radius: GitNexus impact(refresh_config, upstream) is LOW (2 direct callers, Inverter.__init__ and the per-cycle refresh). detect_changes shows only refresh_config changed outside the tests.

🤖 Generated with Claude Code

…percent, not kWh (#5850)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@springfall2008 springfall2008 self-assigned this Oct 30, 2026
@springfall2008 springfall2008 added BOT_REVIEW Trigger an autotriage BOT_CLEANUP Trigger: bot should address PR review feedback and CI failures, then commit and push labels Oct 30, 2026

@springfall2008 springfall2008 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated comment from the triage bot.

Review of 222d7ad: the seeding fix is sound — 1 finding inline, 0 in the body.

What was checked: the seed/comparison mechanics (unit_conversion returns a float for numeric states, so the != read-back is stable and cannot rewrite every cycle), the created_attributes lookup (set unconditionally in create_entity(), so no KeyError), the claim in the new comment about who writes the dummy (all three adjust_reserve(0) sites clamp up to reserve_percent; the hold/freeze sites are gated on set_reserve_enable, which execute.py forces off for these types; self_test runs only under INVERTER_TEST), device bounds for the dummy (no min/max attributes, so (None, None)), the new test's registration, red/green design and restore/teardown, and the literal (GH#5003) interaction.

Comment thread apps/predbat/inverter.py Resolved
@springfall2008 springfall2008 removed the BOT_REVIEW Trigger an autotriage label Oct 30, 2026
…rrects it (#5850)

When refresh_config() rewrites a dummy reserve still holding the old kWh seed, re-read
reserve_percent_current (and reserve_current) so the balancer sees the corrected percent
in that cycle rather than one cycle later. Gated on the write, so a fresh dummy and the
GH#5003 literal-reserve case still report the arg they replaced on construction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@springfall2008 springfall2008 removed the BOT_CLEANUP Trigger: bot should address PR review feedback and CI failures, then commit and push label Oct 30, 2026
@springfall2008
springfall2008 marked this pull request as ready for review October 31, 2026 18:50
@springfall2008
springfall2008 merged commit a8e1ca7 into main Nov 1, 2026
3 checks passed
@springfall2008
springfall2008 deleted the fix/dummy-reserve-percent-seed-5850 branch November 1, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dummy reserve entity for inverters without a reserve register is seeded in kWh but read as percent

1 participant