diff --git a/homeassistant/components/matter/climate.py b/homeassistant/components/matter/climate.py index 2050a9eb185..d2656d59138 100644 --- a/homeassistant/components/matter/climate.py +++ b/homeassistant/components/matter/climate.py @@ -321,7 +321,7 @@ DISCOVERY_SCHEMAS = [ platform=Platform.CLIMATE, entity_description=ClimateEntityDescription( key="MatterThermostat", - name=None, + translation_key="thermostat", ), entity_class=MatterClimate, required_attributes=(clusters.Thermostat.Attributes.LocalTemperature,), diff --git a/homeassistant/components/matter/cover.py b/homeassistant/components/matter/cover.py index ea5250c9bd3..c32b7bc9e1a 100644 --- a/homeassistant/components/matter/cover.py +++ b/homeassistant/components/matter/cover.py @@ -200,7 +200,9 @@ class MatterCover(MatterEntity, CoverEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.COVER, - entity_description=CoverEntityDescription(key="MatterCover", name=None), + entity_description=CoverEntityDescription( + key="MatterCover", translation_key="cover" + ), entity_class=MatterCover, required_attributes=( clusters.WindowCovering.Attributes.OperationalStatus, @@ -214,7 +216,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.COVER, entity_description=CoverEntityDescription( - key="MatterCoverPositionAwareLift", name=None + key="MatterCoverPositionAwareLift", translation_key="cover" ), entity_class=MatterCover, required_attributes=( @@ -229,7 +231,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.COVER, entity_description=CoverEntityDescription( - key="MatterCoverPositionAwareTilt", name=None + key="MatterCoverPositionAwareTilt", translation_key="cover" ), entity_class=MatterCover, required_attributes=( @@ -244,7 +246,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.COVER, entity_description=CoverEntityDescription( - key="MatterCoverPositionAwareLiftAndTilt", name=None + key="MatterCoverPositionAwareLiftAndTilt", translation_key="cover" ), entity_class=MatterCover, required_attributes=( diff --git a/homeassistant/components/matter/entity.py b/homeassistant/components/matter/entity.py index 876693f354f..aaaaf074ddd 100644 --- a/homeassistant/components/matter/entity.py +++ b/homeassistant/components/matter/entity.py @@ -5,9 +5,11 @@ from __future__ import annotations from abc import abstractmethod from collections.abc import Callable from dataclasses import dataclass +from functools import cached_property import logging from typing import TYPE_CHECKING, Any, cast +from chip.clusters import Objects as clusters from chip.clusters.Objects import ClusterAttributeDescriptor, NullValue from matter_server.common.helpers.util import create_attribute_path from matter_server.common.models import EventType, ServerInfoMessage @@ -15,6 +17,7 @@ from matter_server.common.models import EventType, ServerInfoMessage from homeassistant.core import callback from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity import Entity, EntityDescription +from homeassistant.helpers.typing import UndefinedType from .const import DOMAIN, ID_TYPE_DEVICE_ID from .helpers import get_device_id @@ -41,6 +44,7 @@ class MatterEntity(Entity): """Entity class for Matter devices.""" _attr_has_entity_name = True + _name_postfix: str | None = None def __init__( self, @@ -71,6 +75,35 @@ class MatterEntity(Entity): identifiers={(DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")} ) self._attr_available = self._endpoint.node.available + # mark endpoint postfix if the device has the primary attribute on multiple endpoints + if not self._endpoint.node.is_bridge_device and any( + ep + for ep in self._endpoint.node.endpoints.values() + if ep != self._endpoint + and ep.has_attribute(None, entity_info.primary_attribute) + ): + self._name_postfix = str(self._endpoint.endpoint_id) + + # prefer the label attribute for the entity name + # Matter has a way for users and/or vendors to specify a name for an endpoint + # which is always preferred over a standard HA (generated) name + for attr in ( + clusters.FixedLabel.Attributes.LabelList, + clusters.UserLabel.Attributes.LabelList, + ): + if not (labels := self.get_matter_attribute_value(attr)): + continue + for label in labels: + if label.label not in ["Label", "Button"]: + continue + # fixed or user label found: use it + label_value: str = label.value + # in the case the label is only the label id, use it as postfix only + if label_value.isnumeric(): + self._name_postfix = label_value + else: + self._attr_name = label_value + break # make sure to update the attributes once self._update_from_device() @@ -105,6 +138,17 @@ class MatterEntity(Entity): ) ) + @cached_property + def name(self) -> str | UndefinedType | None: + """Return the name of the entity.""" + if hasattr(self, "_attr_name"): + # an explicit entity name was defined, we use that + return self._attr_name + name = super().name + if name and self._name_postfix: + name = f"{name} ({self._name_postfix})" + return name + @callback def _on_matter_event(self, event: EventType, data: Any = None) -> None: """Call on update from the device.""" diff --git a/homeassistant/components/matter/event.py b/homeassistant/components/matter/event.py index ade3452a6cf..dcb67d50523 100644 --- a/homeassistant/components/matter/event.py +++ b/homeassistant/components/matter/event.py @@ -49,8 +49,6 @@ async def async_setup_entry( class MatterEventEntity(MatterEntity, EventEntity): """Representation of a Matter Event entity.""" - _attr_translation_key = "push" - def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize the entity.""" super().__init__(*args, **kwargs) @@ -72,21 +70,6 @@ class MatterEventEntity(MatterEntity, EventEntity): event_types.append("multi_press_ongoing") event_types.append("multi_press_complete") self._attr_event_types = event_types - # the optional label attribute could be used to identify multiple buttons - # e.g. in case of a dimmer switch with 4 buttons, each button - # will have its own name, prefixed by the device name. - if labels := self.get_matter_attribute_value( - clusters.FixedLabel.Attributes.LabelList - ): - for label in labels: - if label.label in ["Label", "Button"]: - label_value: str = label.value - # in the case the label is only the label id, prettify it a bit - if label_value.isnumeric(): - self._attr_name = f"Button {label_value}" - else: - self._attr_name = label_value - break async def async_added_to_hass(self) -> None: """Handle being added to Home Assistant.""" @@ -122,7 +105,9 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.EVENT, entity_description=EventEntityDescription( - key="GenericSwitch", device_class=EventDeviceClass.BUTTON, name=None + key="GenericSwitch", + device_class=EventDeviceClass.BUTTON, + translation_key="button", ), entity_class=MatterEventEntity, required_attributes=( diff --git a/homeassistant/components/matter/light.py b/homeassistant/components/matter/light.py index 007bcd1a33a..777e4a69010 100644 --- a/homeassistant/components/matter/light.py +++ b/homeassistant/components/matter/light.py @@ -421,7 +421,9 @@ class MatterLight(MatterEntity, LightEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LIGHT, - entity_description=LightEntityDescription(key="MatterLight", name=None), + entity_description=LightEntityDescription( + key="MatterLight", translation_key="light" + ), entity_class=MatterLight, required_attributes=(clusters.OnOff.Attributes.OnOff,), optional_attributes=( @@ -445,7 +447,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LIGHT, entity_description=LightEntityDescription( - key="MatterHSColorLightFallback", name=None + key="MatterHSColorLightFallback", translation_key="light" ), entity_class=MatterLight, required_attributes=( @@ -465,7 +467,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LIGHT, entity_description=LightEntityDescription( - key="MatterXYColorLightFallback", name=None + key="MatterXYColorLightFallback", translation_key="light" ), entity_class=MatterLight, required_attributes=( @@ -485,7 +487,7 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LIGHT, entity_description=LightEntityDescription( - key="MatterColorTemperatureLightFallback", name=None + key="MatterColorTemperatureLightFallback", translation_key="light" ), entity_class=MatterLight, required_attributes=( diff --git a/homeassistant/components/matter/lock.py b/homeassistant/components/matter/lock.py index f58ded01013..5456554a535 100644 --- a/homeassistant/components/matter/lock.py +++ b/homeassistant/components/matter/lock.py @@ -176,7 +176,9 @@ class MatterLock(MatterEntity, LockEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LOCK, - entity_description=LockEntityDescription(key="MatterLock", name=None), + entity_description=LockEntityDescription( + key="MatterLock", translation_key="lock" + ), entity_class=MatterLock, required_attributes=(clusters.DoorLock.Attributes.LockState,), optional_attributes=(clusters.DoorLock.Attributes.DoorState,), diff --git a/homeassistant/components/matter/models.py b/homeassistant/components/matter/models.py index c77d6b42dcd..bb79d3571cf 100644 --- a/homeassistant/components/matter/models.py +++ b/homeassistant/components/matter/models.py @@ -107,6 +107,3 @@ class MatterDiscoverySchema: # [optional] bool to specify if this primary value may be discovered # by multiple platforms allow_multi: bool = False - - # [optional] bool to specify if this primary value should be polled - should_poll: bool = False diff --git a/homeassistant/components/matter/strings.json b/homeassistant/components/matter/strings.json index 190aae5de43..db71feab9c4 100644 --- a/homeassistant/components/matter/strings.json +++ b/homeassistant/components/matter/strings.json @@ -45,8 +45,19 @@ } }, "entity": { + "climate": { + "thermostat": { + "name": "Thermostat" + } + }, + "cover": { + "cover": { + "name": "[%key:component::cover::title%]" + } + }, "event": { - "push": { + "button": { + "name": "Button", "state_attributes": { "event_type": { "state": { @@ -64,6 +75,7 @@ }, "fan": { "fan": { + "name": "[%key:component::fan::title%]", "state_attributes": { "preset_mode": { "state": { @@ -92,6 +104,16 @@ "name": "On/Off transition time" } }, + "light": { + "light": { + "name": "[%key:component::light::title%]" + } + }, + "lock": { + "lock": { + "name": "[%key:component::lock::title%]" + } + }, "sensor": { "activated_carbon_filter_condition": { "name": "Activated carbon filter condition" @@ -114,6 +136,14 @@ "hepa_filter_condition": { "name": "Hepa filter condition" } + }, + "switch": { + "switch": { + "name": "[%key:component::switch::title%]" + }, + "power": { + "name": "Power" + } } }, "services": { diff --git a/homeassistant/components/matter/switch.py b/homeassistant/components/matter/switch.py index f148102cfcd..efa78446fc5 100644 --- a/homeassistant/components/matter/switch.py +++ b/homeassistant/components/matter/switch.py @@ -64,7 +64,9 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.SWITCH, entity_description=SwitchEntityDescription( - key="MatterPlug", device_class=SwitchDeviceClass.OUTLET, name=None + key="MatterPlug", + device_class=SwitchDeviceClass.OUTLET, + translation_key="switch", ), entity_class=MatterSwitch, required_attributes=(clusters.OnOff.Attributes.OnOff,), @@ -73,7 +75,38 @@ DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.SWITCH, entity_description=SwitchEntityDescription( - key="MatterSwitch", device_class=SwitchDeviceClass.SWITCH, name=None + key="MatterPowerToggle", + device_class=SwitchDeviceClass.SWITCH, + translation_key="power", + ), + entity_class=MatterSwitch, + required_attributes=(clusters.OnOff.Attributes.OnOff,), + device_type=( + device_types.AirPurifier, + device_types.BasicVideoPlayer, + device_types.CastingVideoPlayer, + device_types.CookSurface, + device_types.Cooktop, + device_types.Dishwasher, + device_types.ExtractorHood, + device_types.HeatingCoolingUnit, + device_types.LaundryDryer, + device_types.LaundryWasher, + device_types.Oven, + device_types.Pump, + device_types.PumpController, + device_types.Refrigerator, + device_types.RoboticVacuumCleaner, + device_types.RoomAirConditioner, + device_types.Speaker, + ), + ), + MatterDiscoverySchema( + platform=Platform.SWITCH, + entity_description=SwitchEntityDescription( + key="MatterSwitch", + device_class=SwitchDeviceClass.OUTLET, + translation_key="switch", ), entity_class=MatterSwitch, required_attributes=(clusters.OnOff.Attributes.OnOff,), @@ -83,6 +116,23 @@ DISCOVERY_SCHEMAS = [ device_types.ExtendedColorLight, device_types.ColorDimmerSwitch, device_types.OnOffLight, + device_types.AirPurifier, + device_types.BasicVideoPlayer, + device_types.CastingVideoPlayer, + device_types.CookSurface, + device_types.Cooktop, + device_types.Dishwasher, + device_types.ExtractorHood, + device_types.HeatingCoolingUnit, + device_types.LaundryDryer, + device_types.LaundryWasher, + device_types.Oven, + device_types.Pump, + device_types.PumpController, + device_types.Refrigerator, + device_types.RoboticVacuumCleaner, + device_types.RoomAirConditioner, + device_types.Speaker, ), ), ] diff --git a/tests/components/matter/fixtures/nodes/multi-endpoint-light.json b/tests/components/matter/fixtures/nodes/multi-endpoint-light.json new file mode 100644 index 00000000000..e3a01da9e7c --- /dev/null +++ b/tests/components/matter/fixtures/nodes/multi-endpoint-light.json @@ -0,0 +1,1637 @@ +{ + "node_id": 197, + "date_commissioned": "2024-06-21T00:23:41.026916", + "last_interview": "2024-06-21T00:23:41.026923", + "interview_version": 6, + "available": true, + "is_bridge": false, + "attributes": { + "0/29/0": [ + { + "0": 18, + "1": 1 + }, + { + "0": 22, + "1": 1 + } + ], + "0/29/1": [29, 31, 40, 42, 48, 49, 51, 53, 60, 62, 63, 64], + "0/29/2": [41], + "0/29/3": [1, 2, 3, 4, 5, 6], + "0/29/65532": 0, + "0/29/65533": 1, + "0/29/65528": [], + "0/29/65529": [], + "0/29/65530": [], + "0/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "0/31/0": [ + { + "1": 5, + "2": 2, + "3": [112233], + "4": null, + "254": 18 + } + ], + "0/31/1": [], + "0/31/2": 4, + "0/31/3": 3, + "0/31/4": 4, + "0/31/65532": 0, + "0/31/65533": 1, + "0/31/65528": [], + "0/31/65529": [], + "0/31/65530": [0, 1], + "0/31/65531": [0, 1, 2, 3, 4, 65528, 65529, 65530, 65531, 65532, 65533], + "0/40/0": 1, + "0/40/1": "Inovelli", + "0/40/2": 4961, + "0/40/3": "VTM31-SN", + "0/40/4": 1, + "0/40/5": "Inovelli", + "0/40/6": "**REDACTED**", + "0/40/7": 1, + "0/40/8": "0.0.0.1", + "0/40/9": 100, + "0/40/10": "1.0.0", + "0/40/11": "20231207", + "0/40/12": "850007431228", + "0/40/13": "https://inovelli.com/products/thread-matter-white-series-smart-2-1-on-off-dimmer-switch", + "0/40/14": "White Series Smart 2-1 Switch", + "0/40/15": "", + "0/40/16": false, + "0/40/17": true, + "0/40/18": "", + "0/40/19": { + "0": 3, + "1": 3 + }, + "0/40/65532": 0, + "0/40/65533": 1, + "0/40/65528": [], + "0/40/65529": [], + "0/40/65530": [0], + "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, 65530, 65531, 65532, 65533 + ], + "0/42/0": [], + "0/42/1": true, + "0/42/2": 1, + "0/42/3": null, + "0/42/65532": 0, + "0/42/65533": 1, + "0/42/65528": [], + "0/42/65529": [0], + "0/42/65530": [0, 1, 2], + "0/42/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "0/48/0": 0, + "0/48/1": { + "0": 60, + "1": 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/65530": [], + "0/48/65531": [0, 1, 2, 3, 4, 65528, 65529, 65530, 65531, 65532, 65533], + "0/49/0": 1, + "0/49/1": [ + { + "0": "guA0lmuCSNw=", + "1": true + } + ], + "0/49/2": 10, + "0/49/3": 20, + "0/49/4": true, + "0/49/5": 0, + "0/49/6": "guA0lmuCSNw=", + "0/49/7": null, + "0/49/65532": 2, + "0/49/65533": 1, + "0/49/65528": [1, 5, 7], + "0/49/65529": [0, 3, 4, 6, 8], + "0/49/65530": [], + "0/49/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 65528, 65529, 65530, 65531, 65532, 65533 + ], + "0/51/0": [ + { + "0": "MyHome442262884", + "1": true, + "2": null, + "3": null, + "4": "pNwAIEFBCBY=", + "5": [], + "6": [], + "7": 4 + } + ], + "0/51/1": 102, + "0/51/2": 1069632, + "0/51/3": 297, + "0/51/4": 0, + "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/65530": [3], + "0/51/65531": [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 65528, 65529, 65530, 65531, 65532, 65533 + ], + "0/53/0": 25, + "0/53/1": 5, + "0/53/2": "MyHome442262884", + "0/53/3": 27622, + "0/53/4": 9430595440367257820, + "0/53/5": "QP2Ea5ozpY2d", + "0/53/6": 0, + "0/53/7": [ + { + "0": 8852464968076080128, + "1": 12, + "2": 9216, + "3": 1183717, + "4": 39695, + "5": 3, + "6": -74, + "7": -74, + "8": 64, + "9": 15, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 13720920983629429643, + "1": 17, + "2": 13312, + "3": 256914, + "4": 61057, + "5": 2, + "6": -84, + "7": -84, + "8": 16, + "9": 1, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 9388760890908673655, + "1": 26, + "2": 17408, + "3": 2054526, + "4": 79216, + "5": 2, + "6": -85, + "7": -86, + "8": 1, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 6844302060861963395, + "1": 48, + "2": 21504, + "3": 23719, + "4": 9471, + "5": 2, + "6": -84, + "7": -84, + "8": 0, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 14305772551860424697, + "1": 1, + "2": 23552, + "3": 189996, + "4": 65613, + "5": 2, + "6": -85, + "7": -85, + "8": 21, + "9": 1, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 17491005778920105492, + "1": 44, + "2": 28672, + "3": 310232, + "4": 144381, + "5": 3, + "6": -61, + "7": -61, + "8": 5, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 7968688256206678783, + "1": 9, + "2": 30720, + "3": 31923, + "4": 15482, + "5": 2, + "6": -88, + "7": -89, + "8": 0, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 2195983971765588925, + "1": 3, + "2": 31744, + "3": 658867, + "4": 53332, + "5": 3, + "6": -77, + "7": -78, + "8": 51, + "9": 2, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 8533237363532831991, + "1": 32, + "2": 38912, + "3": 196496, + "4": 66926, + "5": 3, + "6": -75, + "7": -75, + "8": 0, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 15462742133285018414, + "1": 30, + "2": 51200, + "3": 156349, + "4": 91387, + "5": 1, + "6": -93, + "7": -94, + "8": 0, + "9": 0, + "10": true, + "11": true, + "12": true, + "13": false + }, + { + "0": 9106713788407201067, + "1": 14, + "2": 54272, + "3": 228318, + "4": 145504, + "5": 3, + "6": -65, + "7": -65, + "8": 59, + "9": 6, + "10": true, + "11": true, + "12": true, + "13": false + } + ], + "0/53/8": [ + { + "0": 9392545512105173771, + "1": 0, + "2": 0, + "3": 63, + "4": 0, + "5": 0, + "6": 0, + "7": 0, + "8": true, + "9": false + }, + { + "0": 0, + "1": 1024, + "2": 1, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 13, + "8": true, + "9": false + }, + { + "0": 0, + "1": 2048, + "2": 2, + "3": 53, + "4": 1, + "5": 0, + "6": 0, + "7": 3, + "8": true, + "9": false + }, + { + "0": 8852464968076080128, + "1": 9216, + "2": 9, + "3": 28, + "4": 1, + "5": 3, + "6": 2, + "7": 12, + "8": true, + "9": true + }, + { + "0": 0, + "1": 11264, + "2": 11, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 119, + "8": true, + "9": false + }, + { + "0": 13720920983629429643, + "1": 13312, + "2": 13, + "3": 28, + "4": 1, + "5": 2, + "6": 2, + "7": 17, + "8": true, + "9": true + }, + { + "0": 9388760890908673655, + "1": 17408, + "2": 17, + "3": 28, + "4": 1, + "5": 2, + "6": 0, + "7": 27, + "8": true, + "9": true + }, + { + "0": 6844302060861963395, + "1": 21504, + "2": 21, + "3": 28, + "4": 1, + "5": 2, + "6": 2, + "7": 48, + "8": true, + "9": true + }, + { + "0": 14305772551860424697, + "1": 23552, + "2": 23, + "3": 28, + "4": 1, + "5": 2, + "6": 2, + "7": 1, + "8": true, + "9": true + }, + { + "0": 0, + "1": 27648, + "2": 27, + "3": 53, + "4": 1, + "5": 0, + "6": 0, + "7": 36, + "8": true, + "9": false + }, + { + "0": 17491005778920105492, + "1": 28672, + "2": 28, + "3": 38, + "4": 1, + "5": 3, + "6": 3, + "7": 44, + "8": true, + "9": true + }, + { + "0": 14584221614789315818, + "1": 29696, + "2": 29, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 15, + "8": true, + "9": false + }, + { + "0": 7968688256206678783, + "1": 30720, + "2": 30, + "3": 28, + "4": 1, + "5": 2, + "6": 1, + "7": 9, + "8": true, + "9": true + }, + { + "0": 2195983971765588925, + "1": 31744, + "2": 31, + "3": 28, + "4": 1, + "5": 3, + "6": 1, + "7": 4, + "8": true, + "9": true + }, + { + "0": 8533237363532831991, + "1": 38912, + "2": 38, + "3": 28, + "4": 1, + "5": 3, + "6": 3, + "7": 32, + "8": true, + "9": true + }, + { + "0": 0, + "1": 45056, + "2": 44, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 5, + "8": true, + "9": false + }, + { + "0": 5655139244129535392, + "1": 50176, + "2": 49, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 10, + "8": true, + "9": false + }, + { + "0": 15462742133285018414, + "1": 51200, + "2": 50, + "3": 38, + "4": 1, + "5": 1, + "6": 0, + "7": 30, + "8": true, + "9": true + }, + { + "0": 9106713788407201067, + "1": 54272, + "2": 53, + "3": 28, + "4": 1, + "5": 3, + "6": 3, + "7": 14, + "8": true, + "9": true + }, + { + "0": 0, + "1": 55296, + "2": 54, + "3": 28, + "4": 2, + "5": 0, + "6": 0, + "7": 99, + "8": true, + "9": false + }, + { + "0": 0, + "1": 62464, + "2": 61, + "3": 28, + "4": 1, + "5": 0, + "6": 0, + "7": 51, + "8": true, + "9": false + } + ], + "0/53/9": 544200770, + "0/53/10": 68, + "0/53/11": 57, + "0/53/12": 158, + "0/53/13": 9, + "0/53/14": 66, + "0/53/15": 49, + "0/53/16": 3, + "0/53/17": 17, + "0/53/18": 36, + "0/53/19": 38, + "0/53/20": 33, + "0/53/21": 39, + "0/53/22": 240406, + "0/53/23": 214223, + "0/53/24": 26183, + "0/53/25": 214223, + "0/53/26": 203603, + "0/53/27": 26183, + "0/53/28": 240407, + "0/53/29": 0, + "0/53/30": 0, + "0/53/31": 0, + "0/53/32": 0, + "0/53/33": 408189, + "0/53/34": 10621, + "0/53/35": 0, + "0/53/36": 70745, + "0/53/37": 0, + "0/53/38": 1949, + "0/53/39": 1239481, + "0/53/40": 99469, + "0/53/41": 976396, + "0/53/42": 1046263, + "0/53/43": 0, + "0/53/44": 41, + "0/53/45": 0, + "0/53/46": 0, + "0/53/47": 0, + "0/53/48": 1, + "0/53/49": 21522, + "0/53/50": 0, + "0/53/51": 163615, + "0/53/52": 0, + "0/53/53": 8039, + "0/53/54": 0, + "0/53/55": 0, + "0/53/56": 111822352547840, + "0/53/57": 0, + "0/53/58": 0, + "0/53/59": { + "0": 672, + "1": 8335 + }, + "0/53/60": "AB//wA==", + "0/53/61": { + "0": true, + "1": false, + "2": true, + "3": true, + "4": true, + "5": true, + "6": false, + "7": true, + "8": true, + "9": true, + "10": true, + "11": true + }, + "0/53/62": [0, 0, 0, 0], + "0/53/65532": 15, + "0/53/65533": 1, + "0/53/65528": [], + "0/53/65529": [0], + "0/53/65530": [], + "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, 65530, 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/65530": [], + "0/60/65531": [0, 1, 2, 65528, 65529, 65530, 65531, 65532, 65533], + "0/62/0": [ + { + "1": "FTABAQEkAgE3AyQTAhgmBIAigScmBYAlTTo3BiQVAiQRxRgkBwEkCAEwCUEE+6maBmkSYz6Mc9CPP3rVE6+GVAI1RSaoMuQPvtSHBroJwa2mFK7Aah+sESC00TJ2vzX7jiix1pooU7vKr7hAHDcKNQEoARgkAgE2AwQCBAEYMAQUfXAGsiTrIa0biWN7/3bBx6IQNycwBRR0PzXGsFYhV/yy0eOyHr2WB98K3hgwC0A6AV48fcu123c1UzRL9vZoUGrLYUe3fMtdk27EMXARmFoecygVw3UxOyRE1e7ovYyq1l/B+OS46cFn+Z1Op1TBGA==", + "2": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEE2Zdr5BSI2FoASW7GpgNmBbxI18Gw0g/s2d/3ZLNWQJo3+HNMCxP0f+lmfQPqTta6hH2eALCXvrOemwZwB4OVkDcKNQEpARgkAmAwBBR0PzXGsFYhV/yy0eOyHr2WB98K3jAFFCTX1BG9PZC96rn83WyNVu55l7B8GDALQC2XiH6ek61BOXlOMlWF4CQZkjKupEy4prJWFWaNGg+vcJ7sR/xBtfhfThZhg1Re1atY3aapbB6V2j4xJiCq9HgY", + "254": 18 + } + ], + "0/62/1": [ + { + "1": "BDT3GwcQ+jgb6JHKilDo0cIOCVRVzt/Qp1MGXzpJumBOSFenMDvr940AGy6NI4WfqROrVh9KmrroTnXEqOIhA6Y=", + "2": 4939, + "3": 2, + "4": 197, + "5": "", + "254": 18 + } + ], + "0/62/2": 5, + "0/62/3": 3, + "0/62/4": [ + "FTABAQAkAgE3AyYU2nLdAyYVar5MzhgmBLnNRi0kBQA3BiYU2nLdAyYVar5MzhgkBwEkCAEwCUEENrEEk8M5ztCYkE5UAh3jIAN89pc0KFJ/gbwBIWeN3Ws5aFKjFWCndluUHWDEWPtSMxWTrno8vATU3x8j+yycijcKNQEpARgkAmAwBBQErHkbm0I53zyvS+R5vrTzJR1doTAFFASseRubQjnfPK9L5Hm+tPMlHV2hGDALQLv4FZpuAoq/m0iIdjOY2OTPnm3JjQIWd4QLBf4ncy6uPlPhdDlvanQvCxSl7xaF/XW8j+EsWacZDK15mD4jzuQY", + "FTABAQAkAgE3AycUxxt9sfxycj8mFZkiBagYJgQNz0YtJAUANwYnFMcbfbH8cnI/JhWZIgWoGCQHASQIATAJQQTGlfTQVqZk2GnxHCh364hEd0J4+rUEblxiWQDmYIienGmHY50RviHxI+875LHFTo9rcntChj+TPxP00yUIw3yoNwo1ASkBGCQCYDAEFK5Ln3+cjAgPxBcWXXzMO1MEyW6oMAUUrkuff5yMCA/EFxZdfMw7UwTJbqgYMAtAleRSrdtPawWmPJ2A0t6EFlYTVKtqseAiuHxSwE+U4sEeL+QCO9OCT6f1bsTzD5KDjqTBlWPSjeUDfd5u61o30Bg=", + "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEENPcbBxD6OBvokcqKUOjRwg4JVFXO39CnUwZfOkm6YE5IV6cwO+v3jQAbLo0jhZ+pE6tWH0qauuhOdcSo4iEDpjcKNQEpARgkAmAwBBQk19QRvT2Qveq5/N1sjVbueZewfDAFFCTX1BG9PZC96rn83WyNVu55l7B8GDALQEUvBGKd7aRh6/0l82kua682xBcREAV7Xn4PFsZ7tEs7H4PYHnCZTzgSC7mqY2u0y2AhTztdJ7tCeffml9HQQGwY" + ], + "0/62/5": 18, + "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/65530": [], + "0/62/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65530, 65531, 65532, 65533], + "0/63/0": [], + "0/63/1": [], + "0/63/2": 4, + "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/65530": [], + "0/63/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "0/64/0": [ + { + "0": "Vendor", + "1": "Inovelli" + }, + { + "0": "Product", + "1": "VTM31-SN" + } + ], + "0/64/65532": 0, + "0/64/65533": 1, + "0/64/65528": [], + "0/64/65529": [], + "0/64/65530": [], + "0/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "1/3/0": 0, + "1/3/1": 2, + "1/3/65532": 0, + "1/3/65533": 4, + "1/3/65528": [], + "1/3/65529": [0, 64], + "1/3/65530": [], + "1/3/65531": [0, 1, 65528, 65529, 65530, 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/65530": [], + "1/4/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "1/5/0": null, + "1/5/1": 0, + "1/5/2": 0, + "1/5/3": false, + "1/5/4": 128, + "1/5/65532": 1, + "1/5/65533": 4, + "1/5/65528": [0, 1, 2, 3, 4, 6], + "1/5/65529": [0, 1, 2, 3, 4, 5, 6], + "1/5/65530": [], + "1/5/65531": [0, 1, 2, 3, 4, 65528, 65529, 65530, 65531, 65532, 65533], + "1/6/0": false, + "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/65530": [], + "1/6/65531": [ + 0, 16384, 16385, 16386, 16387, 65528, 65529, 65530, 65531, 65532, 65533 + ], + "1/8/0": 1, + "1/8/1": 0, + "1/8/2": 1, + "1/8/3": 254, + "1/8/15": 0, + "1/8/16": 5, + "1/8/17": 137, + "1/8/18": 15, + "1/8/19": 5, + "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/65530": [], + "1/8/65531": [ + 0, 1, 2, 3, 15, 16, 17, 18, 19, 20, 16384, 65528, 65529, 65530, 65531, + 65532, 65533 + ], + "1/29/0": [ + { + "0": 257, + "1": 1 + } + ], + "1/29/1": [3, 4, 5, 6, 8, 29, 64, 80, 305134641], + "1/29/2": [], + "1/29/3": [], + "1/29/65532": 0, + "1/29/65533": 1, + "1/29/65528": [], + "1/29/65529": [], + "1/29/65530": [], + "1/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "1/64/0": [ + { + "0": "DeviceType", + "1": "DimmableLight" + } + ], + "1/64/65532": 0, + "1/64/65533": 1, + "1/64/65528": [], + "1/64/65529": [], + "1/64/65530": [], + "1/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "1/80/0": "Switch Mode", + "1/80/1": 0, + "1/80/2": [ + { + "0": "OnOff+Single", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "OnOff+Dumb", + "1": 1, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "OnOff+AUX", + "1": 2, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "OnOff+Full Wave", + "1": 3, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Dimmer+Single", + "1": 4, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Dimmer+Dumb", + "1": 5, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Dimmer+Aux", + "1": 6, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "1/80/3": 4, + "1/80/65532": 0, + "1/80/65533": 1, + "1/80/65528": [], + "1/80/65529": [0], + "1/80/65530": [], + "1/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "1/305134641/305070080": 1, + "1/305134641/305070081": 20, + "1/305134641/305070082": 127, + "1/305134641/305070083": 127, + "1/305134641/305070084": 127, + "1/305134641/305070085": 127, + "1/305134641/305070086": 127, + "1/305134641/305070087": 127, + "1/305134641/305070088": 127, + "1/305134641/305070089": 1, + "1/305134641/305070090": 255, + "1/305134641/305070091": false, + "1/305134641/305070092": 0, + "1/305134641/305070093": 255, + "1/305134641/305070094": 255, + "1/305134641/305070095": 255, + "1/305134641/305070097": 11, + "1/305134641/305070101": true, + "1/305134641/305070102": 0, + "1/305134641/305070106": 0, + "1/305134641/305070112": 30, + "1/305134641/305070113": false, + "1/305134641/305070130": 5, + "1/305134641/305070132": false, + "1/305134641/305070133": false, + "1/305134641/305070134": false, + "1/305134641/305070135": 254, + "1/305134641/305070136": 2, + "1/305134641/305070175": 35, + "1/305134641/305070176": 35, + "1/305134641/305070177": 33, + "1/305134641/305070178": 1, + "1/305134641/305070336": false, + "1/305134641/305070338": false, + "1/305134641/305070339": false, + "1/305134641/305070340": true, + "1/305134641/305070341": true, + "1/305134641/305070342": false, + "1/305134641/65532": 0, + "1/305134641/65533": 1, + "1/305134641/65528": [], + "1/305134641/65529": [305070081, 305070083, 305070276], + "1/305134641/65530": [], + "1/305134641/65531": [ + 65528, 65529, 65530, 65531, 305070080, 305070081, 305070082, 305070083, + 305070084, 305070085, 305070086, 305070087, 305070088, 305070089, + 305070090, 305070091, 305070092, 305070093, 305070094, 305070095, + 305070097, 305070101, 305070102, 305070106, 305070112, 305070113, + 305070130, 305070132, 305070133, 305070134, 305070135, 305070136, + 305070175, 305070176, 305070177, 305070178, 305070336, 305070338, + 305070339, 305070340, 305070341, 305070342, 65532, 65533 + ], + "2/3/0": 0, + "2/3/1": 2, + "2/3/65532": 0, + "2/3/65533": 4, + "2/3/65528": [], + "2/3/65529": [0, 64], + "2/3/65530": [], + "2/3/65531": [0, 1, 65528, 65529, 65530, 65531, 65532, 65533], + "2/29/0": [ + { + "0": 260, + "1": 1 + } + ], + "2/29/1": [3, 29, 30, 64, 80], + "2/29/2": [3, 6, 8], + "2/29/3": [], + "2/29/65532": 0, + "2/29/65533": 1, + "2/29/65528": [], + "2/29/65529": [], + "2/29/65530": [], + "2/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "2/30/0": [], + "2/30/65532": 0, + "2/30/65533": 1, + "2/30/65528": [], + "2/30/65529": [], + "2/30/65530": [], + "2/30/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "2/64/0": [ + { + "0": "DeviceType", + "1": "DimmableSwitch" + } + ], + "2/64/65532": 0, + "2/64/65533": 1, + "2/64/65528": [], + "2/64/65529": [], + "2/64/65530": [], + "2/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "2/80/0": "Smart Bulb Mode", + "2/80/1": 0, + "2/80/2": [ + { + "0": "Smart Bulb Disable", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Smart Bulb Enable", + "1": 1, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "2/80/3": 0, + "2/80/65532": 0, + "2/80/65533": 1, + "2/80/65528": [], + "2/80/65529": [0], + "2/80/65530": [], + "2/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "3/3/0": 0, + "3/3/1": 2, + "3/3/65532": 0, + "3/3/65533": 4, + "3/3/65528": [], + "3/3/65529": [0, 64], + "3/3/65530": [], + "3/3/65531": [0, 1, 65528, 65529, 65530, 65531, 65532, 65533], + "3/29/0": [ + { + "0": 15, + "1": 1 + } + ], + "3/29/1": [3, 29, 59, 64, 80], + "3/29/2": [], + "3/29/3": [], + "3/29/65532": 0, + "3/29/65533": 1, + "3/29/65528": [], + "3/29/65529": [], + "3/29/65530": [], + "3/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "3/59/0": 2, + "3/59/1": 0, + "3/59/2": 5, + "3/59/65532": 30, + "3/59/65533": 1, + "3/59/65528": [], + "3/59/65529": [], + "3/59/65530": [1, 2, 3, 4, 5, 6], + "3/59/65531": [0, 1, 2, 65528, 65529, 65530, 65531, 65532, 65533], + "3/64/0": [ + { + "0": "Button", + "1": "Up" + } + ], + "3/64/65532": 0, + "3/64/65533": 1, + "3/64/65528": [], + "3/64/65529": [], + "3/64/65530": [], + "3/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "3/80/0": "Dimming Edge", + "3/80/1": 0, + "3/80/2": [ + { + "0": "Leading", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Trailing", + "1": 1, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "3/80/3": 0, + "3/80/65532": 0, + "3/80/65533": 1, + "3/80/65528": [], + "3/80/65529": [0], + "3/80/65530": [], + "3/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "4/3/0": 0, + "4/3/1": 2, + "4/3/65532": 0, + "4/3/65533": 4, + "4/3/65528": [], + "4/3/65529": [0, 64], + "4/3/65530": [], + "4/3/65531": [0, 1, 65528, 65529, 65530, 65531, 65532, 65533], + "4/29/0": [ + { + "0": 15, + "1": 1 + } + ], + "4/29/1": [3, 29, 59, 64, 80], + "4/29/2": [], + "4/29/3": [], + "4/29/65532": 0, + "4/29/65533": 1, + "4/29/65528": [], + "4/29/65529": [], + "4/29/65530": [], + "4/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "4/59/0": 2, + "4/59/1": 0, + "4/59/2": 5, + "4/59/65532": 30, + "4/59/65533": 1, + "4/59/65528": [], + "4/59/65529": [], + "4/59/65530": [1, 2, 3, 4, 5, 6], + "4/59/65531": [0, 1, 2, 65528, 65529, 65530, 65531, 65532, 65533], + "4/64/0": [ + { + "0": "Button", + "1": "Down" + } + ], + "4/64/65532": 0, + "4/64/65533": 1, + "4/64/65528": [], + "4/64/65529": [], + "4/64/65530": [], + "4/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "4/80/0": "Dimming Speed", + "4/80/1": 0, + "4/80/2": [ + { + "0": "Instant", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "500ms", + "1": 5, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "800ms", + "1": 8, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "1s", + "1": 10, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "1.5s", + "1": 15, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "2s", + "1": 20, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "2.5s", + "1": 25, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "3s", + "1": 30, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "3.5s", + "1": 35, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "4s", + "1": 40, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "5s", + "1": 50, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "6s", + "1": 60, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "7s", + "1": 70, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "8s", + "1": 80, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "10s", + "1": 100, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "4/80/3": 20, + "4/80/65532": 0, + "4/80/65533": 1, + "4/80/65528": [], + "4/80/65529": [0], + "4/80/65530": [], + "4/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "5/3/0": 0, + "5/3/1": 2, + "5/3/65532": 0, + "5/3/65533": 4, + "5/3/65528": [], + "5/3/65529": [0, 64], + "5/3/65530": [], + "5/3/65531": [0, 1, 65528, 65529, 65530, 65531, 65532, 65533], + "5/29/0": [ + { + "0": 15, + "1": 1 + } + ], + "5/29/1": [3, 29, 59, 64, 80], + "5/29/2": [], + "5/29/3": [], + "5/29/65532": 0, + "5/29/65533": 1, + "5/29/65528": [], + "5/29/65529": [], + "5/29/65530": [], + "5/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "5/59/0": 2, + "5/59/1": 0, + "5/59/2": 5, + "5/59/65532": 30, + "5/59/65533": 1, + "5/59/65528": [], + "5/59/65529": [], + "5/59/65530": [1, 2, 3, 4, 5, 6], + "5/59/65531": [0, 1, 2, 65528, 65529, 65530, 65531, 65532, 65533], + "5/64/0": [ + { + "0": "Button", + "1": "Config" + } + ], + "5/64/65532": 0, + "5/64/65533": 1, + "5/64/65528": [], + "5/64/65529": [], + "5/64/65530": [], + "5/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "5/80/0": "Relay", + "5/80/1": 0, + "5/80/2": [ + { + "0": "Relay Click Enable", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Relay Click Disable", + "1": 1, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "5/80/3": 1, + "5/80/65532": 0, + "5/80/65533": 1, + "5/80/65528": [], + "5/80/65529": [0], + "5/80/65530": [], + "5/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "6/3/0": 0, + "6/3/1": 2, + "6/3/65532": 0, + "6/3/65533": 4, + "6/3/65528": [], + "6/3/65529": [0, 64], + "6/3/65530": [], + "6/3/65531": [0, 1, 65528, 65529, 65530, 65531, 65532, 65533], + "6/4/0": 128, + "6/4/65532": 1, + "6/4/65533": 4, + "6/4/65528": [0, 1, 2, 3], + "6/4/65529": [0, 1, 2, 3, 4, 5], + "6/4/65530": [], + "6/4/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "6/5/0": null, + "6/5/1": 0, + "6/5/2": 0, + "6/5/3": false, + "6/5/4": 128, + "6/5/65532": 0, + "6/5/65533": 4, + "6/5/65528": [0, 1, 2, 3, 4, 6], + "6/5/65529": [0, 1, 2, 3, 4, 5, 6], + "6/5/65530": [], + "6/5/65531": [0, 1, 2, 3, 4, 65528, 65529, 65530, 65531, 65532, 65533], + "6/6/0": false, + "6/6/16384": true, + "6/6/16385": 0, + "6/6/16386": 0, + "6/6/16387": 0, + "6/6/65532": 1, + "6/6/65533": 4, + "6/6/65528": [], + "6/6/65529": [0, 1, 2, 64, 65, 66], + "6/6/65530": [], + "6/6/65531": [ + 0, 16384, 16385, 16386, 16387, 65528, 65529, 65530, 65531, 65532, 65533 + ], + "6/8/0": 224, + "6/8/1": 0, + "6/8/2": 1, + "6/8/3": 254, + "6/8/15": 0, + "6/8/17": 254, + "6/8/16384": 128, + "6/8/65532": 0, + "6/8/65533": 5, + "6/8/65528": [], + "6/8/65529": [0, 1, 2, 3, 4, 5, 6, 7], + "6/8/65530": [], + "6/8/65531": [ + 0, 1, 2, 3, 15, 17, 16384, 65528, 65529, 65530, 65531, 65532, 65533 + ], + "6/29/0": [ + { + "0": 269, + "1": 1 + } + ], + "6/29/1": [3, 4, 5, 6, 8, 29, 64, 80, 768], + "6/29/2": [], + "6/29/3": [], + "6/29/65532": 0, + "6/29/65533": 1, + "6/29/65528": [], + "6/29/65529": [], + "6/29/65530": [], + "6/29/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "6/64/0": [ + { + "0": "DeviceType", + "1": "DimmableLight" + }, + { + "0": "Light", + "1": "LED Bar" + } + ], + "6/64/65532": 0, + "6/64/65533": 1, + "6/64/65528": [], + "6/64/65529": [], + "6/64/65530": [], + "6/64/65531": [0, 65528, 65529, 65530, 65531, 65532, 65533], + "6/80/0": "LED Color", + "6/80/1": 0, + "6/80/2": [ + { + "0": "Red", + "1": 0, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Orange", + "1": 1, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Lemon", + "1": 2, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Lime", + "1": 3, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Green", + "1": 4, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Teal", + "1": 5, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Cyan", + "1": 6, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Aqua", + "1": 7, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Blue", + "1": 8, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Violet", + "1": 9, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Magenta", + "1": 10, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "Pink", + "1": 11, + "2": [ + { + "0": 0, + "1": 0 + } + ] + }, + { + "0": "White", + "1": 12, + "2": [ + { + "0": 0, + "1": 0 + } + ] + } + ], + "6/80/3": 2, + "6/80/65532": 0, + "6/80/65533": 1, + "6/80/65528": [], + "6/80/65529": [0], + "6/80/65530": [], + "6/80/65531": [0, 1, 2, 3, 65528, 65529, 65530, 65531, 65532, 65533], + "6/768/0": 6, + "6/768/1": 170, + "6/768/2": 0, + "6/768/3": 24939, + "6/768/4": 24701, + "6/768/7": 500, + "6/768/8": 0, + "6/768/15": 0, + "6/768/16": 0, + "6/768/16385": 0, + "6/768/16394": 25, + "6/768/16395": 0, + "6/768/16396": 65279, + "6/768/16397": 0, + "6/768/16400": 0, + "6/768/65532": 25, + "6/768/65533": 5, + "6/768/65528": [], + "6/768/65529": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 71, 75, 76], + "6/768/65530": [], + "6/768/65531": [ + 0, 1, 2, 3, 4, 7, 8, 15, 16, 16385, 16394, 16395, 16396, 16397, 16400, + 65528, 65529, 65530, 65531, 65532, 65533 + ] + }, + "attribute_subscriptions": [] +} diff --git a/tests/components/matter/fixtures/nodes/on-off-plugin-unit.json b/tests/components/matter/fixtures/nodes/on-off-plugin-unit.json index 8d523f5443a..3b4831a7485 100644 --- a/tests/components/matter/fixtures/nodes/on-off-plugin-unit.json +++ b/tests/components/matter/fixtures/nodes/on-off-plugin-unit.json @@ -24,7 +24,7 @@ "0/40/0": 1, "0/40/1": "Nabu Casa", "0/40/2": 65521, - "0/40/3": "Mock OnOffPluginUnit (powerplug/switch)", + "0/40/3": "Mock OnOffPluginUnit", "0/40/4": 32768, "0/40/5": "", "0/40/6": "XX", diff --git a/tests/components/matter/test_adapter.py b/tests/components/matter/test_adapter.py index 16a7ec3a780..da2ef179c44 100644 --- a/tests/components/matter/test_adapter.py +++ b/tests/components/matter/test_adapter.py @@ -81,7 +81,7 @@ async def test_device_registry_single_node_device_alt( assert entry is not None # test name is derived from productName (because nodeLabel is absent) - assert entry.name == "Mock OnOffPluginUnit (powerplug/switch)" + assert entry.name == "Mock OnOffPluginUnit" # test serial id NOT present as additional identifier assert (DOMAIN, "serial_TEST_SN") not in entry.identifiers @@ -163,13 +163,13 @@ async def test_node_added_subscription( ) ) - entity_state = hass.states.get("light.mock_onoff_light") + entity_state = hass.states.get("light.mock_onoff_light_light") assert not entity_state node_added_callback(EventType.NODE_ADDED, node) await hass.async_block_till_done() - entity_state = hass.states.get("light.mock_onoff_light") + entity_state = hass.states.get("light.mock_onoff_light_light") assert entity_state @@ -187,6 +187,24 @@ async def test_device_registry_single_node_composed_device( assert len(dev_reg.devices) == 1 +async def test_multi_endpoint_name( + hass: HomeAssistant, + matter_client: MagicMock, +) -> None: + """Test that the entity name gets postfixed if the device has multiple primary endpoints.""" + await setup_integration_with_node_fixture( + hass, + "multi-endpoint-light", + matter_client, + ) + entity_state = hass.states.get("light.inovelli_light_1") + assert entity_state + assert entity_state.name == "Inovelli Light (1)" + entity_state = hass.states.get("light.inovelli_light_6") + assert entity_state + assert entity_state.name == "Inovelli Light (6)" + + async def test_get_clean_name_() -> None: """Test get_clean_name helper. diff --git a/tests/components/matter/test_climate.py b/tests/components/matter/test_climate.py index 2150c733700..6a4cf34a640 100644 --- a/tests/components/matter/test_climate.py +++ b/tests/components/matter/test_climate.py @@ -44,7 +44,7 @@ async def test_thermostat_base( ) -> None: """Test thermostat base attributes and state updates.""" # test entity attributes - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["min_temp"] == 7 assert state.attributes["max_temp"] == 35 @@ -66,7 +66,7 @@ async def test_thermostat_base( set_node_attribute(thermostat, 1, 513, 5, 1600) set_node_attribute(thermostat, 1, 513, 6, 3000) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["min_temp"] == 16 assert state.attributes["max_temp"] == 30 @@ -80,56 +80,56 @@ async def test_thermostat_base( # test system mode update from device set_node_attribute(thermostat, 1, 513, 28, 0) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.state == HVACMode.OFF # test running state update from device set_node_attribute(thermostat, 1, 513, 41, 1) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.HEATING set_node_attribute(thermostat, 1, 513, 41, 8) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.HEATING set_node_attribute(thermostat, 1, 513, 41, 2) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.COOLING set_node_attribute(thermostat, 1, 513, 41, 16) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.COOLING set_node_attribute(thermostat, 1, 513, 41, 4) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.FAN set_node_attribute(thermostat, 1, 513, 41, 32) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.FAN set_node_attribute(thermostat, 1, 513, 41, 64) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.FAN set_node_attribute(thermostat, 1, 513, 41, 66) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["hvac_action"] == HVACAction.OFF @@ -137,7 +137,7 @@ async def test_thermostat_base( set_node_attribute(thermostat, 1, 513, 28, 4) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.state == HVACMode.HEAT @@ -145,7 +145,7 @@ async def test_thermostat_base( set_node_attribute(thermostat, 1, 513, 18, 2000) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.attributes["temperature"] == 20 @@ -159,14 +159,14 @@ async def test_thermostat_service_calls( ) -> None: """Test climate platform service calls.""" # test single-setpoint temperature adjustment when cool mode is active - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.state == HVACMode.COOL await hass.services.async_call( "climate", "set_temperature", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "temperature": 25, }, blocking=True, @@ -187,7 +187,7 @@ async def test_thermostat_service_calls( "climate", "set_temperature", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "temperature": 25, }, blocking=True, @@ -199,7 +199,7 @@ async def test_thermostat_service_calls( # test single-setpoint temperature adjustment when heat mode is active set_node_attribute(thermostat, 1, 513, 28, 4) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.state == HVACMode.HEAT @@ -207,7 +207,7 @@ async def test_thermostat_service_calls( "climate", "set_temperature", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "temperature": 20, }, blocking=True, @@ -224,7 +224,7 @@ async def test_thermostat_service_calls( # test dual setpoint temperature adjustments when heat_cool mode is active set_node_attribute(thermostat, 1, 513, 28, 1) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.longan_link_hvac") + state = hass.states.get("climate.longan_link_hvac_thermostat") assert state assert state.state == HVACMode.HEAT_COOL @@ -232,7 +232,7 @@ async def test_thermostat_service_calls( "climate", "set_temperature", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "target_temp_low": 10, "target_temp_high": 30, }, @@ -257,7 +257,7 @@ async def test_thermostat_service_calls( "climate", "set_hvac_mode", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "hvac_mode": HVACMode.HEAT, }, blocking=True, @@ -281,7 +281,7 @@ async def test_thermostat_service_calls( "climate", "set_temperature", { - "entity_id": "climate.longan_link_hvac", + "entity_id": "climate.longan_link_hvac_thermostat", "temperature": 22, "hvac_mode": HVACMode.COOL, }, @@ -312,7 +312,7 @@ async def test_room_airconditioner( room_airconditioner: MatterNode, ) -> None: """Test if a climate entity is created for a Room Airconditioner device.""" - state = hass.states.get("climate.room_airconditioner") + state = hass.states.get("climate.room_airconditioner_thermostat") assert state assert state.attributes["current_temperature"] == 20 assert state.attributes["min_temp"] == 16 @@ -335,13 +335,13 @@ async def test_room_airconditioner( # test fan-only hvac mode set_node_attribute(room_airconditioner, 1, 513, 28, 7) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.room_airconditioner") + state = hass.states.get("climate.room_airconditioner_thermostat") assert state assert state.state == HVACMode.FAN_ONLY # test dry hvac mode set_node_attribute(room_airconditioner, 1, 513, 28, 8) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("climate.room_airconditioner") + state = hass.states.get("climate.room_airconditioner_thermostat") assert state assert state.state == HVACMode.DRY diff --git a/tests/components/matter/test_cover.py b/tests/components/matter/test_cover.py index ff6e933a1ab..f526205234d 100644 --- a/tests/components/matter/test_cover.py +++ b/tests/components/matter/test_cover.py @@ -27,11 +27,11 @@ from .common import ( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_lift", "cover.mock_lift_window_covering"), - ("window-covering_pa-lift", "cover.longan_link_wncv_da01"), - ("window-covering_tilt", "cover.mock_tilt_window_covering"), - ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering"), - ("window-covering_full", "cover.mock_full_window_covering"), + ("window-covering_lift", "cover.mock_lift_window_covering_cover"), + ("window-covering_pa-lift", "cover.longan_link_wncv_da01_cover"), + ("window-covering_tilt", "cover.mock_tilt_window_covering_cover"), + ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering_cover"), + ("window-covering_full", "cover.mock_full_window_covering_cover"), ], ) async def test_cover( @@ -105,9 +105,9 @@ async def test_cover( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_lift", "cover.mock_lift_window_covering"), - ("window-covering_pa-lift", "cover.longan_link_wncv_da01"), - ("window-covering_full", "cover.mock_full_window_covering"), + ("window-covering_lift", "cover.mock_lift_window_covering_cover"), + ("window-covering_pa-lift", "cover.longan_link_wncv_da01_cover"), + ("window-covering_full", "cover.mock_full_window_covering_cover"), ], ) async def test_cover_lift( @@ -162,7 +162,7 @@ async def test_cover_lift( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_lift", "cover.mock_lift_window_covering"), + ("window-covering_lift", "cover.mock_lift_window_covering_cover"), ], ) async def test_cover_lift_only( @@ -207,7 +207,7 @@ async def test_cover_lift_only( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_pa-lift", "cover.longan_link_wncv_da01"), + ("window-covering_pa-lift", "cover.longan_link_wncv_da01_cover"), ], ) async def test_cover_position_aware_lift( @@ -259,9 +259,9 @@ async def test_cover_position_aware_lift( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_tilt", "cover.mock_tilt_window_covering"), - ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering"), - ("window-covering_full", "cover.mock_full_window_covering"), + ("window-covering_tilt", "cover.mock_tilt_window_covering_cover"), + ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering_cover"), + ("window-covering_full", "cover.mock_full_window_covering_cover"), ], ) async def test_cover_tilt( @@ -317,7 +317,7 @@ async def test_cover_tilt( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_tilt", "cover.mock_tilt_window_covering"), + ("window-covering_tilt", "cover.mock_tilt_window_covering_cover"), ], ) async def test_cover_tilt_only( @@ -360,7 +360,7 @@ async def test_cover_tilt_only( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering"), + ("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering_cover"), ], ) async def test_cover_position_aware_tilt( @@ -410,7 +410,7 @@ async def test_cover_full_features( "window-covering_full", matter_client, ) - entity_id = "cover.mock_full_window_covering" + entity_id = "cover.mock_full_window_covering_cover" state = hass.states.get(entity_id) assert state diff --git a/tests/components/matter/test_door_lock.py b/tests/components/matter/test_door_lock.py index 6e0e0846ad5..a0664612aba 100644 --- a/tests/components/matter/test_door_lock.py +++ b/tests/components/matter/test_door_lock.py @@ -34,7 +34,7 @@ async def test_lock( "lock", "unlock", { - "entity_id": "lock.mock_door_lock", + "entity_id": "lock.mock_door_lock_lock", }, blocking=True, ) @@ -52,7 +52,7 @@ async def test_lock( "lock", "lock", { - "entity_id": "lock.mock_door_lock", + "entity_id": "lock.mock_door_lock_lock", }, blocking=True, ) @@ -66,35 +66,35 @@ async def test_lock( ) matter_client.send_device_command.reset_mock() - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_LOCKED set_node_attribute(door_lock, 1, 257, 0, 0) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_UNLOCKING set_node_attribute(door_lock, 1, 257, 0, 2) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_UNLOCKED set_node_attribute(door_lock, 1, 257, 0, 0) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_LOCKING set_node_attribute(door_lock, 1, 257, 0, None) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_UNKNOWN @@ -122,7 +122,7 @@ async def test_lock_requires_pin( await hass.services.async_call( "lock", "lock", - {"entity_id": "lock.mock_door_lock", ATTR_CODE: "1234"}, + {"entity_id": "lock.mock_door_lock_lock", ATTR_CODE: "1234"}, blocking=True, ) @@ -131,7 +131,7 @@ async def test_lock_requires_pin( await hass.services.async_call( "lock", "lock", - {"entity_id": "lock.mock_door_lock", ATTR_CODE: code}, + {"entity_id": "lock.mock_door_lock_lock", ATTR_CODE: code}, blocking=True, ) assert matter_client.send_device_command.call_count == 1 @@ -145,13 +145,13 @@ async def test_lock_requires_pin( # Lock door using default code default_code = "7654321" entity_registry.async_update_entity_options( - "lock.mock_door_lock", "lock", {"default_code": default_code} + "lock.mock_door_lock_lock", "lock", {"default_code": default_code} ) await trigger_subscription_callback(hass, matter_client) await hass.services.async_call( "lock", "lock", - {"entity_id": "lock.mock_door_lock"}, + {"entity_id": "lock.mock_door_lock_lock"}, blocking=True, ) assert matter_client.send_device_command.call_count == 2 @@ -171,7 +171,7 @@ async def test_lock_with_unbolt( door_lock_with_unbolt: MatterNode, ) -> None: """Test door lock.""" - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_LOCKED assert state.attributes["supported_features"] & LockEntityFeature.OPEN @@ -180,7 +180,7 @@ async def test_lock_with_unbolt( "lock", "unlock", { - "entity_id": "lock.mock_door_lock", + "entity_id": "lock.mock_door_lock_lock", }, blocking=True, ) @@ -198,7 +198,7 @@ async def test_lock_with_unbolt( "lock", "open", { - "entity_id": "lock.mock_door_lock", + "entity_id": "lock.mock_door_lock_lock", }, blocking=True, ) @@ -213,6 +213,6 @@ async def test_lock_with_unbolt( set_node_attribute(door_lock_with_unbolt, 1, 257, 3, 0) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("lock.mock_door_lock") + state = hass.states.get("lock.mock_door_lock_lock") assert state assert state.state == STATE_OPEN diff --git a/tests/components/matter/test_event.py b/tests/components/matter/test_event.py index 2bdcfb6adb7..a7bd7c91f7b 100644 --- a/tests/components/matter/test_event.py +++ b/tests/components/matter/test_event.py @@ -40,11 +40,10 @@ async def test_generic_switch_node( generic_switch_node: MatterNode, ) -> None: """Test event entity for a GenericSwitch node.""" - state = hass.states.get("event.mock_generic_switch") + state = hass.states.get("event.mock_generic_switch_button") assert state assert state.state == "unknown" - # the switch endpoint has no label so the entity name should be the device itself - assert state.name == "Mock Generic Switch" + assert state.name == "Mock Generic Switch Button" # check event_types from featuremap 30 assert state.attributes[ATTR_EVENT_TYPES] == [ "initial_press", @@ -71,7 +70,7 @@ async def test_generic_switch_node( data=None, ), ) - state = hass.states.get("event.mock_generic_switch") + state = hass.states.get("event.mock_generic_switch_button") assert state.attributes[ATTR_EVENT_TYPE] == "initial_press" # trigger firing a multi press event await trigger_subscription_callback( @@ -90,7 +89,7 @@ async def test_generic_switch_node( data={"NewPosition": 3}, ), ) - state = hass.states.get("event.mock_generic_switch") + state = hass.states.get("event.mock_generic_switch_button") assert state.attributes[ATTR_EVENT_TYPE] == "multi_press_ongoing" assert state.attributes["NewPosition"] == 3 @@ -106,8 +105,8 @@ async def test_generic_switch_multi_node( state_button_1 = hass.states.get("event.mock_generic_switch_button_1") assert state_button_1 assert state_button_1.state == "unknown" - # name should be 'DeviceName Button 1' due to the label set to just '1' - assert state_button_1.name == "Mock Generic Switch Button 1" + # name should be 'DeviceName Button (1)' due to the label set to just '1' + assert state_button_1.name == "Mock Generic Switch Button (1)" # check event_types from featuremap 14 assert state_button_1.attributes[ATTR_EVENT_TYPES] == [ "initial_press", diff --git a/tests/components/matter/test_fan.py b/tests/components/matter/test_fan.py index 3c4a990018b..30bd7f4a009 100644 --- a/tests/components/matter/test_fan.py +++ b/tests/components/matter/test_fan.py @@ -45,7 +45,7 @@ async def test_fan_base( air_purifier: MatterNode, ) -> None: """Test Fan platform.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" state = hass.states.get(entity_id) assert state assert state.attributes["preset_modes"] == [ @@ -100,7 +100,7 @@ async def test_fan_turn_on_with_percentage( air_purifier: MatterNode, ) -> None: """Test turning on the fan with a specific percentage.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" await hass.services.async_call( FAN_DOMAIN, SERVICE_TURN_ON, @@ -121,7 +121,7 @@ async def test_fan_turn_on_with_preset_mode( air_purifier: MatterNode, ) -> None: """Test turning on the fan with a specific preset mode.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" await hass.services.async_call( FAN_DOMAIN, SERVICE_TURN_ON, @@ -193,7 +193,7 @@ async def test_fan_turn_off( air_purifier: MatterNode, ) -> None: """Test turning off the fan.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" await hass.services.async_call( FAN_DOMAIN, SERVICE_TURN_OFF, @@ -235,7 +235,7 @@ async def test_fan_oscillate( air_purifier: MatterNode, ) -> None: """Test oscillating the fan.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" for oscillating, value in ((True, 1), (False, 0)): await hass.services.async_call( FAN_DOMAIN, @@ -258,7 +258,7 @@ async def test_fan_set_direction( air_purifier: MatterNode, ) -> None: """Test oscillating the fan.""" - entity_id = "fan.air_purifier" + entity_id = "fan.air_purifier_fan" for direction, value in ((DIRECTION_FORWARD, 0), (DIRECTION_REVERSE, 1)): await hass.services.async_call( FAN_DOMAIN, diff --git a/tests/components/matter/test_init.py b/tests/components/matter/test_init.py index e3d8e799658..d3712f24d12 100644 --- a/tests/components/matter/test_init.py +++ b/tests/components/matter/test_init.py @@ -69,7 +69,7 @@ async def test_entry_setup_unload( assert matter_client.connect.call_count == 1 assert entry.state is ConfigEntryState.LOADED - entity_state = hass.states.get("light.mock_onoff_light") + entity_state = hass.states.get("light.mock_onoff_light_light") assert entity_state assert entity_state.state != STATE_UNAVAILABLE @@ -77,7 +77,7 @@ async def test_entry_setup_unload( assert matter_client.disconnect.call_count == 1 assert entry.state is ConfigEntryState.NOT_LOADED - entity_state = hass.states.get("light.mock_onoff_light") + entity_state = hass.states.get("light.mock_onoff_light_light") assert entity_state assert entity_state.state == STATE_UNAVAILABLE @@ -625,7 +625,7 @@ async def test_remove_config_entry_device( device_entry = dr.async_entries_for_config_entry( device_registry, config_entry.entry_id )[0] - entity_id = "light.m5stamp_lighting_app" + entity_id = "light.m5stamp_lighting_app_light" assert device_entry assert entity_registry.async_get(entity_id) diff --git a/tests/components/matter/test_light.py b/tests/components/matter/test_light.py index 2589e041b3b..4fd73b6457b 100644 --- a/tests/components/matter/test_light.py +++ b/tests/components/matter/test_light.py @@ -22,17 +22,17 @@ from .common import ( [ ( "extended-color-light", - "light.mock_extended_color_light", + "light.mock_extended_color_light_light", ["color_temp", "hs", "xy"], ), ( "color-temperature-light", - "light.mock_color_temperature_light", + "light.mock_color_temperature_light_light", ["color_temp"], ), - ("dimmable-light", "light.mock_dimmable_light", ["brightness"]), - ("onoff-light", "light.mock_onoff_light", ["onoff"]), - ("onoff-light-with-levelcontrol-present", "light.d215s", ["onoff"]), + ("dimmable-light", "light.mock_dimmable_light_light", ["brightness"]), + ("onoff-light", "light.mock_onoff_light_light", ["onoff"]), + ("onoff-light-with-levelcontrol-present", "light.d215s_light", ["onoff"]), ], ) async def test_light_turn_on_off( @@ -113,10 +113,10 @@ async def test_light_turn_on_off( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("extended-color-light", "light.mock_extended_color_light"), - ("color-temperature-light", "light.mock_color_temperature_light"), - ("dimmable-light", "light.mock_dimmable_light"), - ("dimmable-plugin-unit", "light.dimmable_plugin_unit"), + ("extended-color-light", "light.mock_extended_color_light_light"), + ("color-temperature-light", "light.mock_color_temperature_light_light"), + ("dimmable-light", "light.mock_dimmable_light_light"), + ("dimmable-plugin-unit", "light.dimmable_plugin_unit_light"), ], ) async def test_dimmable_light( @@ -189,8 +189,8 @@ async def test_dimmable_light( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("extended-color-light", "light.mock_extended_color_light"), - ("color-temperature-light", "light.mock_color_temperature_light"), + ("extended-color-light", "light.mock_extended_color_light_light"), + ("color-temperature-light", "light.mock_color_temperature_light_light"), ], ) async def test_color_temperature_light( @@ -287,7 +287,7 @@ async def test_color_temperature_light( @pytest.mark.parametrize( ("fixture", "entity_id"), [ - ("extended-color-light", "light.mock_extended_color_light"), + ("extended-color-light", "light.mock_extended_color_light_light"), ], ) async def test_extended_color_light( diff --git a/tests/components/matter/test_switch.py b/tests/components/matter/test_switch.py index 5fc23fa7b34..0327e9ea5fe 100644 --- a/tests/components/matter/test_switch.py +++ b/tests/components/matter/test_switch.py @@ -41,7 +41,7 @@ async def test_turn_on( powerplug_node: MatterNode, ) -> None: """Test turning on a switch.""" - state = hass.states.get("switch.mock_onoffpluginunit_powerplug_switch") + state = hass.states.get("switch.mock_onoffpluginunit_switch") assert state assert state.state == "off" @@ -49,7 +49,7 @@ async def test_turn_on( "switch", "turn_on", { - "entity_id": "switch.mock_onoffpluginunit_powerplug_switch", + "entity_id": "switch.mock_onoffpluginunit_switch", }, blocking=True, ) @@ -64,7 +64,7 @@ async def test_turn_on( set_node_attribute(powerplug_node, 1, 6, 0, True) await trigger_subscription_callback(hass, matter_client) - state = hass.states.get("switch.mock_onoffpluginunit_powerplug_switch") + state = hass.states.get("switch.mock_onoffpluginunit_switch") assert state assert state.state == "on" @@ -77,7 +77,7 @@ async def test_turn_off( powerplug_node: MatterNode, ) -> None: """Test turning off a switch.""" - state = hass.states.get("switch.mock_onoffpluginunit_powerplug_switch") + state = hass.states.get("switch.mock_onoffpluginunit_switch") assert state assert state.state == "off" @@ -85,7 +85,7 @@ async def test_turn_off( "switch", "turn_off", { - "entity_id": "switch.mock_onoffpluginunit_powerplug_switch", + "entity_id": "switch.mock_onoffpluginunit_switch", }, blocking=True, ) @@ -109,7 +109,23 @@ async def test_switch_unit( # A switch entity should be discovered as fallback for ANY Matter device (endpoint) # that has the OnOff cluster and does not fall into an explicit discovery schema # by another platform (e.g. light, lock etc.). - state = hass.states.get("switch.mock_switchunit") + state = hass.states.get("switch.mock_switchunit_switch") assert state assert state.state == "off" - assert state.attributes["friendly_name"] == "Mock SwitchUnit" + assert state.attributes["friendly_name"] == "Mock SwitchUnit Switch" + + +# This tests needs to be adjusted to remove lingering tasks +@pytest.mark.parametrize("expected_lingering_tasks", [True]) +async def test_power_switch( + hass: HomeAssistant, + matter_client: MagicMock, +) -> None: + """Test if a Power switch entity is created for a device that supports that.""" + await setup_integration_with_node_fixture( + hass, "room-airconditioner", matter_client + ) + state = hass.states.get("switch.room_airconditioner_power") + assert state + assert state.state == "off" + assert state.attributes["friendly_name"] == "Room AirConditioner Power"