Skip to content

feat(ble-proxy): add AdvertisementData.from_bleak() factory#680

Open
Apollon77 wants to merge 1 commit into
mainfrom
feat/ble-proxy-bleak-advertisement-api
Open

feat(ble-proxy): add AdvertisementData.from_bleak() factory#680
Apollon77 wants to merge 1 commit into
mainfrom
feat/ble-proxy-bleak-advertisement-api

Conversation

@Apollon77
Copy link
Copy Markdown
Collaborator

@Apollon77 Apollon77 commented May 24, 2026

Summary

  • Add an additive AdvertisementData.from_bleak(address, connectable, bleak_advertisement) classmethod on the Python matter_ble_proxy library. Integrators that already hold a bleak.backends.scanner.AdvertisementData — Home Assistant's BluetoothServiceInfoBleak.advertisement, raw bleak.BleakScanner setups, ESPHome BLE proxies — can build the library's wire dataclass with one call instead of copying seven fields by hand.
  • The factory drops tx_power and platform_data (not part of the wire schema) and requires address + connectable explicitly, because bleak.AdvertisementData intentionally carries neither (the first lives on the paired BLEDevice, the second on the scan context).
  • The default BleakScanSource is updated to dogfood the factory; the local_name or device.name fallback is preserved by _replace-ing local_name on the bleak NamedTuple before forwarding.

Non-breaking — the existing public BleScanSource callback contract, AdvertisementData constructor, and __init__.py export surface are unchanged. Adopting the factory is opt-in.

Resolves #679.

Follow-up: Home Assistant adjustments (after this PR merges + a matter-ble-proxy release)

homeassistant/components/matter/ble_proxy.py in home-assistant/core#171384 can simplify _to_advertisement_data to a single AdvertisementData.from_bleak call:

 from bleak.backends.device import BLEDevice
 from home_assistant_bluetooth import BluetoothServiceInfoBleak
 from matter_ble_proxy import (
     AdvertisementData,
     BleDeviceResolver,
     BleScanSource,
     MatterBleProxy,
 )

 ...

         @callback
         def _on_advertisement(
             service_info: BluetoothServiceInfoBleak,
             _change: object,
         ) -> None:
             try:
-                callback_fn(_to_advertisement_data(service_info))
+                callback_fn(
+                    AdvertisementData.from_bleak(
+                        service_info.address,
+                        service_info.connectable,
+                        service_info.advertisement,
+                    )
+                )
             except Exception:
                 _LOGGER.exception("BLE proxy advertisement forward failed")

Then delete the _to_advertisement_data helper entirely (the whole def _to_advertisement_data(...) block at the bottom of the file). Net result on HA side: three attribute reads + one factory call, instead of a seven-field manual translation. Renames or removals on bleak.AdvertisementData would surface as a typing error rather than silently dropping fields.

Per @bdraco's review comment thread on _to_advertisement_data.

Test plan

  • python_ble_proxy pytest suite passes (8/8, two new tests cover from_bleak)
  • ruff check + ruff format --check clean
  • mypy clean
  • After merge + a matter-ble-proxy release: apply the HA diff above in #171384 and verify commissioning still works end-to-end

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 24, 2026 15:42
@Apollon77 Apollon77 requested a review from TheJulianJES May 24, 2026 15:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the python_ble_proxy integration surface to accept Bleak’s native bleak.backends.scanner.AdvertisementData in the scan callback (with address and connectable passed explicitly), removing the library’s internal AdvertisementData dataclass while keeping the on-wire device_discovered JSON schema unchanged.

Changes:

  • Replace BleScanSource callback contract from a library dataclass to (address, connectable, bleak AdvertisementData).
  • Remove the internal AdvertisementData dataclass and build device_discovered payloads directly from Bleak’s shape.
  • Update Bleak backend + docs/exports/tests to match the new contract.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
python_ble_proxy/matter_ble_proxy/client.py Updates callback typing/contract and rewires scan event mapping to use Bleak AdvertisementData + explicit address/connectable.
python_ble_proxy/matter_ble_proxy/bleak_backend.py Stops building the removed dataclass; forwards (device.address, True, advertisement) and preserves prior name fallback via _replace(local_name=...).
python_ble_proxy/matter_ble_proxy/protocol.py Deletes the internal AdvertisementData dataclass definition.
python_ble_proxy/matter_ble_proxy/init.py Removes AdvertisementData from exports.
python_ble_proxy/README.md Updates integrator docs to describe the new callback signature and Bleak type.
python_ble_proxy/tests/test_protocol.py Removes the AdvertisementData defaulting test now that the type is deleted.
CHANGELOG.md Adds a WIP entry describing the new callback signature.
Comments suppressed due to low confidence (1)

python_ble_proxy/matter_ble_proxy/client.py:361

  • The scan callback contract and the device_discovered payload are now derived from bleak’s AdvertisementData (local_namename, plus explicit address/connectable). There’s no unit test exercising this mapping/dedup behavior, so regressions (wrong field, missing connectable, incorrect dedup keying) won’t be caught. Consider adding a test that runs _handle_start_scan with a fake BleScanSource and asserts the emitted device_discovered payload and duplicate suppression.
        def _on_advertisement(address: str, connectable: bool, ad: BleakAdvertisementData) -> None:
            if service_uuid_set is not None:
                advertised = {_normalize_uuid(u) for u in ad.service_uuids}
                # Some stacks only surface the service UUID via its service_data key,
                # so include those too. _normalize_uuid collapses Bleak's canonical

Comment thread python_ble_proxy/matter_ble_proxy/client.py Outdated
Comment thread CHANGELOG.md Outdated
@Apollon77 Apollon77 force-pushed the feat/ble-proxy-bleak-advertisement-api branch from 21e9063 to 9566391 Compare May 24, 2026 16:00
@Apollon77 Apollon77 changed the title feat(ble-proxy): accept bleak.AdvertisementData directly in scan callback feat(ble-proxy): add AdvertisementData.from_bleak() factory May 24, 2026
@Apollon77 Apollon77 requested a review from Copilot May 24, 2026 16:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread python_ble_proxy/matter_ble_proxy/protocol.py Outdated
Add an additive `AdvertisementData.from_bleak(address, connectable,
bleak_advertisement)` classmethod to the Python `matter_ble_proxy`
library, so integrators that already have a
`bleak.backends.scanner.AdvertisementData` (Home Assistant's
`BluetoothServiceInfoBleak.advertisement`, raw Bleak wrappers,
ESPHome BLE proxies, ...) can build the library's wire dataclass
without copying seven fields by hand.

The existing public API (`BleScanSource` callback contract,
`AdvertisementData` constructor, `__init__` export surface) is
unchanged — this is purely additive. The default `BleakScanSource`
now uses the new factory internally; the `local_name or device.name`
fallback is preserved via `advertisement._replace`.

Resolves #679.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Apollon77 Apollon77 force-pushed the feat/ble-proxy-bleak-advertisement-api branch from 9566391 to 5256f8e Compare May 24, 2026 16:16
@Apollon77 Apollon77 requested a review from Copilot May 24, 2026 16:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

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.

Accept bleak.AdvertisementData directly in advertisement forwarding API

2 participants