Repository navigation
fix(givtcp): fill per-inverter arg slots by REST endpoint index, not discovery order (#5209) - #5216
Merged
Merged
Conversation
…discovery order (#5209) An endpoint down at discovery shifted every later inverter's entities down a slot while inverter_limit_charge and other hand-set per-inverter args stayed put, so one physical inverter was driven by two Predbat inverters. Adopting the late endpoint on re-probe appended it, turning the shift into a rotation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
springfall2008
commented
Sep 24, 2026
springfall2008
commented
Sep 24, 2026
springfall2008
commented
Sep 24, 2026
springfall2008
commented
Sep 24, 2026
springfall2008
commented
Sep 24, 2026
springfall2008
marked this pull request as ready for review
September 26, 2026 10:16
CossieRob
pushed a commit
to CossieRob/batpred
that referenced
this pull request
Sep 26, 2026
… daemon On 2026-09-26 the PR springfall2008#5216 cleanup backgrounded its pre-commit run, ended on "I'll push and reply once it finishes", and exited 0 with its fixes uncommitted. The daemon took exit 0 as success and cleared BOT_CLEANUP; the next sync_repo() then failed at `git checkout main` because the leftover edits would be overwritten - and since every flow starts with sync_repo(), every flow after it failed the same way. - claude_env() now sets CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 for every claude invocation, which removes run_in_background from the Bash tool (checked against Claude Code 2.1.283). A -p session cannot come back for a background result. - sync_repo() stashes anything left uncommitted (aborting an unfinished merge first) before checking out main, so leftovers are kept but can no longer block the checkout. - process_bot_cleanup_pr() checks the clone after a clean exit and marks the PR BOT_FAILED, with the reason, when work was left uncommitted or unpushed. - pr-cleanup SKILL.md: run the quality gate in the foreground, and drop the false claim that an unpushed commit is discarded on the next run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n adoption, split gap/tail log - automatic_config() records what each key held before its first claim and hands a capability-gated key back to it when a re-run's gate fails (a late endpoint lacking v3 or a register), instead of leaving the gap-slot claim pointing at an entity that is never published. - run() publishes again straight after rediscover() adopts an endpoint, so the re-run's discovery-key gates see the adopted inverter's sensors rather than failing for all of them. - Gap slots below the highest answered endpoint get their own Warn line naming the URL and the cost (planned without live data until it answers); only tail slots are "left as configured". - Rewrite the automatic_config() header comment to the per-endpoint invariant. - Update the debug-journal GH#5029 row and PR #4645 proxy bullet for _per_endpoint_values(). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
springfall2008
added a commit
that referenced
this pull request
Sep 27, 2026
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.
This is an automated draft PR generated from issue #5209 — a maintainer should review it before merging.
Fixes #5209
Summary
GivTCPComponent.automatic_config()built each per-inverter arg list by position, from the endpoints that answered discovery. If endpoint 0 was down at startup, endpoints 1 and 2 moved into slots 0 and 1. Hand-set per-inverter args such asinverter_limit_charge: [2600, 2600, 3000]stayed where they were. So Predbat inverter 1 wrote 2600 W to the AC3 on endpoint 2, and inverter 2 wrote 3000 W back to it every cycle. When endpoint 0 came back,rediscover()appended it, which turned the shift into a permanent rotation:[givtcp_1, givtcp_2, givtcp_0]._keep_configured_tail()is replaced by_per_endpoint_values(), which always puts REST endpoint n in slot n:num_invertersnow covers at leastmax(discovered) + 1. The order ofself.discoveredno longer carries meaning, so appending on re-probe is harmless. The #5029 tail behaviour is unchanged: past the last discovered endpoint, the configured entries are kept, a scalar is broadcast, and a short list stays short.This also fixes the reporter's
battery_calibration ... expected 3warnings. An unconfigured claimed key now gets one entry per inverter instead of coming out short.Review round 1
run()now publishes again straight afterrediscover()adopts an endpoint. Without this, the re-run's discovery-key gates saw nothing published for the adopted inverter and failed for every key. On main that left the old, shorter claim in place; with the handback it would have dropped the keys for the whole fleet.Warnline naming the URL and what it costs.automatic_config()header comment and the debug-journal GH#5029 row and PR fix(inverter): auto-create charge_rate entity for script-driven "power" inverters (#3311) #4645 bullet are updated to the per-endpoint invariant.Testing
tools/triage_test.sh givtcp_component: fails without the fix (104/108, 4 failed) and passes with it. The red run shows the reporter's exact lists:charge_rateshifted to[givtcp_1, givtcp_2, inv2],battery_calibrationtwo entries short of three, and the[givtcp_1, givtcp_2, givtcp_0]rotation after recovery. After review round 1: 118/118.test_leading_endpoint_down_does_not_shift_the_fleetreproduces the Predbat GivTCP REST repeatedly setting inverter charge/discharge rate to wrong value, then correct value #5209 setup: 3 endpoints, endpoint 0 down,num_inverters: 3, then endpoint 0 recovers.test_gated_claim_is_handed_back_when_a_late_endpoint_lacks_the_capability,test_gap_and_tail_slots_are_logged_separately, and abattery_calibrationassertion intest_rediscovery_picks_up_an_inverter_that_was_down_at_startupcover the round 1 changes../run_pre_commitpasses: all hooks plus the quick suite (4 slow tests skipped).Notes
test_automatic_config_maps_predbat_inverter_to_the_live_endpointis now..._keeps_the_live_endpoint_in_its_own_slot. It hadgivtcp_rest: [dead, live]becoming one inverter driven by endpoint 1. It now becomes two inverters, with slot 0 pointing at endpoint 0's own (not yet published) entities.test_rediscovery_appends_so_running_inverters_keep_their_identityis nowtest_rediscovery_keeps_inverter_identity_by_endpoint.givtcp_rest[n]. The shipped templates only ever put placeholders at the tail, and a tail placeholder is unaffected.num_invertersto choose between the two behaviours, and rejected it: the GivTCP template tells REST users they can deletenum_inverters, so the users most exposed to this bug often won't have it set.soc_maxread falls through to Inverter's 8 kWh default and its control writes have nowhere to land. That lasts until the hourly re-probe adopts the endpoint, or indefinitely if the URL belongs to a decommissioned inverter. Main planned correctly in that case for users with no per-inverter lists, because it compressed the fleet down to what answered. I did not cap the gap fill: a cap has to fall back to compressing, and compressing is the Predbat GivTCP REST repeatedly setting inverter charge/discharge rate to wrong value, then correct value #5209 misroute for anyone who does have per-inverter settings. It would also have to be decided fleet-wide rather than per key, because deciding it per key reintroduces the index mismatch between keys. The startup log now names the URL and says to remove it fromgivtcp_restif that inverter no longer exists.battery_calibrationto be added totemplates/givenergy_givtcp.yaml. I left that out of scope: withgivtcp_restset, that key is auto-configured, and after this fix it comes out full length.impactratedautomatic_configand_keep_configured_tailLOW, and their only caller isrun().detect_changesshows only the GivTCP run → rediscover → automatic_config flows. I found nothing else that reads the order ofself.discovered._keep_configured_tail) and the PR fix(inverter): auto-create charge_rate entity for script-driven "power" inverters (#3311) #4645 bullet, which used the per-inverter list shape as a per-index source proxy, are updated in this PR. The proxy still holds past the last discovered endpoint, but gap slots below it are now filled.🤖 Generated with Claude Code