Skip to content

fix(sigenergy): send the optional command fields inside commands[] - #5377

Merged
springfall2008 merged 1 commit into
mainfrom
fix/sigenergy-command-fields-in-commands-5376
Oct 4, 2026
Merged

springfall2008 merged 1 commit into
mainfrom
fix/sigenergy-command-fields-in-commands-5376

Conversation

@springfall2008

Copy link
Copy Markdown
Owner

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

Fixes #5376

Summary

On Sigenergy Cloud, send_battery_command() wrote the six optional fields (chargingPower, pvPower, maxSellPower, maxPurchasePower, chargePriorityType, dischargePriorityType) at the top level of the MQTT payload. The Sigenergy API expects them inside each entry of commands[], next to systemId, and ignores them at the top level. The result was that every charge ran at full inverter power whatever rate Predbat asked for, and the priority types were dropped.

They have sat at the top level since cba12cc ("Fix control commands"), which moved the four required fields into commands[] and left the optional ones behind. This change builds all of them into the command object. The payload now has only accessToken and commands at the top level.

Behaviour change to expect

Power limits and priority types have never reached a Sigenergy Cloud system before, so this is the first time the following take effect on real hardware:

  • Low power charging (set_charge_low_power) and any charge rate below the inverter maximum.
  • Rate-limited export.
  • chargingPower: 0 to hold the battery, used by freeze charge and the freeze_export_hold branch in apply_controls().
  • chargePriorityType / dischargePriorityType.

Testing

  • tools/triage_test.sh sigenergy: fails without the fix (FAIL: test_sigenergy_send_battery_command_mqtt — 'chargingPower', with sigenergy.py stashed and the test kept) and passes with it.
  • test_sigenergy_send_battery_command_mqtt now asserts that each of the six optional fields lands in commands[0] with its value, that the top level holds only accessToken and commands, that fields which were not passed are omitted, and that a zero chargingPower is sent rather than dropped.
  • ./run_pre_commit: every hook passes for the files in this PR (ruff, black, cspell and the rest). markdownlint-fix reported failures only in uncommitted local files in the working clone (.claude/skills/gitnexus/*, CLAUDE.md, AGENTS.md), none of which are part of this PR.
  • Not tested against a live Sigenergy system.

Notes

  • The freeze branches need checking on real hardware. The GH#4761 freeze export work in apply_controls() reasoned about chargingPower being bidirectional at a time when the field was never applied. That logic is unchanged here, but it is exercised for real for the first time by this fix, so freeze charge, freeze export and the discharge hold should be watched on a live system before release.
  • Blast radius: send_battery_command() has one caller, in apply_controls(), which only passes arguments through. GitNexus impact rates it LOW. The signature, the de-duplication hash and the log line are unchanged.
  • No other changes were made; the field placement follows the example command in the Sigenergy API documentation quoted in the issue.

🤖 Generated with Claude Code

chargingPower, pvPower, maxSellPower, maxPurchasePower, chargePriorityType and
dischargePriorityType were written at the top level of the MQTT payload, where
the Sigenergy API ignores them, so every charge ran at full power whatever rate
Predbat asked for. Build them into the command object next to systemId.

Fixes #5376

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@springfall2008 springfall2008 self-assigned this Oct 3, 2026
@springfall2008
springfall2008 marked this pull request as ready for review October 3, 2026 19:30
Copilot AI balanced review requested due to automatic review settings October 3, 2026 19:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The payload fix is sound, but it activates previously ignored live battery controls whose hardware behavior remains unverified.

Review effort: Balanced
Findings: None

What changed in this PR

Moves Sigenergy optional battery-command fields into the API-required commands[] object.

Changes:

  • Corrects all six optional MQTT field locations.
  • Expands tests for field placement, omission, rounding, and zero-power commands.
File Description
apps/​predbat/​sigenergy.py Builds optional fields inside each command object.
apps/​predbat/​tests/​test_sigenergy.py Verifies the corrected payload structure and edge cases.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@springfall2008
springfall2008 merged commit 4aa2564 into main Oct 4, 2026
3 checks passed
@springfall2008
springfall2008 deleted the fix/sigenergy-command-fields-in-commands-5376 branch October 4, 2026 08:28
springfall2008 added a commit that referenced this pull request Oct 5, 2026
…octopus row (GH#5390) (#5397)

* docs(debug-journal): fold in the 2026-10-04 queue slice (9 candidates); mark GH#5376 fixed by PR #5377 (v9.3.5) and GH#5366 by PR #5383; re-verify the SolaX/counter-dip entries after PR #5389; add the CID499 read/write units, marginal-band contamination, GivTCP verify-tolerance, minute-data dip asymmetry, Fox MaxSoc, car-export-blind, re:-first-match and tooltip-clamp entries

Co-Authored-By: Claude Code <noreply@anthropic.com>

* docs(debug-journal): map the IOG supervision bounce symptom into the octopus row (GH#5390)

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: CI <ci@example.com>
Co-authored-by: Claude Code <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.

Sigenergy Cloud: chargingPower sent outside commands[], so charge power limits are ignored

2 participants