Skip to content

fix(ble): keep auto-reconnect alive when the rescan fails - #66

Merged
eigger merged 1 commit into
mainfrom
fix/obd-reconnect-scan-failure
Aug 1, 2026
Merged

fix(ble): keep auto-reconnect alive when the rescan fails#66
eigger merged 1 commit into
mainfrom
fix/obd-reconnect-scan-failure

Conversation

@eigger

@eigger eigger commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Auto-reconnect waits for an advertisement from the adapter's MAC before retrying, but that wait sat outside the retry loop's try/catch:

while (isActive) {
    waitForDevice()          // <- unguarded
    try { runObdSession(...) }
    catch (e: Exception) { ...; delay(3_000) }
}

Any failure inside waitForDevice escapes the while loop entirely, runs the finally, and terminates the connect() flow for good. Nothing is scanning after that, yet the last status emitted was Scanning, so the device sits in "scanning" forever and never reconnects — while a manual connect still works, because that path starts a fresh job with skipScan=true and dials the MAC directly instead of scanning. That matches the reported symptom exactly.

scanForMac can end without emitting (permission check returning early, or the underlying scan flow completing or erroring after Android refuses another scan start), and first() on an empty flow throws NoSuchElementException, so this is reachable in normal use rather than only on a hard error.

Move waitForDevice inside the try in both the OBD and GATT-notify loops so a scan failure is retried like any other session failure, and log the reason at LINK level so the next occurrence is visible instead of silent. Also make the missing-permission path in scanForMac throw SecurityException rather than returning an empty flow, so the cause is named instead of surfacing as an unrelated NoSuchElementException.

Auto-reconnect waits for an advertisement from the adapter's MAC before
retrying, but that wait sat outside the retry loop's try/catch:

    while (isActive) {
        waitForDevice()          // <- unguarded
        try { runObdSession(...) }
        catch (e: Exception) { ...; delay(3_000) }
    }

Any failure inside waitForDevice escapes the while loop entirely, runs the
finally, and terminates the connect() flow for good. Nothing is scanning
after that, yet the last status emitted was Scanning, so the device sits in
"scanning" forever and never reconnects — while a manual connect still works,
because that path starts a fresh job with skipScan=true and dials the MAC
directly instead of scanning. That matches the reported symptom exactly.

scanForMac can end without emitting (permission check returning early, or the
underlying scan flow completing or erroring after Android refuses another scan
start), and first() on an empty flow throws NoSuchElementException, so this is
reachable in normal use rather than only on a hard error.

Move waitForDevice inside the try in both the OBD and GATT-notify loops so a
scan failure is retried like any other session failure, and log the reason at
LINK level so the next occurrence is visible instead of silent. Also make the
missing-permission path in scanForMac throw SecurityException rather than
returning an empty flow, so the cause is named instead of surfacing as an
unrelated NoSuchElementException.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@eigger
eigger merged commit 385bf90 into main Aug 1, 2026
3 checks passed
@eigger
eigger deleted the fix/obd-reconnect-scan-failure branch August 1, 2026 13:21
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