Add raw advertisement data to Bluetooth WebSocket API (#150358)

This commit is contained in:
J. Nick Koston
2025-08-10 02:44:15 -05:00
committed by GitHub
parent 1c603f968f
commit 865b3a6646
3 changed files with 22 additions and 3 deletions

View File

@@ -39,7 +39,13 @@ def async_setup(hass: HomeAssistant) -> None:
def serialize_service_info(
service_info: BluetoothServiceInfoBleak, time_diff: float
) -> dict[str, Any]:
"""Serialize a BluetoothServiceInfoBleak object."""
"""Serialize a BluetoothServiceInfoBleak object.
The raw field is included for:
1. Debugging - to see the actual advertisement packet
2. Data freshness - manufacturer_data and service_data are aggregated
across multiple advertisements, raw shows the latest packet only
"""
return {
"name": service_info.name,
"address": service_info.address,
@@ -57,6 +63,7 @@ def serialize_service_info(
"connectable": service_info.connectable,
"time": service_info.time + time_diff,
"tx_power": service_info.tx_power,
"raw": service_info.raw.hex() if service_info.raw else None,
}

View File

@@ -145,6 +145,7 @@ def inject_advertisement_with_time_and_source_connectable(
time: float,
source: str,
connectable: bool,
raw: bytes | None = None,
) -> None:
"""Inject an advertisement into the manager from a specific source at a time and connectable status."""
async_get_advertisement_callback(hass)(
@@ -161,6 +162,7 @@ def inject_advertisement_with_time_and_source_connectable(
connectable=connectable,
time=time,
tx_power=adv.tx_power,
raw=raw,
)
)

View File

@@ -22,6 +22,7 @@ from . import (
generate_advertisement_data,
generate_ble_device,
inject_advertisement_with_source,
inject_advertisement_with_time_and_source_connectable,
)
from tests.common import MockConfigEntry, async_fire_time_changed
@@ -72,6 +73,7 @@ async def test_subscribe_advertisements(
"source": HCI0_SOURCE_ADDRESS,
"time": ANY,
"tx_power": -127,
"raw": None,
}
]
}
@@ -83,8 +85,15 @@ async def test_subscribe_advertisements(
service_uuids=[],
rssi=-80,
)
inject_advertisement_with_source(
hass, switchbot_device_signal_100, switchbot_adv_signal_100, HCI1_SOURCE_ADDRESS
# Inject with raw bytes data
inject_advertisement_with_time_and_source_connectable(
hass,
switchbot_device_signal_100,
switchbot_adv_signal_100,
time.monotonic(),
HCI1_SOURCE_ADDRESS,
True,
raw=b"\x02\x01\x06\x03\x03\x0f\x18",
)
async with asyncio.timeout(1):
response = await client.receive_json()
@@ -101,6 +110,7 @@ async def test_subscribe_advertisements(
"source": HCI1_SOURCE_ADDRESS,
"time": ANY,
"tx_power": -127,
"raw": "02010603030f18",
}
]
}