Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Three moderate Gateway issues remain unresolved, along with an API documentation update.
Review effort: Lite
Findings: None
What changed in this PR
Adds correlated MQTT ACK handling and typed write outcomes to prevent unsafe inverter retries and expose structured failures.
Changes:
- Correlates ACKs, validates targets, and handles reconnects.
- Propagates rejected or uncertain outcomes through verification, standalone dispatch, and HTTP APIs.
- Adds regression coverage for ACK and retry behavior.
| File | Summary |
|---|---|
apps/predbat/web.py |
Serializes structured failures; documentation should define the new response contract (nit, 1 vote). |
apps/predbat/userinterface.py |
Propagates typed standalone service results. |
apps/predbat/tests/test_gateway.py |
Updates command-ID tests and registration. |
apps/predbat/tests/test_gateway_write_results.py |
Adds Gateway write and failure regressions. |
apps/predbat/inverter.py |
Handles ACK-aware verification and retry behavior. |
apps/predbat/gateway.py |
Adds ACK correlation and control validation; three moderate findings remain (1 vote each) involving empty-status cache invalidation, owner-loop shutdown races, and unknown online-state handling. |
apps/predbat/component_base.py |
Defines structured write results and errors. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
_check_control_target validated writes against _last_status/_last_telemetry_time, which _process_telemetry never updates on an empty-inverters frame (to avoid wiping a good binding or triggering a spurious reconfigure). That meant a device actively reporting "I can see nothing" was indistinguishable from simply not having reported at all, so a stale-but-still-fresh topology snapshot kept validating writes for up to 120s after the device said the target was gone. Track the timestamp of the most recent empty frame separately, and reject a write when that empty frame is newer than the last known-good status and still fresh itself — distinguishing "no news" from "fresh news is bad" without touching the cached topology used elsewhere. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n} response /api/service now returns a JSON object instead of true/false/null when a Hub-connected component (e.g. the Gateway) rejects a write or can't confirm its outcome, but the doc still only described the legacy true/false/null contract. Document the new shape, and call out that outcome_unknown means the write's effect is unconfirmed — callers must not blindly retry it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Out-of-order topology telemetry is compared by receipt time, which can incorrectly block or permit controls.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (1)
| # Record that the device actively reported an empty topology, distinct | ||
| # from simply not having heard from it. _last_status/_last_telemetry_time | ||
| # deliberately stay untouched here: overwriting them would wipe a good | ||
| # binding and could trigger a spurious reconfigure. _check_control_target | ||
| # uses this timestamp to tell "no fresh news" from "fresh news is bad". | ||
| self._last_empty_telemetry_time = time.time() |
|
Automated comment from the triage bot (pr-cleanup run). I didn't push anything. This branch needs a manual rebase, because merging What changed upstream: #5220 (merged 2026-09-26) added its own Hub command-ack handling to
This PR covers the same ground a different way: Why I didn't resolve it:
Then the typed-outcome plumbing this PR adds to the standalone service dispatch, the HTTP service API and the inverter verifier would have to be ported onto whichever model survives. That is a re-implementation, so I've left it for the author. The other files in the merge ( I didn't process the review threads or CI failures on this run, because they'd need re-checking against the rebased code anyway. |
|
@mgazza #5231 merged this morning, and it overlaps most of this PR. I don't think this one can be rebased as it stands. It needs a rethink on top of #5231, or closing in favour of a smaller follow-up. Which would you prefer? How the two overlap Both PRs subscribe to
What a trial rebase onto main showed
Two issues here that apply whatever happens with #5231
Fallback policy This needs deciding either way. #5231 says a denied or missing ack subscription leaves writes as they were. This PR blocks all inverter control in that case. The rollout notes here say instance tokens don't have read access to What's still worth having from this PR
If you want to keep going, I'd build it as a layer on #5231:
That is probably small enough to be a fresh PR, and closing this one would keep the review history clean. |

Summary
Consume correlated Hub command acknowledgements and carry rejected/uncertain results back through standalone service dispatch to the inverter verification loops.
Proof and tests
New regressions run actual Gateway telemetry/configuration, standalone service dispatch, cross-loop MQTT publication and inverter number/switch/schedule verification. Only physical device/broker boundaries are simulated.
Before the fix, explicit NACKs and a disconnected coordinator cause ten writes and 20 simulated seconds of polling, ending in the observed
didn't completemessages. A healthy single AIO completes in one attempt. This proves the mechanism can produce the symptom, not a unique cause for field Modbus failures.GitNexus marks the shared verifier change CRITICAL (20 affected flows). Those flows were reviewed and the broader regression suites above rerun. No change to coordinator selection, fanout or other integrations' legacy retry behavior is intended.
Rollout prerequisites
The instance MQTT token needs read access to
predbat/devices/<paired-device>/ack/+. Existing one-level+status grants do not cover ACKs. Deploy token-issuer ACL support and firmware that truthfully reports failed setters before enabling this consumer. Old firmware can still falsely ACK failure, so telemetry verification remains essential.No deployment, live device commands or provider changes are part of this PR.