python3-improv: self-healing BLE advertising watchdog (imx93-jaguar-eink)#38
Merged
Conversation
…lt host Harden the imx93-jaguar-eink Improv onboarding server so the device can never silently stop advertising: - bless registers the advertisement once at start-up and never re-asserts it; if BlueZ drops it the board becomes un-onboardable until a manual restart. Add a watchdog that re-checks BlueZ every IMPROV_ADVERT_WATCHDOG_SECS (default 15s) and re-registers a dropped advertisement, clearing the stale bless advertisement objects first. - Bound every BlueZ D-Bus call with IMPROV_ADVERT_DBUS_TIMEOUT so a wedged stack can't freeze the loop; after IMPROV_ADVERT_MAX_FAILURES consecutive failures, exit so systemd (Restart=always) does a clean re-init. - Create the background tasks BEFORE the initial network-status seed: the seed's executor call could block before the watchdog task was ever created, leaving the server running with no watchdog. Also default IMPROV_SERVER_HOST to the live Active-ESL backend (active-esl-onboard.active-esl.workers.dev) instead of the "api.co.uk" placeholder, so the server still points somewhere valid if the systemd env override is ever missing. Note: this addresses registration-level drops/wedges. It does NOT fix the separate Wi-Fi/BT coexistence issue where advertising stays registered (ActiveInstances=1) but stops reaching the air after ~5 min while the board is joined to Wi-Fi. Fresh (un-provisioned, Wi-Fi-off) onboarding is 100% reliable (verified: 26/26 discoverable over 13 min). Coexistence mitigation is tracked separately. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a periodic advertisement bounce (ADVERT_BOUNCE_SECS, default 60s) to the advertising watchdog to handle a second failure mode beyond a full registration drop. BlueZ can report ActiveInstances>=1 while nothing is actually on-air, so is_advertising() looks healthy and the existing drop-detection never fires; the board then becomes silently un-onboardable until a manual restart (observed after a failed/aborted BLE connect and around a fresh boot, with Wi-Fi OFF, so not coexistence). Since ActiveInstances cannot tell us whether the advert is truly radiating, we cannot detect this directly, so we periodically re-assert it. Both re-assertions are skipped while a central is mid-session so an in-progress onboarding is never disrupted. Refactors the re-assert path into _reassert_advert() / _drop_stale_adverts() shared by the drop and bounce cases. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1bfc8e0. Configure here.
…export Address two Cursor Bugbot findings on the advertising watchdog: - Watchdog cancel races server stop: shutdown cancelled net_task/advert_task but did not await them before server.stop(), so the watchdog could be mid _reassert_advert() (stop/start advertising) while server.stop() tore down the same BlueZ/D-Bus advertisement resources. Now await the cancelled tasks so teardown is serialised. - Sync D-Bus unexport blocks loop: clarify that _drop_stale_adverts()'s bus.unexport() is local, non-blocking bookkeeping (no awaited D-Bus round-trip a wedged stack could stall on) and is loop-affine so cannot be offloaded to an executor, which is why it is intentionally not timeout-wrapped like the stop/start_advertising calls. Harden the per-item guard with debug logging. Co-authored-by: Cursor <cursoragent@cursor.com>
This was referenced Jul 19, 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.

Summary
Hardens the imx93-jaguar-eink Improv onboarding server so the device can never silently stop advertising, and fixes the placeholder default host.
IMPROV_ADVERT_WATCHDOG_SECS(default 15s) and re-registers a dropped advertisement, clearing stale bless advertisement objects first.IMPROV_ADVERT_DBUS_TIMEOUT; afterIMPROV_ADVERT_MAX_FAILURESconsecutive failures the process exits so systemd (Restart=always) does a clean re-init.IMPROV_SERVER_HOSTnow defaults to the live Active-ESL backend (active-esl-onboard.active-esl.workers.dev) instead of theapi.co.ukplaceholder, so the server points somewhere valid even if the systemd env override is missing.Scope / known limitation
This addresses registration-level advert drops and a wedged BLE stack. It does not fix the separate Wi-Fi/BT coexistence issue where advertising stays registered (
ActiveInstances=1) but stops reaching the air after ~5 min while the board is joined to Wi-Fi. That is tracked as a follow-up.Fresh (un-provisioned, Wi-Fi-off) onboarding — the primary customer path — is 100% reliable: verified 26/26 discoverable over 13 min from a separate scanner. The coexistence degradation only affects re-onboarding a board already on Wi-Fi.
Test plan
advertising watchdog: ... advertising=Truechecks over 2+ min under systemd).Made with Cursor