fix(discovery): response-driven PC-Link inventory progress (no more 0→99 jump)#459
Merged
Merged
Conversation
…->99 jump) Diagnosed from a real scan log: the bar jumps 0->99% then freezes ~25s. Root cause: the library's identity phase (the bulk of a PC-Link inventory / Load Project Overview) queues all N×96 register reads up front — the log shows 96 reads QUEUED in 150 ms (21:49:25.5xx) while the phase doesn't COMPLETE until 21:49:50.1 (~25 s of bus round-trips, 94 $2E answers streaming back over that window). Because the library emits on_progress per QUEUED command, all 96 progress events fire in that 150 ms burst: the bar races to ~99% instantly, then sits frozen for the 25 s the scan actually takes (zero further emits), then snaps to 100. #458 fixed the inventory '1/1' freeze and the probing drop; this is the distinct identity-phase queue-ahead glitch. Fix (HA-side, no library change): drive the identity bar from RESPONSES, not queued commands. The $2E answers flow through _discovery_frame_callback as they arrive — exactly the real progress. - _handle_discovery_progress, identity branch: capture the expected total (module_total × register_total = N×96) and return early; do NOT let the racing queued counters (module_index / registers_sent) drive the bar. - _discovery_frame_callback: during identity, count each $2E answer into discovery_identity_responses and refresh the bar/message. - discovery_progress_percent, identity branch: phase_frac = responses/expected (falls back to the old module-index estimate when the per-address total isn't known — older libraries). Verified against the log's values (1 address × 96 reads, 94 responses): before = 99.9% after 150 ms then frozen; after = 33% -> smoothly 34/40/50/67/83/99% as answers arrive -> 100%. Register-scan (Load Existing Installation) was already real-time (synchronous send-and-wait) and is unchanged. Tests: +2 (response-driven vs queue-driven regression; identity midpoint tracks responses); 3 existing updated for the new response-driven behaviour. 446 passed, ruff clean, mypy 100 (= baseline). https://claude.ai/code/session_01LH7yGDY8ttvZUVMVjfSNXj
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.
Summary
Your scan log pinned it exactly. The PC-Link inventory bar jumps 0 → 99 % then freezes ~25 s — and it's a different bug from the ones #458 fixed.
Root cause (from the log)
The identity phase (the bulk of a "Load Project Overview") queues all N×96 register reads up front:
21:49:25.474inventory starts21:49:25.624— all 96 reads queued (150 ms)21:49:50.164— phase completes, ~25 s later, with the 94$2Eanswers streaming back over that window (25.7 → 40.1)The library emits
on_progressper queued command, so all 96 progress events fire in that 150 ms burst → the bar races to ~99 % instantly, then sits frozen for the 25 s the scan actually takes (zero further emits), then snaps to 100.Fix (HA-side, no library change)
Drive the identity bar from responses, not queued commands — the
$2Eanswers already flow through_discovery_frame_callbackas they arrive:_handle_discovery_progress(identity): capture the expected total (module_total × register_total= N×96) and return early — don't let the racing queued counters drive the bar._discovery_frame_callback: during identity, count each$2Eanswer intodiscovery_identity_responsesand refresh the bar/message.discovery_progress_percent(identity):phase_frac = responses / expected(falls back to the old module-index estimate for older libraries that don't surface the per-address total).Verified against the log's actual values (1 address × 96 reads, 94 responses)
Smooth and monotonic, tracking the real 25 s scan. Register-scan ("Load Existing Installation") was already real-time (synchronous send-and-wait) and is unchanged.
Tests
+2 regressions (response-driven vs queue-driven; identity midpoint tracks responses); 3 existing tests updated for the new behaviour.
446 passed,ruffclean,mypy100 (= baseline).https://claude.ai/code/session_01LH7yGDY8ttvZUVMVjfSNXj
Generated by Claude Code