Skip to content

Keep passive scans continuous and support instant batched updates - #1558

Open
rmounce wants to merge 3 commits into
custom-components:masterfrom
rmounce:feature/continuous-scan
Open

Keep passive scans continuous and support instant batched updates#1558
rmounce wants to merge 3 commits into
custom-components:masterfrom
rmounce:feature/continuous-scan

Conversation

@rmounce

@rmounce rmounce commented Jul 20, 2026

Copy link
Copy Markdown

Summary

This PR contains three intentionally separate commits that improve passive HCI scanning and low-latency measurement delivery:

  • decouple scanner lifetime from the measurement aggregation period
  • add a configurable per-adapter raw-HCI inactivity watchdog
  • add backward-compatible periodic/instant measurement update policies, including per-device overrides
  • parse every legacy or extended advertising report in batched HCI LE meta-events

The commits are kept separate so the scanner lifecycle, instant delivery, and multi-report parser work can be split into smaller PRs if preferred during review.

Motivation and root cause

Restarting the HCI scanner after every aggregation period creates avoidable scan downtime. With period: 1, a TP-Link UB500 was repeatedly closing and reopening its HCI socket and losing advertisements.

After continuous scanning and instant updates were enabled, matched captures identified a second UB500-specific loss mechanism. The adapter commonly emits LE Extended Advertising Report events containing two to five reports. BleParser.parse_raw_data() assumed exactly one report and rejected the complete HCI event whenever its total length exceeded the first report's length.

Behavior

  • Successful passive scans remain running independently of period.
  • hci_inactivity_timeout defaults to 60 seconds and accepts 0 to disable recovery.
  • Raw activity uses time.monotonic() and is tracked per HCI adapter before packet recognition or duplicate filtering.
  • Failed scan setup retains the existing rate-limited bt_auto_restart recovery path.
  • measurement_update defaults to periodic; instant publishes each parser-accepted packet without mean or median filtering.
  • Device-level default, periodic, and instant values follow the existing override/inheritance pattern.
  • Instant updates use only the current packet RSSI and avoid writing before Home Assistant has attached the entity.
  • Existing ATC/PVVX packet-ID duplicate filtering is preserved.
  • Legacy (0x02) and extended (0x0D) batched HCI events are split into individual reports before using the existing advertisement parser.
  • Unknown or malformed report content does not discard other safely framed reports in the same event.

Existing periodic aggregation remains the default for backward compatibility.

Validation

  • 336 tests passed, including focused watchdog, instant-mode, duplicate-ID, legacy multi-report, extended multi-report, mixed known/unknown, truncated-report, and HCIdump fan-out tests.
  • isort, codespell, Python compilation, JSON validation, and git diff --check passed.
  • Live Home Assistant validation with a TP-Link UB500 processed HCI events containing up to five reports.
  • In a matched 41-second raw-HCI/recorder window, 11 of 12 PVVX thermometers had exactly matching raw distinct packet-ID and Home Assistant update counts. The remaining device had one capture-boundary state row.
  • No scanner watchdog/restart errors or new kernel USB/HCI disconnect or -71 errors occurred during validation.

Configuration example

ble_monitor:
  hci_inactivity_timeout: 60
  measurement_update: instant

PR description drafted by OpenAI Codex.

rmounce and others added 3 commits July 20, 2026 22:16
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
@rmounce
rmounce marked this pull request as ready for review July 20, 2026 12:57
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.

1 participant