You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Solis GS_fb00: warn when a freeze or hold can't be enforced because energy_control_switch is missing #5857
Summary: on Solis GS_fb00, when energy_control_switch isn't configured, Predbat still shows "Freeze charging" or "Hold for car" while the battery keeps discharging. It writes the hold but cannot enforce it, and on those cycles it gives no warning.
Seen in #5834 and #5852. That setup uses Pho3niX90's solis_modbus, which has no Energy Storage Control Switch with the option names Predbat writes.
Detail
On GS_fb00, freezes and holds raise the reserve (Reserved SOC) to SoC + 1%. That reserve only stops discharge while the inverter's Battery Reserve bit is on. adjust_charge_immediate() sets that bit through write_solis_energy_control() (apps/predbat/inverter.py, ~3495).
When energy_control_switch is unset, write_solis_energy_control() returns without writing (~3341). It warns only when warn_missing is True, and the caller passes warn_missing=(target_soc > 0 and not freeze). So the warning appears on charge cycles and never on the freeze and hold cycles where the missing switch actually matters.
Proposal
On GS_fb00, also warn on freeze and hold cycles when energy_control_switch is unset. Make it a one-time warning, or rate-limited, so the log isn't flooded. Say that the hold won't be enforced unless the inverter's Battery Reserve mode is kept on.
Optionally, show the hold in the status as not enforced, so "Hold for car" doesn't read as a working hold.
Add a unit test covering a freeze cycle with the switch unset.
Automated first-pass triage — a maintainer will review before any action is taken.
Classification: enhancement (no priority attached).
This matches what the source tickets (#5834, #5852) found, and I've confirmed every claim in the report against current main (6fd23db4):
write_solis_energy_control() (apps/predbat/inverter.py:3332) returns without writing when energy_control_switch is unset (apps/predbat/inverter.py:3342), and warns only when warn_missing=True (apps/predbat/inverter.py:3343).
The FB00 freeze/hold caller passes warn_missing=(target_soc > 0 and not freeze) (apps/predbat/inverter.py:3497), so the warning fires on charge cycles and is suppressed exactly on the freeze and hold cycles where the missing switch is the difference between a working hold and a silent no-op.
Docs match that gap: docs/inverter-setup.md:2833 only promises a warning "during charge slots" and otherwise tells the user to keep the switch on Backup/Reserve themselves.
Two additions to the report's scope, both verified in the tree:
The export/freeze-export caller (apps/predbat/inverter.py:3548) passes no warn_missing at all, so those cycles are silent too — including freeze-export, where the switch drives Feed-in priority on FB00.
The GS caller (alt_charge_discharge_enable, apps/predbat/inverter.py:3319) warns only on a real charge enable; on GS a missing switch is far more visible because the switch write is the enable, so the FB00-first proposal is the right scope.
Implementation pointers, all verified in the tree:
The "one-time / rate-limited" ask already has a proven pattern: battery_scaling_invalid_warned (from PR fix(inverter): warn once, not every cycle, while battery_scaling keeps reading invalid #5841, apps/predbat/inverter.py:416, used at 531–536) demotes repeat occurrences from Warn to Info instead of dropping them. Note the existing warning text (... Predbat cannot make sure the inverter allows grid charging, apps/predbat/inverter.py:3344) is charge-specific — a freeze/hold warning needs different wording (the hold won't be enforced unless the inverter's Battery Reserve mode is kept on), so this is likely a separate message rather than just widening warn_missing.
Unit test: test_solis_energy_control() (apps/predbat/tests/test_inverter.py:70) already supports configured=False (pops the arg at line 95), but the only unconfigured case is a charge cycle (solis_fb00_not_configured, line 5851) — a freeze cycle with the switch unset is the natural additional case (cf. solis_fb00_freeze_blocks_grid at line 5852, run today only configured). Asserting the warning itself would need log capture, which the helper doesn't do today.
Status surfacing ("hold not enforced") would be a follow-on step: write_solis_energy_control() returns None and no caller distinguishes configured from unconfigured, so the status path needs new plumbing either way.
Related: #5834 (the original EV-hold question, same single code path), #5852 (the household-drain bug report on the same mechanism, currently waiting on the reporter's files), #5152 (a different hold gap — the discharge suppression there is slot-bounded).
No further files needed from the reporter at this stage — the mechanism was already verified from evidence in the source tickets.
Activity
springfall2008 commentedon Oct 29, 2026
Automated first-pass triage — a maintainer will review before any action is taken.
Classification: enhancement (no priority attached).
This matches what the source tickets (#5834, #5852) found, and I've confirmed every claim in the report against current main (
6fd23db4):write_solis_energy_control()(apps/predbat/inverter.py:3332) returns without writing whenenergy_control_switchis unset (apps/predbat/inverter.py:3342), and warns only whenwarn_missing=True(apps/predbat/inverter.py:3343).warn_missing=(target_soc > 0 and not freeze)(apps/predbat/inverter.py:3497), so the warning fires on charge cycles and is suppressed exactly on the freeze and hold cycles where the missing switch is the difference between a working hold and a silent no-op.docs/inverter-setup.md:2833only promises a warning "during charge slots" and otherwise tells the user to keep the switch onBackup/Reservethemselves.Two additions to the report's scope, both verified in the tree:
apps/predbat/inverter.py:3548) passes nowarn_missingat all, so those cycles are silent too — including freeze-export, where the switch drives Feed-in priority on FB00.alt_charge_discharge_enable,apps/predbat/inverter.py:3319) warns only on a real charge enable; on GS a missing switch is far more visible because the switch write is the enable, so the FB00-first proposal is the right scope.Implementation pointers, all verified in the tree:
battery_scaling_invalid_warned(from PR fix(inverter): warn once, not every cycle, while battery_scaling keeps reading invalid #5841,apps/predbat/inverter.py:416, used at 531–536) demotes repeat occurrences from Warn to Info instead of dropping them. Note the existing warning text (... Predbat cannot make sure the inverter allows grid charging,apps/predbat/inverter.py:3344) is charge-specific — a freeze/hold warning needs different wording (the hold won't be enforced unless the inverter's Battery Reserve mode is kept on), so this is likely a separate message rather than just wideningwarn_missing.test_solis_energy_control()(apps/predbat/tests/test_inverter.py:70) already supportsconfigured=False(pops the arg at line 95), but the only unconfigured case is a charge cycle (solis_fb00_not_configured, line 5851) — a freeze cycle with the switch unset is the natural additional case (cf.solis_fb00_freeze_blocks_gridat line 5852, run today only configured). Asserting the warning itself would need log capture, which the helper doesn't do today.write_solis_energy_control()returns None and no caller distinguishes configured from unconfigured, so the status path needs new plumbing either way.Related: #5834 (the original EV-hold question, same single code path), #5852 (the household-drain bug report on the same mechanism, currently waiting on the reporter's files), #5152 (a different hold gap — the discharge suppression there is slot-bounded).
No further files needed from the reporter at this stage — the mechanism was already verified from evidence in the source tickets.