Skip to content

fix(inverter): only invoke discharge_freeze_service on an explicit freeze request - #4472

Open
chalfontchubby wants to merge 1 commit into
mainfrom
fix/adjust-export-immediate-freeze-on-target-reached
Open

fix(inverter): only invoke discharge_freeze_service on an explicit freeze request#4472
chalfontchubby wants to merge 1 commit into
mainfrom
fix/adjust-export-immediate-freeze-on-target-reached

Conversation

@chalfontchubby

Copy link
Copy Markdown
Collaborator

Summary

adjust_export_immediate() (inverter.py) called discharge_freeze_service whenever an active export reached its target SoC (target_soc == self.soc_percent), regardless of the freeze argument the caller passed - so it fired independently of set_export_freeze any time export naturally completed, not just for a deliberate Freeze Export.

execute.py's own call site already gated the genuine freeze case correctly:

if self.set_export_freeze and self.export_limits_best[0] == 99:
    inverter.adjust_export_immediate(inverter.soc_percent, freeze=True)
elif not disabled_export:
    inverter.adjust_export_immediate(int(self.export_limits_best[0]))

The bug was one level down - adjust_export_immediate re-derived its own independent freeze decision from SoC equality alone, so the ordinary elif branch (active export, freeze defaults False) still ended up calling the freeze service the moment the export target was reached.

Confirmed live via a reporter's log on #4464 - exporting down to a 0% target reliably produced:

Inverter 0 Current Target SoC is 0%, already at target
Inverter 0 Calling service discharge_freeze_service ... {'option': 'Freeze Discharging'}

with switch.predbat_set_export_freeze off the whole time.

Fix

Reaching the target via ordinary export isn't a freeze - it's "nothing left to discharge," which already had its own correct handling one branch over (target_soc > self.soc_percent -> discharge_stop_service). Merged the equality case into that branch instead, so discharge_freeze_service only fires when the caller explicitly passes freeze=True (i.e. set_export_freeze's own path).

Test plan

  • tests/test_inverter.py updated - two sub-cases that pinned the old "target reached -> freeze" behaviour now expect discharge_stop; added a discharge-domain dedup reset (clear=True) on those two so they're judged independently of whatever the preceding sub-test happened to send, now that several target values collapse onto the same discharge_stop call
  • ./run_all --test inverter / --test execute pass
  • ./run_all --quick - all tests pass
  • ./run_pre_commit - clean

Fixes #4464.

🤖 Generated with Claude Code

…eeze request

adjust_export_immediate() called discharge_freeze_service whenever an
active export reached its target SoC (target_soc == self.soc_percent),
regardless of the freeze argument the caller passed - so it fired
independently of set_export_freeze whenever export naturally completed,
not just for a deliberate Freeze Export. execute.py's own call site
already gated the genuine freeze case correctly on set_export_freeze;
the bug was one level down, re-deriving an independent freeze decision
from SoC equality alone.

Reaching the target via ordinary export isn't a freeze, it's "nothing
left to discharge" - now merged into the existing target_soc >=
self.soc_percent stop case, so only freeze=True (set_export_freeze's
own path) calls discharge_freeze_service.

Confirmed live via a reporter's log on #4464: exporting down to 0%
reliably triggered "Calling service discharge_freeze_service ... Freeze
Discharging" the moment the target was reached, with the switch off.

Fixes #4464.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

Predbat requested "Freeze Discharging" despite switch.predbat_set_export_freeze = False

1 participant