Skip to content

fix(discovery): response-driven PC-Link inventory progress (no more 0→99 jump)#459

Merged
fdebrus merged 1 commit into
mainfrom
claude/discovery-identity-progress
Jun 9, 2026
Merged

fix(discovery): response-driven PC-Link inventory progress (no more 0→99 jump)#459
fdebrus merged 1 commit into
mainfrom
claude/discovery-identity-progress

Conversation

@fdebrus

@fdebrus fdebrus commented Jun 9, 2026

Copy link
Copy Markdown
Owner

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.474 inventory starts
  • 21:49:25.624all 96 reads queued (150 ms)
  • 21:49:50.164 — phase completes, ~25 s later, with the 94 $2E answers streaming back over that window (25.7 → 40.1)

The library emits on_progress per 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 $2E answers already flow through _discovery_frame_callback as 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 $2E answer into discovery_identity_responses and 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)

before after
after 150 ms queue burst 99.9 % 33 %
as answers arrive (24/48/72/94) frozen 99.9 % 50 / 67 / 83 / 99 %
finished 100 % 100 %

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, ruff clean, mypy 100 (= baseline).

https://claude.ai/code/session_01LH7yGDY8ttvZUVMVjfSNXj


Generated by Claude Code

…->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
@fdebrus fdebrus merged commit 596fc1a into main Jun 9, 2026
8 checks passed
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.

2 participants