diff --git a/homeassistant/components/bluetooth/__init__.py b/homeassistant/components/bluetooth/__init__.py index b6058767669..ea058a72759 100644 --- a/homeassistant/components/bluetooth/__init__.py +++ b/homeassistant/components/bluetooth/__init__.py @@ -71,7 +71,7 @@ ADDRESS: Final = "address" LOCAL_NAME: Final = "local_name" SERVICE_UUID: Final = "service_uuid" MANUFACTURER_ID: Final = "manufacturer_id" -MANUFACTURER_DATA_FIRST_BYTE: Final = "manufacturer_data_first_byte" +MANUFACTURER_DATA_START: Final = "manufacturer_data_start" BluetoothChange = Enum("BluetoothChange", "ADVERTISEMENT") @@ -157,14 +157,16 @@ def _ble_device_matches( return False if ( - matcher_manufacturer_data_first_byte := matcher.get( - MANUFACTURER_DATA_FIRST_BYTE + matcher_manufacturer_data_start := matcher.get(MANUFACTURER_DATA_START) + ) is not None: + matcher_manufacturer_data_start_bytes = bytearray( + matcher_manufacturer_data_start ) - ) is not None and not any( - matcher_manufacturer_data_first_byte == manufacturer_data[0] - for manufacturer_data in advertisement_data.manufacturer_data.values() - ): - return False + if not any( + manufacturer_data.startswith(matcher_manufacturer_data_start_bytes) + for manufacturer_data in advertisement_data.manufacturer_data.values() + ): + return False return True diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index a4f5350a167..17692476834 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -5,7 +5,7 @@ "documentation": "https://www.home-assistant.io/integrations/homekit_controller", "requirements": ["aiohomekit==1.1.4"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."], - "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_first_byte": 6 }], + "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }], "after_dependencies": ["zeroconf"], "codeowners": ["@Jc2k", "@bdraco"], "iot_class": "local_push", diff --git a/homeassistant/generated/bluetooth.py b/homeassistant/generated/bluetooth.py index feac27af1f1..03486b6043c 100644 --- a/homeassistant/generated/bluetooth.py +++ b/homeassistant/generated/bluetooth.py @@ -6,11 +6,13 @@ from __future__ import annotations # fmt: off -BLUETOOTH: list[dict[str, str | int]] = [ +BLUETOOTH: list[dict[str, str | int | list[int]]] = [ { "domain": "homekit_controller", "manufacturer_id": 76, - "manufacturer_data_first_byte": 6 + "manufacturer_data_start": [ + 6 + ] }, { "domain": "switchbot", diff --git a/homeassistant/loader.py b/homeassistant/loader.py index d0e6189ef96..9de06c48786 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -89,7 +89,7 @@ class BluetoothMatcherOptional(TypedDict, total=False): local_name: str service_uuid: str manufacturer_id: int - manufacturer_data_first_byte: int + manufacturer_data_start: list[int] class BluetoothMatcher(BluetoothMatcherRequired, BluetoothMatcherOptional): diff --git a/script/hassfest/bluetooth.py b/script/hassfest/bluetooth.py index 77a8779efbd..d8277213f27 100644 --- a/script/hassfest/bluetooth.py +++ b/script/hassfest/bluetooth.py @@ -14,7 +14,7 @@ from __future__ import annotations # fmt: off -BLUETOOTH: list[dict[str, str | int]] = {} +BLUETOOTH: list[dict[str, str | int | list[int]]] = {} """.strip() diff --git a/script/hassfest/manifest.py b/script/hassfest/manifest.py index 4f76fb9ed1e..9c1bd0a63f3 100644 --- a/script/hassfest/manifest.py +++ b/script/hassfest/manifest.py @@ -196,7 +196,7 @@ MANIFEST_SCHEMA = vol.Schema( vol.Optional("service_uuid"): vol.All(str, verify_lowercase), vol.Optional("local_name"): vol.All(str), vol.Optional("manufacturer_id"): int, - vol.Optional("manufacturer_data_first_byte"): int, + vol.Optional("manufacturer_data_start"): [int], } ) ], diff --git a/tests/components/bluetooth/test_init.py b/tests/components/bluetooth/test_init.py index ec737cef593..a31f911f6a7 100644 --- a/tests/components/bluetooth/test_init.py +++ b/tests/components/bluetooth/test_init.py @@ -153,12 +153,12 @@ async def test_discovery_match_by_local_name(hass, mock_bleak_scanner_start): async def test_discovery_match_by_manufacturer_id_and_first_byte( hass, mock_bleak_scanner_start ): - """Test bluetooth discovery match by manufacturer_id and manufacturer_data_first_byte.""" + """Test bluetooth discovery match by manufacturer_id and manufacturer_data_start.""" mock_bt = [ { "domain": "homekit_controller", "manufacturer_id": 76, - "manufacturer_data_first_byte": 0x06, + "manufacturer_data_start": [0x06, 0x02, 0x03], } ] with patch( @@ -174,7 +174,9 @@ async def test_discovery_match_by_manufacturer_id_and_first_byte( hkc_device = BLEDevice("44:44:33:11:23:45", "lock") hkc_adv = AdvertisementData( - local_name="lock", service_uuids=[], manufacturer_data={76: b"\x06"} + local_name="lock", + service_uuids=[], + manufacturer_data={76: b"\x06\x02\x03\x99"}, ) models.HA_BLEAK_SCANNER._callback(hkc_device, hkc_adv) diff --git a/tests/test_loader.py b/tests/test_loader.py index b8a469f80aa..da788e0db75 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -205,7 +205,7 @@ def test_integration_properties(hass): {"hostname": "tesla_*", "macaddress": "98ED5C*"}, {"registered_devices": True}, ], - "bluetooth": [{"manufacturer_id": 76, "manufacturer_data_first_byte": 6}], + "bluetooth": [{"manufacturer_id": 76, "manufacturer_data_start": [0x06]}], "usb": [ {"vid": "10C4", "pid": "EA60"}, {"vid": "1CF1", "pid": "0030"}, @@ -244,7 +244,7 @@ def test_integration_properties(hass): {"vid": "10C4", "pid": "8A2A"}, ] assert integration.bluetooth == [ - {"manufacturer_id": 76, "manufacturer_data_first_byte": 6} + {"manufacturer_id": 76, "manufacturer_data_start": [0x06]} ] assert integration.ssdp == [ {