Skip to content

fix(inverter): auto-create charge_rate entity for script-driven "power" inverters (#3311) - #4645

Open
chalfontchubby wants to merge 1 commit into
mainfrom
fix/solax-low-power-charge-rate-entity
Open

fix(inverter): auto-create charge_rate entity for script-driven "power" inverters (#3311)#4645
chalfontchubby wants to merge 1 commit into
mainfrom
fix/solax-low-power-charge-rate-entity

Conversation

@chalfontchubby

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes Low power mode does not work on Solax #3311 - Solax low power mode sends battery_rate_max instead of the planned "Best rate" to charge_start_service.
  • Root cause: output_charge_control: "power" inverters normally write their rate straight to the inverter via a REST/cloud API, so the dummy charge_rate/discharge_rate HA entities were only ever auto-created for "current" mode. Solax is "power" mode but script-driven (charge_start_service → a plain HA script, not REST) - get_current_charge_rate()/adjust_charge_rate() still fall back to self.base.args["charge_rate"] exactly like "current" mode does, unless the inverter is genuinely REST-driven. Without the entity, the low-power-mode calculation runs fine (visible in the reporter's own log as "Best rate: 2500W") but has nowhere to persist it, so it reads back as battery_rate_max_raw and the script gets sent full power. Community member f948lan independently found the same root cause and worked around it manually (creating input_number helpers) - this makes that automatic.
  • Only auto-creates when nothing is already configured: unlike "current" mode (where charge_rate is always a synthetic mirror of the real current-based control, so it's always safe to (re)create), a "power" inverter's charge_rate can be a real, user-configured entity (e.g. GE's own apps.yaml template comment: "If not using REST then instead set the Control here") - the fix must not clobber that. Caught this exact regression while building the fix (broke test_adjust_charge_rate1 against GE's default non-REST config) and tightened the condition accordingly.
  • Not the same bug as Discharge Start Service always called with maximum power #4619/PR fix(inverter): discharge_start_service sends the planned rate, not always max #4621 (merged) - that was the discharge side hardcoding a wrong value despite the entity existing; this is the charge side's entity never existing in the first place for script-driven "power" inverters.

Test plan

  • ./run_all --test inverter - full inverter suite passes
  • New test test_low_power_mode_entity_created_for_script_driven_power_inverter - REST-less "power" inverter (Solax-shaped) gets the entity auto-created
  • New test test_low_power_mode_entity_not_clobbered_when_already_configured - a real, pre-configured charge_rate (e.g. GE's own template) is left untouched, not overwritten
  • New test test_low_power_mode_entity_not_created_for_rest_driven_power_inverter - genuinely REST-driven "power" inverters are unaffected
  • Verified all three fail appropriately against the pre-fix code (reverted, confirmed failures, restored)
  • ./run_pre_commit clean
  • Full ./run_all --quick suite passes

🤖 Generated with Claude Code

…r" inverters (#3311)

Solax's low-power-mode charge rate is driven via charge_start_service (a plain
HA script call), not a REST/cloud API, but output_charge_control: "power" meant
the dummy charge_rate/discharge_rate entities were only ever auto-created for
"current" mode. get_current_charge_rate() and adjust_charge_rate() both fall
back to self.base.args["charge_rate"] regardless of output_charge_control
unless the inverter is genuinely REST-driven - without the entity, the
computed rate had nowhere to be stored and read back as battery_rate_max_raw,
sending full power to the script regardless of what was planned.

Only auto-create when nothing is already configured - unlike "current" mode
(where charge_rate is always a synthetic mirror), a "power" inverter's
charge_rate can be a real user-configured entity (e.g. GE's own "if not using
REST" apps.yaml template) that must not be overwritten.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Comment thread apps/predbat/inverter.py
# was actually planned. Only fill in the gap when nothing is configured at all.
max_charge = self.battery_rate_max_charge * MINUTE_WATT
max_discharge = self.battery_rate_max_discharge * MINUTE_WATT
if "charge_rate" not in self.base.args:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Should this be an 'has' in the inverter config rather than silently creating missing entities?

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.

Low power mode does not work on Solax

2 participants