Skip to content

feat: add optional validate_connection callback to establish_connection#225

Closed
cgoudie wants to merge 1 commit intoBluetooth-Devices:mainfrom
TechBlueprints:feat/validate-connection
Closed

feat: add optional validate_connection callback to establish_connection#225
cgoudie wants to merge 1 commit intoBluetooth-Devices:mainfrom
TechBlueprints:feat/validate-connection

Conversation

@cgoudie
Copy link

@cgoudie cgoudie commented Feb 16, 2026

Summary

  • Adds an optional validate_connection parameter to establish_connection() — an async callback Callable[[BleakClient], Awaitable[bool]] that is invoked after every successful connect().
  • If the callback returns False or raises any exception, the client is disconnected and the attempt is retried until max_attempts is exhausted.
  • Defaults to None so existing callers are completely unaffected — no API contract change.

Motivation

A successful BLE connect() does not guarantee the connection is actually usable. The device may accept the connection but fail to respond to GATT reads/writes. This callback lets the calling application verify the connection is live (e.g. read a characteristic, send a command and check the response) before establish_connection returns.

Example usage

async def validate(client: BleakClient) -> bool:
    """Read the device info characteristic to prove the link is alive."""
    value = await client.read_gatt_char("00002a29-0000-1000-8000-00805f9b34fb")
    return len(value) > 0

client = await establish_connection(
    BleakClient,
    device,
    "my-sensor",
    validate_connection=validate,
)

Test plan

  • test_establish_connection_validate_connection_passes — callback returns True, client returned
  • test_establish_connection_validate_connection_fails_then_passes — first call returns False (disconnect + retry), second call returns True
  • test_establish_connection_validate_connection_exception_treated_as_false — callback raises RuntimeError, treated as failure, retry succeeds
  • test_establish_connection_validate_connection_exhausts_retries — callback always returns False, raises BleakConnectionError after max_attempts
  • test_establish_connection_no_validate_connection — no callback provided, behaviour unchanged
  • All existing tests pass (50 passed, 1 skipped)
  • All pre-commit hooks pass (black, flake8, mypy, bandit, isort, etc.)

Made with Cursor

Allow callers to supply an async callback that verifies a connection is
actually usable after connect() succeeds (e.g. send a command and check
the response).  If the callback returns False or raises any exception
the client is disconnected and the attempt is retried until max_attempts
is exhausted.

The parameter is fully optional (defaults to None) so existing callers
are unaffected.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bdraco bdraco closed this Feb 16, 2026
@codecov
Copy link

codecov bot commented Feb 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.10%. Comparing base (69ea901) to head (61a281b).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #225      +/-   ##
==========================================
+ Coverage   79.64%   80.10%   +0.45%     
==========================================
  Files           6        6              
  Lines         570      583      +13     
  Branches      112      114       +2     
==========================================
+ Hits          454      467      +13     
  Misses         70       70              
  Partials       46       46              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bdraco
Copy link
Member

bdraco commented Feb 16, 2026

@cgoudie Please stop opening PRs. You are leaving me no choice but to ban you from the org

@bdraco
Copy link
Member

bdraco commented Feb 16, 2026

I turned off PRs for 24 hours to stop the spam

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

Comments