Match the known address first in Yale Access Bluetooth discovery (#182018)

This commit is contained in:
Franck Nijhof
2026-09-14 07:56:38 +02:00
committed by GitHub
parent a3c91078aa
commit ef3acfda24
3 changed files with 68 additions and 4 deletions
+15 -4
View File
@@ -37,13 +37,24 @@ def async_find_existing_service_info(
) -> BluetoothServiceInfoBleak | None:
"""Return the service info for the given local_name and address."""
has_unique_local_name = local_name_is_unique(local_name)
by_local_name: BluetoothServiceInfoBleak | None = None
for service_info in async_discovered_service_info(hass):
device = service_info.device
if (
has_unique_local_name and device.name == local_name
) or device.address == address:
if device.address == address:
return service_info
return None
# The local name is all we have to go on when the address is hidden
# behind a system UUID, but anything can advertise that name, so it
# only counts when nothing answers to the address we were given.
if (
by_local_name is None
and has_unique_local_name
and device.name == local_name
):
by_local_name = service_info
return by_local_name
def short_address(address: str) -> str:
+17
View File
@@ -41,6 +41,23 @@ LOCK_DISCOVERY_INFO_UUID_ADDRESS = BluetoothServiceInfoBleak(
tx_power=-127,
)
SAME_LOCAL_NAME_DISCOVERY_INFO = BluetoothServiceInfoBleak(
name="M1012LU",
address="A8:51:AB:91:1C:FA",
rssi=-40,
manufacturer_data={
76: b"\x061\x00Z\x8f\x93\xb2\xec\x85\x06\x00i\x00\x02\x02Q\xed\x1d\xf0"
},
service_uuids=[],
service_data={},
source="local",
device=generate_ble_device(address="A8:51:AB:91:1C:FA", name="M1012LU"),
advertisement=generate_advertisement_data(),
time=0,
connectable=True,
tx_power=-127,
)
OLD_FIRMWARE_LOCK_DISCOVERY_INFO = BluetoothServiceInfoBleak(
name="Aug",
address="AA:BB:CC:DD:EE:FF",
@@ -23,6 +23,7 @@ from . import (
LOCK_DISCOVERY_INFO_UUID_ADDRESS,
NOT_YALE_DISCOVERY_INFO,
OLD_FIRMWARE_LOCK_DISCOVERY_INFO,
SAME_LOCAL_NAME_DISCOVERY_INFO,
YALE_ACCESS_LOCK_DISCOVERY_INFO,
)
@@ -579,6 +580,41 @@ async def test_integration_discovery_success(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1
async def test_integration_discovery_prefers_address(hass: HomeAssistant) -> None:
"""Test integration discovery binds to the address it was handed."""
with patch(
"homeassistant.components.yalexs_ble.util.async_discovered_service_info",
# Another device is advertising the same cached local name, and it is
# seen before the lock itself
return_value=[
SAME_LOCAL_NAME_DISCOVERY_INFO,
YALE_ACCESS_LOCK_DISCOVERY_INFO,
],
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
data={
"name": "Front Door",
"address": YALE_ACCESS_LOCK_DISCOVERY_INFO.address,
"key": "2fd51b8621c6a139eaffbedcb846b60f",
"slot": 66,
"serial": "M1XXX012LU",
},
)
assert result["type"] is FlowResultType.FORM
with patch(
"homeassistant.components.yalexs_ble.async_setup_entry",
return_value=True,
):
result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {})
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["data"][CONF_ADDRESS] == YALE_ACCESS_LOCK_DISCOVERY_INFO.address
async def test_integration_discovery_device_not_found(hass: HomeAssistant) -> None:
"""Test integration discovery when the device is not found."""
with patch(