diff --git a/homeassistant/components/matter/adapter.py b/homeassistant/components/matter/adapter.py index fbc027091b4..7d73ceafc7a 100644 --- a/homeassistant/components/matter/adapter.py +++ b/homeassistant/components/matter/adapter.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast +from matter_server.client.models.device_types import BridgedDevice from matter_server.common.models import EventType, ServerInfoMessage from homeassistant.config_entries import ConfigEntry @@ -20,6 +21,14 @@ if TYPE_CHECKING: from matter_server.client.models.node import MatterEndpoint, MatterNode +def get_clean_name(name: str | None) -> str | None: + """Strip spaces and null char from the name.""" + if name is None: + return name + name = name.replace("\x00", "") + return name.strip() or None + + class MatterAdapter: """Connect Matter into Home Assistant.""" @@ -70,11 +79,27 @@ class MatterAdapter: server_info = cast(ServerInfoMessage, self.matter_client.server_info) basic_info = endpoint.device_info - name = basic_info.nodeLabel or basic_info.productLabel or basic_info.productName + # use (first) DeviceType of the endpoint as fallback product name + device_type = next( + ( + x + for x in endpoint.device_types + if x.device_type != BridgedDevice.device_type + ), + None, + ) + name = ( + get_clean_name(basic_info.nodeLabel) + or get_clean_name(basic_info.productLabel) + or get_clean_name(basic_info.productName) + or device_type.__class__.__name__ + if device_type + else None + ) # handle bridged devices bridge_device_id = None - if endpoint.is_bridged_device: + if endpoint.is_bridged_device and endpoint.node.endpoints[0] != endpoint: bridge_device_id = get_device_id( server_info, endpoint.node.endpoints[0], @@ -91,14 +116,19 @@ class MatterAdapter: # prefix identifier with 'serial_' to be able to filter it identifiers.add((DOMAIN, f"{ID_TYPE_SERIAL}_{basic_info.serialNumber}")) + model = ( + get_clean_name(basic_info.productName) or device_type.__class__.__name__ + if device_type + else None + ) dr.async_get(self.hass).async_get_or_create( name=name, config_entry_id=self.config_entry.entry_id, identifiers=identifiers, hw_version=basic_info.hardwareVersionString, sw_version=basic_info.softwareVersionString, - manufacturer=basic_info.vendorName, - model=basic_info.productName, + manufacturer=basic_info.vendorName or endpoint.node.device_info.vendorName, + model=model, via_device=(DOMAIN, bridge_device_id) if bridge_device_id else None, ) diff --git a/tests/components/matter/fixtures/nodes/onoff-light-alt-name.json b/tests/components/matter/fixtures/nodes/onoff-light-alt-name.json new file mode 100644 index 00000000000..8b1f1004e59 --- /dev/null +++ b/tests/components/matter/fixtures/nodes/onoff-light-alt-name.json @@ -0,0 +1,411 @@ +{ + "node_id": 1, + "date_commissioned": "2022-11-29T21:23:48.485051", + "last_interview": "2022-11-29T21:23:48.485057", + "interview_version": 2, + "attributes": { + "0/4/0": 128, + "0/4/65532": 1, + "0/4/65533": 4, + "0/4/65528": [0, 1, 2, 3], + "0/4/65529": [0, 1, 2, 3, 4, 5], + "0/4/65531": [0, 65528, 65529, 65531, 65532, 65533], + "0/29/0": [ + { + "type": 22, + "revision": 1 + } + ], + "0/29/1": [ + 4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62, 63, + 64, 65 + ], + "0/29/2": [41], + "0/29/3": [1], + "0/29/65532": 0, + "0/29/65533": 1, + "0/29/65528": [], + "0/29/65529": [], + "0/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/31/0": [ + { + "privilege": 5, + "authMode": 2, + "subjects": [112233], + "targets": null, + "fabricIndex": 1 + } + ], + "0/31/1": [], + "0/31/2": 4, + "0/31/3": 3, + "0/31/4": 3, + "0/31/65532": 0, + "0/31/65533": 1, + "0/31/65528": [], + "0/31/65529": [], + "0/31/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533], + "0/40/0": 1, + "0/40/1": "Nabu Casa", + "0/40/2": 65521, + "0/40/3": "Mock Light", + "0/40/4": 32768, + "0/40/5": "Mock OnOff Light \u0000", + "0/40/6": "XX", + "0/40/7": 0, + "0/40/8": "v1.0", + "0/40/9": 1, + "0/40/10": "v1.0", + "0/40/11": "20200101", + "0/40/12": "", + "0/40/13": "", + "0/40/14": "", + "0/40/15": "12345678", + "0/40/16": false, + "0/40/17": true, + "0/40/18": "mock-onoff-light", + "0/40/19": { + "caseSessionsPerFabric": 3, + "subscriptionsPerFabric": 3 + }, + "0/40/65532": 0, + "0/40/65533": 1, + "0/40/65528": [], + "0/40/65529": [], + "0/40/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 65528, 65529, 65531, 65532, 65533 + ], + "0/42/0": [], + "0/42/1": true, + "0/42/2": 0, + "0/42/3": 0, + "0/42/65532": 0, + "0/42/65533": 1, + "0/42/65528": [], + "0/42/65529": [0], + "0/42/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/43/0": "en-US", + "0/43/1": [ + "en-US", + "de-DE", + "fr-FR", + "en-GB", + "es-ES", + "zh-CN", + "it-IT", + "ja-JP" + ], + "0/43/65532": 0, + "0/43/65533": 1, + "0/43/65528": [], + "0/43/65529": [], + "0/43/65531": [0, 1, 65528, 65529, 65531, 65532, 65533], + "0/44/0": 0, + "0/44/1": 0, + "0/44/2": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 7], + "0/44/65532": 0, + "0/44/65533": 1, + "0/44/65528": [], + "0/44/65529": [], + "0/44/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533], + "0/48/0": 0, + "0/48/1": { + "failSafeExpiryLengthSeconds": 60, + "maxCumulativeFailsafeSeconds": 900 + }, + "0/48/2": 0, + "0/48/3": 0, + "0/48/4": true, + "0/48/65532": 0, + "0/48/65533": 1, + "0/48/65528": [1, 3, 5], + "0/48/65529": [0, 2, 4], + "0/48/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533], + "0/49/0": 1, + "0/49/1": [ + { + "networkID": "", + "connected": true + } + ], + "0/49/2": 10, + "0/49/3": 30, + "0/49/4": true, + "0/49/5": 0, + "0/49/6": "", + "0/49/7": null, + "0/49/65532": 1, + "0/49/65533": 1, + "0/49/65528": [1, 5, 7], + "0/49/65529": [0, 2, 4, 6, 8], + "0/49/65531": [0, 1, 2, 3, 4, 5, 6, 7, 65528, 65529, 65531, 65532, 65533], + "0/50/65532": 0, + "0/50/65533": 1, + "0/50/65528": [1], + "0/50/65529": [0], + "0/50/65531": [65528, 65529, 65531, 65532, 65533], + "0/51/0": [ + { + "name": "WIFI_STA_DEF", + "isOperational": true, + "offPremiseServicesReachableIPv4": null, + "offPremiseServicesReachableIPv6": null, + "hardwareAddress": "", + "IPv4Addresses": [""], + "IPv6Addresses": [], + "type": 1 + } + ], + "0/51/1": 6, + "0/51/2": 31279, + "0/51/3": 8, + "0/51/4": 1, + "0/51/5": [], + "0/51/6": [], + "0/51/7": [], + "0/51/8": false, + "0/51/65532": 0, + "0/51/65533": 1, + "0/51/65528": [], + "0/51/65529": [0], + "0/51/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533 + ], + "0/52/0": [], + "0/52/1": 166480, + "0/52/2": 86512, + "0/52/3": 157052, + "0/52/65532": 0, + "0/52/65533": 1, + "0/52/65528": [], + "0/52/65529": [], + "0/52/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/53/65532": 15, + "0/53/65533": 1, + "0/53/65528": [], + "0/53/65529": [0], + "0/53/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 65528, 65529, 65531, 65532, 65533 + ], + "0/54/0": "", + "0/54/1": 4, + "0/54/2": 3, + "0/54/3": 6, + "0/54/4": -61, + "0/54/5": null, + "0/54/6": null, + "0/54/7": null, + "0/54/8": null, + "0/54/9": null, + "0/54/10": null, + "0/54/11": null, + "0/54/12": null, + "0/54/65532": 3, + "0/54/65533": 1, + "0/54/65528": [], + "0/54/65529": [0], + "0/54/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 65528, 65529, 65531, 65532, + 65533 + ], + "0/55/0": null, + "0/55/1": null, + "0/55/2": 0, + "0/55/3": 0, + "0/55/4": 0, + "0/55/5": 0, + "0/55/6": 0, + "0/55/7": null, + "0/55/8": 0, + "0/55/65532": 3, + "0/55/65533": 1, + "0/55/65528": [], + "0/55/65529": [0], + "0/55/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533 + ], + "0/59/65532": 0, + "0/59/65533": 1, + "0/59/65528": [], + "0/59/65529": [], + "0/59/65531": [65528, 65529, 65531, 65532, 65533], + "0/60/0": 0, + "0/60/1": null, + "0/60/2": null, + "0/60/65532": 0, + "0/60/65533": 1, + "0/60/65528": [], + "0/60/65529": [0, 1, 2], + "0/60/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533], + "0/62/0": [ + { + "noc": "", + "icac": "", + "fabricIndex": 1 + } + ], + "0/62/1": [ + { + "rootPublicKey": "", + "vendorId": 65521, + "fabricId": 1, + "nodeId": 1, + "label": "", + "fabricIndex": 1 + } + ], + "0/62/2": 5, + "0/62/3": 1, + "0/62/4": [""], + "0/62/5": 1, + "0/62/65532": 0, + "0/62/65533": 1, + "0/62/65528": [1, 3, 5, 8], + "0/62/65529": [0, 2, 4, 6, 7, 9, 10, 11], + "0/62/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65531, 65532, 65533], + "0/63/0": [], + "0/63/1": [], + "0/63/2": 3, + "0/63/3": 3, + "0/63/65532": 0, + "0/63/65533": 1, + "0/63/65528": [2, 5], + "0/63/65529": [0, 1, 3, 4], + "0/63/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/64/0": [ + { + "label": "room", + "value": "bedroom 2" + }, + { + "label": "orientation", + "value": "North" + }, + { + "label": "floor", + "value": "2" + }, + { + "label": "direction", + "value": "up" + } + ], + "0/64/65532": 0, + "0/64/65533": 1, + "0/64/65528": [], + "0/64/65529": [], + "0/64/65531": [0, 65528, 65529, 65531, 65532, 65533], + "0/65/0": [], + "0/65/65532": 0, + "0/65/65533": 1, + "0/65/65528": [], + "0/65/65529": [], + "0/65/65531": [0, 65528, 65529, 65531, 65532, 65533], + "1/3/0": 0, + "1/3/1": 0, + "1/3/65532": 0, + "1/3/65533": 4, + "1/3/65528": [], + "1/3/65529": [0, 64], + "1/3/65531": [0, 1, 65528, 65529, 65531, 65532, 65533], + "1/4/0": 128, + "1/4/65532": 1, + "1/4/65533": 4, + "1/4/65528": [0, 1, 2, 3], + "1/4/65529": [0, 1, 2, 3, 4, 5], + "1/4/65531": [0, 65528, 65529, 65531, 65532, 65533], + "1/6/0": true, + "1/6/16384": true, + "1/6/16385": 0, + "1/6/16386": 0, + "1/6/16387": null, + "1/6/65532": 1, + "1/6/65533": 4, + "1/6/65528": [], + "1/6/65529": [0, 1, 2, 64, 65, 66], + "1/6/65531": [ + 0, 16384, 16385, 16386, 16387, 65528, 65529, 65531, 65532, 65533 + ], + "1/8/0": 52, + "1/8/1": 0, + "1/8/2": 1, + "1/8/3": 254, + "1/8/4": 0, + "1/8/5": 0, + "1/8/6": 0, + "1/8/15": 0, + "1/8/16": 0, + "1/8/17": null, + "1/8/18": 0, + "1/8/19": 0, + "1/8/20": 50, + "1/8/16384": null, + "1/8/65532": 3, + "1/8/65533": 5, + "1/8/65528": [], + "1/8/65529": [0, 1, 2, 3, 4, 5, 6, 7], + "1/8/65531": [ + 0, 1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, 20, 16384, 65528, 65529, 65531, + 65532, 65533 + ], + "1/29/0": [ + { + "type": 257, + "revision": 1 + } + ], + "1/29/1": [3, 4, 6, 8, 29, 768, 1030], + "1/29/2": [], + "1/29/3": [], + "1/29/65532": 0, + "1/29/65533": 1, + "1/29/65528": [], + "1/29/65529": [], + "1/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "1/768/0": 0, + "1/768/1": 0, + "1/768/2": 0, + "1/768/3": 24939, + "1/768/4": 24701, + "1/768/7": 0, + "1/768/8": 2, + "1/768/15": 0, + "1/768/16": 0, + "1/768/16384": 0, + "1/768/16385": 2, + "1/768/16386": 0, + "1/768/16387": 0, + "1/768/16388": 25, + "1/768/16389": 8960, + "1/768/16390": 0, + "1/768/16394": 31, + "1/768/16395": 0, + "1/768/16396": 65279, + "1/768/16397": 0, + "1/768/16400": 0, + "1/768/65532": 31, + "1/768/65533": 5, + "1/768/65528": [], + "1/768/65529": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 64, 65, 66, 67, 68, 71, 75, 76 + ], + "1/768/65531": [ + 0, 1, 2, 3, 4, 7, 8, 15, 16, 16384, 16385, 16386, 16387, 16388, 16389, + 16390, 16394, 16395, 16396, 16397, 16400, 65528, 65529, 65531, 65532, + 65533 + ], + "1/1030/0": 0, + "1/1030/1": 0, + "1/1030/2": 1, + "1/1030/65532": 0, + "1/1030/65533": 3, + "1/1030/65528": [], + "1/1030/65529": [], + "1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533] + }, + "available": true +} diff --git a/tests/components/matter/fixtures/nodes/onoff-light-no-name.json b/tests/components/matter/fixtures/nodes/onoff-light-no-name.json new file mode 100644 index 00000000000..3fa4ca49ccd --- /dev/null +++ b/tests/components/matter/fixtures/nodes/onoff-light-no-name.json @@ -0,0 +1,411 @@ +{ + "node_id": 1, + "date_commissioned": "2022-11-29T21:23:48.485051", + "last_interview": "2022-11-29T21:23:48.485057", + "interview_version": 2, + "attributes": { + "0/4/0": 128, + "0/4/65532": 1, + "0/4/65533": 4, + "0/4/65528": [0, 1, 2, 3], + "0/4/65529": [0, 1, 2, 3, 4, 5], + "0/4/65531": [0, 65528, 65529, 65531, 65532, 65533], + "0/29/0": [ + { + "type": 22, + "revision": 1 + } + ], + "0/29/1": [ + 4, 29, 31, 40, 42, 43, 44, 48, 49, 50, 51, 52, 53, 54, 55, 59, 60, 62, 63, + 64, 65 + ], + "0/29/2": [41], + "0/29/3": [1], + "0/29/65532": 0, + "0/29/65533": 1, + "0/29/65528": [], + "0/29/65529": [], + "0/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/31/0": [ + { + "privilege": 5, + "authMode": 2, + "subjects": [112233], + "targets": null, + "fabricIndex": 1 + } + ], + "0/31/1": [], + "0/31/2": 4, + "0/31/3": 3, + "0/31/4": 3, + "0/31/65532": 0, + "0/31/65533": 1, + "0/31/65528": [], + "0/31/65529": [], + "0/31/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533], + "0/40/0": 1, + "0/40/1": "Nabu Casa", + "0/40/2": 65521, + "0/40/3": "Mock Light", + "0/40/4": 32768, + "0/40/5": null, + "0/40/6": "XX", + "0/40/7": 0, + "0/40/8": "v1.0", + "0/40/9": 1, + "0/40/10": "v1.0", + "0/40/11": "20200101", + "0/40/12": "", + "0/40/13": "", + "0/40/14": "", + "0/40/15": "12345678", + "0/40/16": false, + "0/40/17": true, + "0/40/18": "mock-onoff-light", + "0/40/19": { + "caseSessionsPerFabric": 3, + "subscriptionsPerFabric": 3 + }, + "0/40/65532": 0, + "0/40/65533": 1, + "0/40/65528": [], + "0/40/65529": [], + "0/40/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 65528, 65529, 65531, 65532, 65533 + ], + "0/42/0": [], + "0/42/1": true, + "0/42/2": 0, + "0/42/3": 0, + "0/42/65532": 0, + "0/42/65533": 1, + "0/42/65528": [], + "0/42/65529": [0], + "0/42/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/43/0": "en-US", + "0/43/1": [ + "en-US", + "de-DE", + "fr-FR", + "en-GB", + "es-ES", + "zh-CN", + "it-IT", + "ja-JP" + ], + "0/43/65532": 0, + "0/43/65533": 1, + "0/43/65528": [], + "0/43/65529": [], + "0/43/65531": [0, 1, 65528, 65529, 65531, 65532, 65533], + "0/44/0": 0, + "0/44/1": 0, + "0/44/2": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 7], + "0/44/65532": 0, + "0/44/65533": 1, + "0/44/65528": [], + "0/44/65529": [], + "0/44/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533], + "0/48/0": 0, + "0/48/1": { + "failSafeExpiryLengthSeconds": 60, + "maxCumulativeFailsafeSeconds": 900 + }, + "0/48/2": 0, + "0/48/3": 0, + "0/48/4": true, + "0/48/65532": 0, + "0/48/65533": 1, + "0/48/65528": [1, 3, 5], + "0/48/65529": [0, 2, 4], + "0/48/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533], + "0/49/0": 1, + "0/49/1": [ + { + "networkID": "", + "connected": true + } + ], + "0/49/2": 10, + "0/49/3": 30, + "0/49/4": true, + "0/49/5": 0, + "0/49/6": "", + "0/49/7": null, + "0/49/65532": 1, + "0/49/65533": 1, + "0/49/65528": [1, 5, 7], + "0/49/65529": [0, 2, 4, 6, 8], + "0/49/65531": [0, 1, 2, 3, 4, 5, 6, 7, 65528, 65529, 65531, 65532, 65533], + "0/50/65532": 0, + "0/50/65533": 1, + "0/50/65528": [1], + "0/50/65529": [0], + "0/50/65531": [65528, 65529, 65531, 65532, 65533], + "0/51/0": [ + { + "name": "WIFI_STA_DEF", + "isOperational": true, + "offPremiseServicesReachableIPv4": null, + "offPremiseServicesReachableIPv6": null, + "hardwareAddress": "", + "IPv4Addresses": [""], + "IPv6Addresses": [], + "type": 1 + } + ], + "0/51/1": 6, + "0/51/2": 31279, + "0/51/3": 8, + "0/51/4": 1, + "0/51/5": [], + "0/51/6": [], + "0/51/7": [], + "0/51/8": false, + "0/51/65532": 0, + "0/51/65533": 1, + "0/51/65528": [], + "0/51/65529": [0], + "0/51/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533 + ], + "0/52/0": [], + "0/52/1": 166480, + "0/52/2": 86512, + "0/52/3": 157052, + "0/52/65532": 0, + "0/52/65533": 1, + "0/52/65528": [], + "0/52/65529": [], + "0/52/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/53/65532": 15, + "0/53/65533": 1, + "0/53/65528": [], + "0/53/65529": [0], + "0/53/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 65528, 65529, 65531, 65532, 65533 + ], + "0/54/0": "", + "0/54/1": 4, + "0/54/2": 3, + "0/54/3": 6, + "0/54/4": -61, + "0/54/5": null, + "0/54/6": null, + "0/54/7": null, + "0/54/8": null, + "0/54/9": null, + "0/54/10": null, + "0/54/11": null, + "0/54/12": null, + "0/54/65532": 3, + "0/54/65533": 1, + "0/54/65528": [], + "0/54/65529": [0], + "0/54/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 65528, 65529, 65531, 65532, + 65533 + ], + "0/55/0": null, + "0/55/1": null, + "0/55/2": 0, + "0/55/3": 0, + "0/55/4": 0, + "0/55/5": 0, + "0/55/6": 0, + "0/55/7": null, + "0/55/8": 0, + "0/55/65532": 3, + "0/55/65533": 1, + "0/55/65528": [], + "0/55/65529": [0], + "0/55/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533 + ], + "0/59/65532": 0, + "0/59/65533": 1, + "0/59/65528": [], + "0/59/65529": [], + "0/59/65531": [65528, 65529, 65531, 65532, 65533], + "0/60/0": 0, + "0/60/1": null, + "0/60/2": null, + "0/60/65532": 0, + "0/60/65533": 1, + "0/60/65528": [], + "0/60/65529": [0, 1, 2], + "0/60/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533], + "0/62/0": [ + { + "noc": "", + "icac": "", + "fabricIndex": 1 + } + ], + "0/62/1": [ + { + "rootPublicKey": "", + "vendorId": 65521, + "fabricId": 1, + "nodeId": 1, + "label": "", + "fabricIndex": 1 + } + ], + "0/62/2": 5, + "0/62/3": 1, + "0/62/4": [""], + "0/62/5": 1, + "0/62/65532": 0, + "0/62/65533": 1, + "0/62/65528": [1, 3, 5, 8], + "0/62/65529": [0, 2, 4, 6, 7, 9, 10, 11], + "0/62/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65531, 65532, 65533], + "0/63/0": [], + "0/63/1": [], + "0/63/2": 3, + "0/63/3": 3, + "0/63/65532": 0, + "0/63/65533": 1, + "0/63/65528": [2, 5], + "0/63/65529": [0, 1, 3, 4], + "0/63/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "0/64/0": [ + { + "label": "room", + "value": "bedroom 2" + }, + { + "label": "orientation", + "value": "North" + }, + { + "label": "floor", + "value": "2" + }, + { + "label": "direction", + "value": "up" + } + ], + "0/64/65532": 0, + "0/64/65533": 1, + "0/64/65528": [], + "0/64/65529": [], + "0/64/65531": [0, 65528, 65529, 65531, 65532, 65533], + "0/65/0": [], + "0/65/65532": 0, + "0/65/65533": 1, + "0/65/65528": [], + "0/65/65529": [], + "0/65/65531": [0, 65528, 65529, 65531, 65532, 65533], + "1/3/0": 0, + "1/3/1": 0, + "1/3/65532": 0, + "1/3/65533": 4, + "1/3/65528": [], + "1/3/65529": [0, 64], + "1/3/65531": [0, 1, 65528, 65529, 65531, 65532, 65533], + "1/4/0": 128, + "1/4/65532": 1, + "1/4/65533": 4, + "1/4/65528": [0, 1, 2, 3], + "1/4/65529": [0, 1, 2, 3, 4, 5], + "1/4/65531": [0, 65528, 65529, 65531, 65532, 65533], + "1/6/0": true, + "1/6/16384": true, + "1/6/16385": 0, + "1/6/16386": 0, + "1/6/16387": null, + "1/6/65532": 1, + "1/6/65533": 4, + "1/6/65528": [], + "1/6/65529": [0, 1, 2, 64, 65, 66], + "1/6/65531": [ + 0, 16384, 16385, 16386, 16387, 65528, 65529, 65531, 65532, 65533 + ], + "1/8/0": 52, + "1/8/1": 0, + "1/8/2": 1, + "1/8/3": 254, + "1/8/4": 0, + "1/8/5": 0, + "1/8/6": 0, + "1/8/15": 0, + "1/8/16": 0, + "1/8/17": null, + "1/8/18": 0, + "1/8/19": 0, + "1/8/20": 50, + "1/8/16384": null, + "1/8/65532": 3, + "1/8/65533": 5, + "1/8/65528": [], + "1/8/65529": [0, 1, 2, 3, 4, 5, 6, 7], + "1/8/65531": [ + 0, 1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, 20, 16384, 65528, 65529, 65531, + 65532, 65533 + ], + "1/29/0": [ + { + "type": 257, + "revision": 1 + } + ], + "1/29/1": [3, 4, 6, 8, 29, 768, 1030], + "1/29/2": [], + "1/29/3": [], + "1/29/65532": 0, + "1/29/65533": 1, + "1/29/65528": [], + "1/29/65529": [], + "1/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533], + "1/768/0": 0, + "1/768/1": 0, + "1/768/2": 0, + "1/768/3": 24939, + "1/768/4": 24701, + "1/768/7": 0, + "1/768/8": 2, + "1/768/15": 0, + "1/768/16": 0, + "1/768/16384": 0, + "1/768/16385": 2, + "1/768/16386": 0, + "1/768/16387": 0, + "1/768/16388": 25, + "1/768/16389": 8960, + "1/768/16390": 0, + "1/768/16394": 31, + "1/768/16395": 0, + "1/768/16396": 65279, + "1/768/16397": 0, + "1/768/16400": 0, + "1/768/65532": 31, + "1/768/65533": 5, + "1/768/65528": [], + "1/768/65529": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 64, 65, 66, 67, 68, 71, 75, 76 + ], + "1/768/65531": [ + 0, 1, 2, 3, 4, 7, 8, 15, 16, 16384, 16385, 16386, 16387, 16388, 16389, + 16390, 16394, 16395, 16396, 16397, 16400, 65528, 65529, 65531, 65532, + 65533 + ], + "1/1030/0": 0, + "1/1030/1": 0, + "1/1030/2": 1, + "1/1030/65532": 0, + "1/1030/65533": 3, + "1/1030/65528": [], + "1/1030/65529": [], + "1/1030/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533] + }, + "available": true +} diff --git a/tests/components/matter/test_adapter.py b/tests/components/matter/test_adapter.py index 8eadb76894e..9c37033dd4f 100644 --- a/tests/components/matter/test_adapter.py +++ b/tests/components/matter/test_adapter.py @@ -8,6 +8,7 @@ from matter_server.common.helpers.util import dataclass_from_dict from matter_server.common.models import EventType, MatterNodeData import pytest +from homeassistant.components.matter.adapter import get_clean_name from homeassistant.components.matter.const import DOMAIN from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr @@ -17,14 +18,24 @@ from .common import load_and_parse_node_fixture, setup_integration_with_node_fix # This tests needs to be adjusted to remove lingering tasks @pytest.mark.parametrize("expected_lingering_tasks", [True]) +@pytest.mark.parametrize( + ("node_fixture", "name"), + [ + ("onoff-light", "Mock OnOff Light"), + ("onoff-light-alt-name", "Mock OnOff Light"), + ("onoff-light-no-name", "Mock Light"), + ], +) async def test_device_registry_single_node_device( hass: HomeAssistant, matter_client: MagicMock, + node_fixture: str, + name: str, ) -> None: """Test bridge devices are set up correctly with via_device.""" await setup_integration_with_node_fixture( hass, - "onoff-light", + node_fixture, matter_client, ) @@ -37,7 +48,7 @@ async def test_device_registry_single_node_device( # test serial id present as additional identifier assert (DOMAIN, "serial_12345678") in entry.identifiers - assert entry.name == "Mock OnOff Light" + assert entry.name == name assert entry.manufacturer == "Nabu Casa" assert entry.model == "Mock Light" assert entry.hw_version == "v1.0" @@ -145,3 +156,17 @@ async def test_node_added_subscription( entity_state = hass.states.get("light.mock_onoff_light") assert entity_state + + +async def test_get_clean_name_() -> None: + """Test get_clean_name helper. + + Test device names that are assigned to `null` + or have a trailing null char with spaces. + """ + assert get_clean_name(None) is None + assert get_clean_name("\x00") is None + assert get_clean_name(" \x00") is None + assert get_clean_name("") is None + assert get_clean_name("Mock device") == "Mock device" + assert get_clean_name("Mock device \x00") == "Mock device"