Repository navigation
fix(gateway): bind battery_scaling, battery_rate_max and inverter_time per inverter - #5331
Merged
Merged
Conversation
…e per inverter automatic_config() built every per-inverter arg in the inverter loop except these three, which were hard-coded to the first inverter's entity. inverter.py reads them at index=self.id, so on a hub with two or more primary inverters inverter 1+ hit "Out of range index 1" every cycle (plus three apps.yaml validation errors) and silently fell back to defaults: battery_rate_max 2600 W instead of the hub-reported rate (3000 W on the AC Gen1 field case), battery scaling 1.0, and no clock-drift check. The hub already publishes battery_dod, battery_rate_max and inverter_time for every inverter, so the lists now carry one entry per inverter in the same serial order as soc_percent. Single-inverter and Gateway-coordinated topologies still get a one-entry list bound to the same serial as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused fix matches indexed inverter reads and includes appropriate regression coverage.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes Gateway multi-inverter configuration so each inverter receives its own battery and clock entities.
Changes:
- Builds three per-inverter entity lists in serial-sorted order.
- Adds regression coverage for two primary inverters.
| File | Description |
|---|---|
apps/predbat/gateway.py |
Binds battery scaling, maximum rate, and inverter time per inverter. |
apps/predbat/tests/test_gateway.py |
Verifies multi-inverter bindings and ordering. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a PredBat Gateway (Hub) site with two or more primary inverters,
GatewayMQTT.automatic_config()bound three per-inverter args to the first inverter only:inverter.pyreads all three atindex=self.id. So for inverter 1 onwards:Warn: Out of range index 1 within item battery_rate_max / battery_scaling / inverter_time, and config validation reports 3 errors (… has 1 entries, expected 2 based on num_inverters).battery_rate_maxsilently falls back to 2600 W. In the field case (2 × GivEnergy AC Gen1 behind a Hub) the hub reports 3000 W for the second inverter, so PredBat planned that battery about 13% slower than it is and sentset_charge_rate power_w: 2600.battery_scalingfalls back to 1.0. That happens to match the hub's default 100% depth of discharge, but it isn't read from the hub.inverter_timeis never read for that inverter, so its clock-drift check doesn't run.Every other per-inverter arg (
soc_percent,battery_power,charge_rate,inverter_limit, …) is already built in the per-inverter loop. These three were left over from the single-inverter version.Fix
Build the three lists inside the existing per-inverter loop, so each has one entry per primary inverter, in the same serial-sorted order as
soc_percent. The hub already publishesbattery_dod,battery_rate_maxandinverter_timefor every inverter. This was confirmed on the field instance, where both…_23g800_*and…_25g400_*exist with live values. So no gateway-side change is needed.Single-inverter sites, and the Gateway-coordinated topology where
automatic_configpicks the Gateway as the sole control target, still get a one-entry list bound to the same serial as before.test_single_inverter_energy_and_health_argsandTestBoundEntitiesAreWrittencover those cases and still pass.Tests
TestAutomaticConfig.test_multi_inverter_battery_args_have_one_entry_per_inverter: two primary inverters, and asserts each of the three args lists both inverters' entities in order. It failed before the fix (battery_scalinghad a single entry) and passes after../run_all --test gateway: passed../run_all --quick: All tests passed (4 slow tests skipped, 80.95s).🤖 Generated with Claude Code