Fix Matter entity names (#120038)
parent
180c244a78
commit
4110f4f393
|
@ -321,7 +321,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
platform=Platform.CLIMATE,
|
platform=Platform.CLIMATE,
|
||||||
entity_description=ClimateEntityDescription(
|
entity_description=ClimateEntityDescription(
|
||||||
key="MatterThermostat",
|
key="MatterThermostat",
|
||||||
name=None,
|
translation_key="thermostat",
|
||||||
),
|
),
|
||||||
entity_class=MatterClimate,
|
entity_class=MatterClimate,
|
||||||
required_attributes=(clusters.Thermostat.Attributes.LocalTemperature,),
|
required_attributes=(clusters.Thermostat.Attributes.LocalTemperature,),
|
||||||
|
|
|
@ -200,7 +200,9 @@ class MatterCover(MatterEntity, CoverEntity):
|
||||||
DISCOVERY_SCHEMAS = [
|
DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.COVER,
|
platform=Platform.COVER,
|
||||||
entity_description=CoverEntityDescription(key="MatterCover", name=None),
|
entity_description=CoverEntityDescription(
|
||||||
|
key="MatterCover", translation_key="cover"
|
||||||
|
),
|
||||||
entity_class=MatterCover,
|
entity_class=MatterCover,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
clusters.WindowCovering.Attributes.OperationalStatus,
|
clusters.WindowCovering.Attributes.OperationalStatus,
|
||||||
|
@ -214,7 +216,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.COVER,
|
platform=Platform.COVER,
|
||||||
entity_description=CoverEntityDescription(
|
entity_description=CoverEntityDescription(
|
||||||
key="MatterCoverPositionAwareLift", name=None
|
key="MatterCoverPositionAwareLift", translation_key="cover"
|
||||||
),
|
),
|
||||||
entity_class=MatterCover,
|
entity_class=MatterCover,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
@ -229,7 +231,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.COVER,
|
platform=Platform.COVER,
|
||||||
entity_description=CoverEntityDescription(
|
entity_description=CoverEntityDescription(
|
||||||
key="MatterCoverPositionAwareTilt", name=None
|
key="MatterCoverPositionAwareTilt", translation_key="cover"
|
||||||
),
|
),
|
||||||
entity_class=MatterCover,
|
entity_class=MatterCover,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
@ -244,7 +246,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.COVER,
|
platform=Platform.COVER,
|
||||||
entity_description=CoverEntityDescription(
|
entity_description=CoverEntityDescription(
|
||||||
key="MatterCoverPositionAwareLiftAndTilt", name=None
|
key="MatterCoverPositionAwareLiftAndTilt", translation_key="cover"
|
||||||
),
|
),
|
||||||
entity_class=MatterCover,
|
entity_class=MatterCover,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
|
|
@ -5,9 +5,11 @@ from __future__ import annotations
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from functools import cached_property
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any, cast
|
from typing import TYPE_CHECKING, Any, cast
|
||||||
|
|
||||||
|
from chip.clusters import Objects as clusters
|
||||||
from chip.clusters.Objects import ClusterAttributeDescriptor, NullValue
|
from chip.clusters.Objects import ClusterAttributeDescriptor, NullValue
|
||||||
from matter_server.common.helpers.util import create_attribute_path
|
from matter_server.common.helpers.util import create_attribute_path
|
||||||
from matter_server.common.models import EventType, ServerInfoMessage
|
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.core import callback
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||||
|
from homeassistant.helpers.typing import UndefinedType
|
||||||
|
|
||||||
from .const import DOMAIN, ID_TYPE_DEVICE_ID
|
from .const import DOMAIN, ID_TYPE_DEVICE_ID
|
||||||
from .helpers import get_device_id
|
from .helpers import get_device_id
|
||||||
|
@ -41,6 +44,7 @@ class MatterEntity(Entity):
|
||||||
"""Entity class for Matter devices."""
|
"""Entity class for Matter devices."""
|
||||||
|
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
|
_name_postfix: str | None = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -71,6 +75,35 @@ class MatterEntity(Entity):
|
||||||
identifiers={(DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")}
|
identifiers={(DOMAIN, f"{ID_TYPE_DEVICE_ID}_{node_device_id}")}
|
||||||
)
|
)
|
||||||
self._attr_available = self._endpoint.node.available
|
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
|
# make sure to update the attributes once
|
||||||
self._update_from_device()
|
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
|
@callback
|
||||||
def _on_matter_event(self, event: EventType, data: Any = None) -> None:
|
def _on_matter_event(self, event: EventType, data: Any = None) -> None:
|
||||||
"""Call on update from the device."""
|
"""Call on update from the device."""
|
||||||
|
|
|
@ -49,8 +49,6 @@ async def async_setup_entry(
|
||||||
class MatterEventEntity(MatterEntity, EventEntity):
|
class MatterEventEntity(MatterEntity, EventEntity):
|
||||||
"""Representation of a Matter Event entity."""
|
"""Representation of a Matter Event entity."""
|
||||||
|
|
||||||
_attr_translation_key = "push"
|
|
||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -72,21 +70,6 @@ class MatterEventEntity(MatterEntity, EventEntity):
|
||||||
event_types.append("multi_press_ongoing")
|
event_types.append("multi_press_ongoing")
|
||||||
event_types.append("multi_press_complete")
|
event_types.append("multi_press_complete")
|
||||||
self._attr_event_types = event_types
|
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:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Handle being added to Home Assistant."""
|
"""Handle being added to Home Assistant."""
|
||||||
|
@ -122,7 +105,9 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.EVENT,
|
platform=Platform.EVENT,
|
||||||
entity_description=EventEntityDescription(
|
entity_description=EventEntityDescription(
|
||||||
key="GenericSwitch", device_class=EventDeviceClass.BUTTON, name=None
|
key="GenericSwitch",
|
||||||
|
device_class=EventDeviceClass.BUTTON,
|
||||||
|
translation_key="button",
|
||||||
),
|
),
|
||||||
entity_class=MatterEventEntity,
|
entity_class=MatterEventEntity,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
|
|
@ -421,7 +421,9 @@ class MatterLight(MatterEntity, LightEntity):
|
||||||
DISCOVERY_SCHEMAS = [
|
DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.LIGHT,
|
platform=Platform.LIGHT,
|
||||||
entity_description=LightEntityDescription(key="MatterLight", name=None),
|
entity_description=LightEntityDescription(
|
||||||
|
key="MatterLight", translation_key="light"
|
||||||
|
),
|
||||||
entity_class=MatterLight,
|
entity_class=MatterLight,
|
||||||
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
||||||
optional_attributes=(
|
optional_attributes=(
|
||||||
|
@ -445,7 +447,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.LIGHT,
|
platform=Platform.LIGHT,
|
||||||
entity_description=LightEntityDescription(
|
entity_description=LightEntityDescription(
|
||||||
key="MatterHSColorLightFallback", name=None
|
key="MatterHSColorLightFallback", translation_key="light"
|
||||||
),
|
),
|
||||||
entity_class=MatterLight,
|
entity_class=MatterLight,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
@ -465,7 +467,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.LIGHT,
|
platform=Platform.LIGHT,
|
||||||
entity_description=LightEntityDescription(
|
entity_description=LightEntityDescription(
|
||||||
key="MatterXYColorLightFallback", name=None
|
key="MatterXYColorLightFallback", translation_key="light"
|
||||||
),
|
),
|
||||||
entity_class=MatterLight,
|
entity_class=MatterLight,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
@ -485,7 +487,7 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.LIGHT,
|
platform=Platform.LIGHT,
|
||||||
entity_description=LightEntityDescription(
|
entity_description=LightEntityDescription(
|
||||||
key="MatterColorTemperatureLightFallback", name=None
|
key="MatterColorTemperatureLightFallback", translation_key="light"
|
||||||
),
|
),
|
||||||
entity_class=MatterLight,
|
entity_class=MatterLight,
|
||||||
required_attributes=(
|
required_attributes=(
|
||||||
|
|
|
@ -176,7 +176,9 @@ class MatterLock(MatterEntity, LockEntity):
|
||||||
DISCOVERY_SCHEMAS = [
|
DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.LOCK,
|
platform=Platform.LOCK,
|
||||||
entity_description=LockEntityDescription(key="MatterLock", name=None),
|
entity_description=LockEntityDescription(
|
||||||
|
key="MatterLock", translation_key="lock"
|
||||||
|
),
|
||||||
entity_class=MatterLock,
|
entity_class=MatterLock,
|
||||||
required_attributes=(clusters.DoorLock.Attributes.LockState,),
|
required_attributes=(clusters.DoorLock.Attributes.LockState,),
|
||||||
optional_attributes=(clusters.DoorLock.Attributes.DoorState,),
|
optional_attributes=(clusters.DoorLock.Attributes.DoorState,),
|
||||||
|
|
|
@ -107,6 +107,3 @@ class MatterDiscoverySchema:
|
||||||
# [optional] bool to specify if this primary value may be discovered
|
# [optional] bool to specify if this primary value may be discovered
|
||||||
# by multiple platforms
|
# by multiple platforms
|
||||||
allow_multi: bool = False
|
allow_multi: bool = False
|
||||||
|
|
||||||
# [optional] bool to specify if this primary value should be polled
|
|
||||||
should_poll: bool = False
|
|
||||||
|
|
|
@ -45,8 +45,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entity": {
|
"entity": {
|
||||||
|
"climate": {
|
||||||
|
"thermostat": {
|
||||||
|
"name": "Thermostat"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cover": {
|
||||||
|
"cover": {
|
||||||
|
"name": "[%key:component::cover::title%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
"event": {
|
"event": {
|
||||||
"push": {
|
"button": {
|
||||||
|
"name": "Button",
|
||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"event_type": {
|
"event_type": {
|
||||||
"state": {
|
"state": {
|
||||||
|
@ -64,6 +75,7 @@
|
||||||
},
|
},
|
||||||
"fan": {
|
"fan": {
|
||||||
"fan": {
|
"fan": {
|
||||||
|
"name": "[%key:component::fan::title%]",
|
||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
"state": {
|
"state": {
|
||||||
|
@ -92,6 +104,16 @@
|
||||||
"name": "On/Off transition time"
|
"name": "On/Off transition time"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"light": {
|
||||||
|
"light": {
|
||||||
|
"name": "[%key:component::light::title%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lock": {
|
||||||
|
"lock": {
|
||||||
|
"name": "[%key:component::lock::title%]"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
"activated_carbon_filter_condition": {
|
"activated_carbon_filter_condition": {
|
||||||
"name": "Activated carbon filter condition"
|
"name": "Activated carbon filter condition"
|
||||||
|
@ -114,6 +136,14 @@
|
||||||
"hepa_filter_condition": {
|
"hepa_filter_condition": {
|
||||||
"name": "Hepa filter condition"
|
"name": "Hepa filter condition"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"switch": {
|
||||||
|
"switch": {
|
||||||
|
"name": "[%key:component::switch::title%]"
|
||||||
|
},
|
||||||
|
"power": {
|
||||||
|
"name": "Power"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
|
|
|
@ -64,7 +64,9 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SWITCH,
|
platform=Platform.SWITCH,
|
||||||
entity_description=SwitchEntityDescription(
|
entity_description=SwitchEntityDescription(
|
||||||
key="MatterPlug", device_class=SwitchDeviceClass.OUTLET, name=None
|
key="MatterPlug",
|
||||||
|
device_class=SwitchDeviceClass.OUTLET,
|
||||||
|
translation_key="switch",
|
||||||
),
|
),
|
||||||
entity_class=MatterSwitch,
|
entity_class=MatterSwitch,
|
||||||
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
||||||
|
@ -73,7 +75,38 @@ DISCOVERY_SCHEMAS = [
|
||||||
MatterDiscoverySchema(
|
MatterDiscoverySchema(
|
||||||
platform=Platform.SWITCH,
|
platform=Platform.SWITCH,
|
||||||
entity_description=SwitchEntityDescription(
|
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,
|
entity_class=MatterSwitch,
|
||||||
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
required_attributes=(clusters.OnOff.Attributes.OnOff,),
|
||||||
|
@ -83,6 +116,23 @@ DISCOVERY_SCHEMAS = [
|
||||||
device_types.ExtendedColorLight,
|
device_types.ExtendedColorLight,
|
||||||
device_types.ColorDimmerSwitch,
|
device_types.ColorDimmerSwitch,
|
||||||
device_types.OnOffLight,
|
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,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,7 +24,7 @@
|
||||||
"0/40/0": 1,
|
"0/40/0": 1,
|
||||||
"0/40/1": "Nabu Casa",
|
"0/40/1": "Nabu Casa",
|
||||||
"0/40/2": 65521,
|
"0/40/2": 65521,
|
||||||
"0/40/3": "Mock OnOffPluginUnit (powerplug/switch)",
|
"0/40/3": "Mock OnOffPluginUnit",
|
||||||
"0/40/4": 32768,
|
"0/40/4": 32768,
|
||||||
"0/40/5": "",
|
"0/40/5": "",
|
||||||
"0/40/6": "XX",
|
"0/40/6": "XX",
|
||||||
|
|
|
@ -81,7 +81,7 @@ async def test_device_registry_single_node_device_alt(
|
||||||
assert entry is not None
|
assert entry is not None
|
||||||
|
|
||||||
# test name is derived from productName (because nodeLabel is absent)
|
# 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
|
# test serial id NOT present as additional identifier
|
||||||
assert (DOMAIN, "serial_TEST_SN") not in entry.identifiers
|
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
|
assert not entity_state
|
||||||
|
|
||||||
node_added_callback(EventType.NODE_ADDED, node)
|
node_added_callback(EventType.NODE_ADDED, node)
|
||||||
await hass.async_block_till_done()
|
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
|
assert entity_state
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,6 +187,24 @@ async def test_device_registry_single_node_composed_device(
|
||||||
assert len(dev_reg.devices) == 1
|
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:
|
async def test_get_clean_name_() -> None:
|
||||||
"""Test get_clean_name helper.
|
"""Test get_clean_name helper.
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ async def test_thermostat_base(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test thermostat base attributes and state updates."""
|
"""Test thermostat base attributes and state updates."""
|
||||||
# test entity attributes
|
# test entity attributes
|
||||||
state = hass.states.get("climate.longan_link_hvac")
|
state = hass.states.get("climate.longan_link_hvac_thermostat")
|
||||||
assert state
|
assert state
|
||||||
assert state.attributes["min_temp"] == 7
|
assert state.attributes["min_temp"] == 7
|
||||||
assert state.attributes["max_temp"] == 35
|
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, 5, 1600)
|
||||||
set_node_attribute(thermostat, 1, 513, 6, 3000)
|
set_node_attribute(thermostat, 1, 513, 6, 3000)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["min_temp"] == 16
|
assert state.attributes["min_temp"] == 16
|
||||||
assert state.attributes["max_temp"] == 30
|
assert state.attributes["max_temp"] == 30
|
||||||
|
@ -80,56 +80,56 @@ async def test_thermostat_base(
|
||||||
# test system mode update from device
|
# test system mode update from device
|
||||||
set_node_attribute(thermostat, 1, 513, 28, 0)
|
set_node_attribute(thermostat, 1, 513, 28, 0)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.OFF
|
assert state.state == HVACMode.OFF
|
||||||
|
|
||||||
# test running state update from device
|
# test running state update from device
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 1)
|
set_node_attribute(thermostat, 1, 513, 41, 1)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.HEATING
|
assert state.attributes["hvac_action"] == HVACAction.HEATING
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 8)
|
set_node_attribute(thermostat, 1, 513, 41, 8)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.HEATING
|
assert state.attributes["hvac_action"] == HVACAction.HEATING
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 2)
|
set_node_attribute(thermostat, 1, 513, 41, 2)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.COOLING
|
assert state.attributes["hvac_action"] == HVACAction.COOLING
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 16)
|
set_node_attribute(thermostat, 1, 513, 41, 16)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.COOLING
|
assert state.attributes["hvac_action"] == HVACAction.COOLING
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 4)
|
set_node_attribute(thermostat, 1, 513, 41, 4)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.FAN
|
assert state.attributes["hvac_action"] == HVACAction.FAN
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 32)
|
set_node_attribute(thermostat, 1, 513, 41, 32)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.FAN
|
assert state.attributes["hvac_action"] == HVACAction.FAN
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 64)
|
set_node_attribute(thermostat, 1, 513, 41, 64)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.FAN
|
assert state.attributes["hvac_action"] == HVACAction.FAN
|
||||||
|
|
||||||
set_node_attribute(thermostat, 1, 513, 41, 66)
|
set_node_attribute(thermostat, 1, 513, 41, 66)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["hvac_action"] == HVACAction.OFF
|
assert state.attributes["hvac_action"] == HVACAction.OFF
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ async def test_thermostat_base(
|
||||||
set_node_attribute(thermostat, 1, 513, 28, 4)
|
set_node_attribute(thermostat, 1, 513, 28, 4)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.HEAT
|
assert state.state == HVACMode.HEAT
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ async def test_thermostat_base(
|
||||||
set_node_attribute(thermostat, 1, 513, 18, 2000)
|
set_node_attribute(thermostat, 1, 513, 18, 2000)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.attributes["temperature"] == 20
|
assert state.attributes["temperature"] == 20
|
||||||
|
|
||||||
|
@ -159,14 +159,14 @@ async def test_thermostat_service_calls(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test climate platform service calls."""
|
"""Test climate platform service calls."""
|
||||||
# test single-setpoint temperature adjustment when cool mode is active
|
# 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
|
||||||
assert state.state == HVACMode.COOL
|
assert state.state == HVACMode.COOL
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"climate",
|
"climate",
|
||||||
"set_temperature",
|
"set_temperature",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"temperature": 25,
|
"temperature": 25,
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
|
@ -187,7 +187,7 @@ async def test_thermostat_service_calls(
|
||||||
"climate",
|
"climate",
|
||||||
"set_temperature",
|
"set_temperature",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"temperature": 25,
|
"temperature": 25,
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
|
@ -199,7 +199,7 @@ async def test_thermostat_service_calls(
|
||||||
# test single-setpoint temperature adjustment when heat mode is active
|
# test single-setpoint temperature adjustment when heat mode is active
|
||||||
set_node_attribute(thermostat, 1, 513, 28, 4)
|
set_node_attribute(thermostat, 1, 513, 28, 4)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.HEAT
|
assert state.state == HVACMode.HEAT
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ async def test_thermostat_service_calls(
|
||||||
"climate",
|
"climate",
|
||||||
"set_temperature",
|
"set_temperature",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"temperature": 20,
|
"temperature": 20,
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
|
@ -224,7 +224,7 @@ async def test_thermostat_service_calls(
|
||||||
# test dual setpoint temperature adjustments when heat_cool mode is active
|
# test dual setpoint temperature adjustments when heat_cool mode is active
|
||||||
set_node_attribute(thermostat, 1, 513, 28, 1)
|
set_node_attribute(thermostat, 1, 513, 28, 1)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.HEAT_COOL
|
assert state.state == HVACMode.HEAT_COOL
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ async def test_thermostat_service_calls(
|
||||||
"climate",
|
"climate",
|
||||||
"set_temperature",
|
"set_temperature",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"target_temp_low": 10,
|
"target_temp_low": 10,
|
||||||
"target_temp_high": 30,
|
"target_temp_high": 30,
|
||||||
},
|
},
|
||||||
|
@ -257,7 +257,7 @@ async def test_thermostat_service_calls(
|
||||||
"climate",
|
"climate",
|
||||||
"set_hvac_mode",
|
"set_hvac_mode",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"hvac_mode": HVACMode.HEAT,
|
"hvac_mode": HVACMode.HEAT,
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
|
@ -281,7 +281,7 @@ async def test_thermostat_service_calls(
|
||||||
"climate",
|
"climate",
|
||||||
"set_temperature",
|
"set_temperature",
|
||||||
{
|
{
|
||||||
"entity_id": "climate.longan_link_hvac",
|
"entity_id": "climate.longan_link_hvac_thermostat",
|
||||||
"temperature": 22,
|
"temperature": 22,
|
||||||
"hvac_mode": HVACMode.COOL,
|
"hvac_mode": HVACMode.COOL,
|
||||||
},
|
},
|
||||||
|
@ -312,7 +312,7 @@ async def test_room_airconditioner(
|
||||||
room_airconditioner: MatterNode,
|
room_airconditioner: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test if a climate entity is created for a Room Airconditioner device."""
|
"""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
|
||||||
assert state.attributes["current_temperature"] == 20
|
assert state.attributes["current_temperature"] == 20
|
||||||
assert state.attributes["min_temp"] == 16
|
assert state.attributes["min_temp"] == 16
|
||||||
|
@ -335,13 +335,13 @@ async def test_room_airconditioner(
|
||||||
# test fan-only hvac mode
|
# test fan-only hvac mode
|
||||||
set_node_attribute(room_airconditioner, 1, 513, 28, 7)
|
set_node_attribute(room_airconditioner, 1, 513, 28, 7)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.FAN_ONLY
|
assert state.state == HVACMode.FAN_ONLY
|
||||||
|
|
||||||
# test dry hvac mode
|
# test dry hvac mode
|
||||||
set_node_attribute(room_airconditioner, 1, 513, 28, 8)
|
set_node_attribute(room_airconditioner, 1, 513, 28, 8)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == HVACMode.DRY
|
assert state.state == HVACMode.DRY
|
||||||
|
|
|
@ -27,11 +27,11 @@ from .common import (
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("fixture", "entity_id"),
|
||||||
[
|
[
|
||||||
("window-covering_lift", "cover.mock_lift_window_covering"),
|
("window-covering_lift", "cover.mock_lift_window_covering_cover"),
|
||||||
("window-covering_pa-lift", "cover.longan_link_wncv_da01"),
|
("window-covering_pa-lift", "cover.longan_link_wncv_da01_cover"),
|
||||||
("window-covering_tilt", "cover.mock_tilt_window_covering"),
|
("window-covering_tilt", "cover.mock_tilt_window_covering_cover"),
|
||||||
("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering"),
|
("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering_cover"),
|
||||||
("window-covering_full", "cover.mock_full_window_covering"),
|
("window-covering_full", "cover.mock_full_window_covering_cover"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_cover(
|
async def test_cover(
|
||||||
|
@ -105,9 +105,9 @@ async def test_cover(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("fixture", "entity_id"),
|
||||||
[
|
[
|
||||||
("window-covering_lift", "cover.mock_lift_window_covering"),
|
("window-covering_lift", "cover.mock_lift_window_covering_cover"),
|
||||||
("window-covering_pa-lift", "cover.longan_link_wncv_da01"),
|
("window-covering_pa-lift", "cover.longan_link_wncv_da01_cover"),
|
||||||
("window-covering_full", "cover.mock_full_window_covering"),
|
("window-covering_full", "cover.mock_full_window_covering_cover"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_cover_lift(
|
async def test_cover_lift(
|
||||||
|
@ -162,7 +162,7 @@ async def test_cover_lift(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("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(
|
async def test_cover_lift_only(
|
||||||
|
@ -207,7 +207,7 @@ async def test_cover_lift_only(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("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(
|
async def test_cover_position_aware_lift(
|
||||||
|
@ -259,9 +259,9 @@ async def test_cover_position_aware_lift(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("fixture", "entity_id"),
|
||||||
[
|
[
|
||||||
("window-covering_tilt", "cover.mock_tilt_window_covering"),
|
("window-covering_tilt", "cover.mock_tilt_window_covering_cover"),
|
||||||
("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering"),
|
("window-covering_pa-tilt", "cover.mock_pa_tilt_window_covering_cover"),
|
||||||
("window-covering_full", "cover.mock_full_window_covering"),
|
("window-covering_full", "cover.mock_full_window_covering_cover"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_cover_tilt(
|
async def test_cover_tilt(
|
||||||
|
@ -317,7 +317,7 @@ async def test_cover_tilt(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("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(
|
async def test_cover_tilt_only(
|
||||||
|
@ -360,7 +360,7 @@ async def test_cover_tilt_only(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("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(
|
async def test_cover_position_aware_tilt(
|
||||||
|
@ -410,7 +410,7 @@ async def test_cover_full_features(
|
||||||
"window-covering_full",
|
"window-covering_full",
|
||||||
matter_client,
|
matter_client,
|
||||||
)
|
)
|
||||||
entity_id = "cover.mock_full_window_covering"
|
entity_id = "cover.mock_full_window_covering_cover"
|
||||||
|
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
|
|
|
@ -34,7 +34,7 @@ async def test_lock(
|
||||||
"lock",
|
"lock",
|
||||||
"unlock",
|
"unlock",
|
||||||
{
|
{
|
||||||
"entity_id": "lock.mock_door_lock",
|
"entity_id": "lock.mock_door_lock_lock",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -52,7 +52,7 @@ async def test_lock(
|
||||||
"lock",
|
"lock",
|
||||||
"lock",
|
"lock",
|
||||||
{
|
{
|
||||||
"entity_id": "lock.mock_door_lock",
|
"entity_id": "lock.mock_door_lock_lock",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -66,35 +66,35 @@ async def test_lock(
|
||||||
)
|
)
|
||||||
matter_client.send_device_command.reset_mock()
|
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
|
||||||
assert state.state == STATE_LOCKED
|
assert state.state == STATE_LOCKED
|
||||||
|
|
||||||
set_node_attribute(door_lock, 1, 257, 0, 0)
|
set_node_attribute(door_lock, 1, 257, 0, 0)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == STATE_UNLOCKING
|
assert state.state == STATE_UNLOCKING
|
||||||
|
|
||||||
set_node_attribute(door_lock, 1, 257, 0, 2)
|
set_node_attribute(door_lock, 1, 257, 0, 2)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == STATE_UNLOCKED
|
assert state.state == STATE_UNLOCKED
|
||||||
|
|
||||||
set_node_attribute(door_lock, 1, 257, 0, 0)
|
set_node_attribute(door_lock, 1, 257, 0, 0)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == STATE_LOCKING
|
assert state.state == STATE_LOCKING
|
||||||
|
|
||||||
set_node_attribute(door_lock, 1, 257, 0, None)
|
set_node_attribute(door_lock, 1, 257, 0, None)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ async def test_lock_requires_pin(
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"lock",
|
"lock",
|
||||||
"lock",
|
"lock",
|
||||||
{"entity_id": "lock.mock_door_lock", ATTR_CODE: "1234"},
|
{"entity_id": "lock.mock_door_lock_lock", ATTR_CODE: "1234"},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ async def test_lock_requires_pin(
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"lock",
|
"lock",
|
||||||
"lock",
|
"lock",
|
||||||
{"entity_id": "lock.mock_door_lock", ATTR_CODE: code},
|
{"entity_id": "lock.mock_door_lock_lock", ATTR_CODE: code},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
assert matter_client.send_device_command.call_count == 1
|
assert matter_client.send_device_command.call_count == 1
|
||||||
|
@ -145,13 +145,13 @@ async def test_lock_requires_pin(
|
||||||
# Lock door using default code
|
# Lock door using default code
|
||||||
default_code = "7654321"
|
default_code = "7654321"
|
||||||
entity_registry.async_update_entity_options(
|
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 trigger_subscription_callback(hass, matter_client)
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"lock",
|
"lock",
|
||||||
"lock",
|
"lock",
|
||||||
{"entity_id": "lock.mock_door_lock"},
|
{"entity_id": "lock.mock_door_lock_lock"},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
assert matter_client.send_device_command.call_count == 2
|
assert matter_client.send_device_command.call_count == 2
|
||||||
|
@ -171,7 +171,7 @@ async def test_lock_with_unbolt(
|
||||||
door_lock_with_unbolt: MatterNode,
|
door_lock_with_unbolt: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test door lock."""
|
"""Test door lock."""
|
||||||
state = hass.states.get("lock.mock_door_lock")
|
state = hass.states.get("lock.mock_door_lock_lock")
|
||||||
assert state
|
assert state
|
||||||
assert state.state == STATE_LOCKED
|
assert state.state == STATE_LOCKED
|
||||||
assert state.attributes["supported_features"] & LockEntityFeature.OPEN
|
assert state.attributes["supported_features"] & LockEntityFeature.OPEN
|
||||||
|
@ -180,7 +180,7 @@ async def test_lock_with_unbolt(
|
||||||
"lock",
|
"lock",
|
||||||
"unlock",
|
"unlock",
|
||||||
{
|
{
|
||||||
"entity_id": "lock.mock_door_lock",
|
"entity_id": "lock.mock_door_lock_lock",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -198,7 +198,7 @@ async def test_lock_with_unbolt(
|
||||||
"lock",
|
"lock",
|
||||||
"open",
|
"open",
|
||||||
{
|
{
|
||||||
"entity_id": "lock.mock_door_lock",
|
"entity_id": "lock.mock_door_lock_lock",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -213,6 +213,6 @@ async def test_lock_with_unbolt(
|
||||||
set_node_attribute(door_lock_with_unbolt, 1, 257, 3, 0)
|
set_node_attribute(door_lock_with_unbolt, 1, 257, 3, 0)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == STATE_OPEN
|
assert state.state == STATE_OPEN
|
||||||
|
|
|
@ -40,11 +40,10 @@ async def test_generic_switch_node(
|
||||||
generic_switch_node: MatterNode,
|
generic_switch_node: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test event entity for a GenericSwitch node."""
|
"""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
|
||||||
assert state.state == "unknown"
|
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 Button"
|
||||||
assert state.name == "Mock Generic Switch"
|
|
||||||
# check event_types from featuremap 30
|
# check event_types from featuremap 30
|
||||||
assert state.attributes[ATTR_EVENT_TYPES] == [
|
assert state.attributes[ATTR_EVENT_TYPES] == [
|
||||||
"initial_press",
|
"initial_press",
|
||||||
|
@ -71,7 +70,7 @@ async def test_generic_switch_node(
|
||||||
data=None,
|
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"
|
assert state.attributes[ATTR_EVENT_TYPE] == "initial_press"
|
||||||
# trigger firing a multi press event
|
# trigger firing a multi press event
|
||||||
await trigger_subscription_callback(
|
await trigger_subscription_callback(
|
||||||
|
@ -90,7 +89,7 @@ async def test_generic_switch_node(
|
||||||
data={"NewPosition": 3},
|
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[ATTR_EVENT_TYPE] == "multi_press_ongoing"
|
||||||
assert state.attributes["NewPosition"] == 3
|
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")
|
state_button_1 = hass.states.get("event.mock_generic_switch_button_1")
|
||||||
assert state_button_1
|
assert state_button_1
|
||||||
assert state_button_1.state == "unknown"
|
assert state_button_1.state == "unknown"
|
||||||
# name should be 'DeviceName Button 1' due to the label set to just '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"
|
assert state_button_1.name == "Mock Generic Switch Button (1)"
|
||||||
# check event_types from featuremap 14
|
# check event_types from featuremap 14
|
||||||
assert state_button_1.attributes[ATTR_EVENT_TYPES] == [
|
assert state_button_1.attributes[ATTR_EVENT_TYPES] == [
|
||||||
"initial_press",
|
"initial_press",
|
||||||
|
|
|
@ -45,7 +45,7 @@ async def test_fan_base(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test Fan platform."""
|
"""Test Fan platform."""
|
||||||
entity_id = "fan.air_purifier"
|
entity_id = "fan.air_purifier_fan"
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.attributes["preset_modes"] == [
|
assert state.attributes["preset_modes"] == [
|
||||||
|
@ -100,7 +100,7 @@ async def test_fan_turn_on_with_percentage(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test turning on the fan with a specific percentage."""
|
"""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(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -121,7 +121,7 @@ async def test_fan_turn_on_with_preset_mode(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test turning on the fan with a specific preset mode."""
|
"""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(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
|
@ -193,7 +193,7 @@ async def test_fan_turn_off(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test turning off the fan."""
|
"""Test turning off the fan."""
|
||||||
entity_id = "fan.air_purifier"
|
entity_id = "fan.air_purifier_fan"
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
|
@ -235,7 +235,7 @@ async def test_fan_oscillate(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test oscillating the fan."""
|
"""Test oscillating the fan."""
|
||||||
entity_id = "fan.air_purifier"
|
entity_id = "fan.air_purifier_fan"
|
||||||
for oscillating, value in ((True, 1), (False, 0)):
|
for oscillating, value in ((True, 1), (False, 0)):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
|
@ -258,7 +258,7 @@ async def test_fan_set_direction(
|
||||||
air_purifier: MatterNode,
|
air_purifier: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test oscillating the fan."""
|
"""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)):
|
for direction, value in ((DIRECTION_FORWARD, 0), (DIRECTION_REVERSE, 1)):
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
FAN_DOMAIN,
|
FAN_DOMAIN,
|
||||||
|
|
|
@ -69,7 +69,7 @@ async def test_entry_setup_unload(
|
||||||
|
|
||||||
assert matter_client.connect.call_count == 1
|
assert matter_client.connect.call_count == 1
|
||||||
assert entry.state is ConfigEntryState.LOADED
|
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
|
||||||
assert entity_state.state != STATE_UNAVAILABLE
|
assert entity_state.state != STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ async def test_entry_setup_unload(
|
||||||
|
|
||||||
assert matter_client.disconnect.call_count == 1
|
assert matter_client.disconnect.call_count == 1
|
||||||
assert entry.state is ConfigEntryState.NOT_LOADED
|
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
|
||||||
assert entity_state.state == STATE_UNAVAILABLE
|
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_entry = dr.async_entries_for_config_entry(
|
||||||
device_registry, config_entry.entry_id
|
device_registry, config_entry.entry_id
|
||||||
)[0]
|
)[0]
|
||||||
entity_id = "light.m5stamp_lighting_app"
|
entity_id = "light.m5stamp_lighting_app_light"
|
||||||
|
|
||||||
assert device_entry
|
assert device_entry
|
||||||
assert entity_registry.async_get(entity_id)
|
assert entity_registry.async_get(entity_id)
|
||||||
|
|
|
@ -22,17 +22,17 @@ from .common import (
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"extended-color-light",
|
"extended-color-light",
|
||||||
"light.mock_extended_color_light",
|
"light.mock_extended_color_light_light",
|
||||||
["color_temp", "hs", "xy"],
|
["color_temp", "hs", "xy"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"color-temperature-light",
|
"color-temperature-light",
|
||||||
"light.mock_color_temperature_light",
|
"light.mock_color_temperature_light_light",
|
||||||
["color_temp"],
|
["color_temp"],
|
||||||
),
|
),
|
||||||
("dimmable-light", "light.mock_dimmable_light", ["brightness"]),
|
("dimmable-light", "light.mock_dimmable_light_light", ["brightness"]),
|
||||||
("onoff-light", "light.mock_onoff_light", ["onoff"]),
|
("onoff-light", "light.mock_onoff_light_light", ["onoff"]),
|
||||||
("onoff-light-with-levelcontrol-present", "light.d215s", ["onoff"]),
|
("onoff-light-with-levelcontrol-present", "light.d215s_light", ["onoff"]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_light_turn_on_off(
|
async def test_light_turn_on_off(
|
||||||
|
@ -113,10 +113,10 @@ async def test_light_turn_on_off(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("fixture", "entity_id"),
|
||||||
[
|
[
|
||||||
("extended-color-light", "light.mock_extended_color_light"),
|
("extended-color-light", "light.mock_extended_color_light_light"),
|
||||||
("color-temperature-light", "light.mock_color_temperature_light"),
|
("color-temperature-light", "light.mock_color_temperature_light_light"),
|
||||||
("dimmable-light", "light.mock_dimmable_light"),
|
("dimmable-light", "light.mock_dimmable_light_light"),
|
||||||
("dimmable-plugin-unit", "light.dimmable_plugin_unit"),
|
("dimmable-plugin-unit", "light.dimmable_plugin_unit_light"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_dimmable_light(
|
async def test_dimmable_light(
|
||||||
|
@ -189,8 +189,8 @@ async def test_dimmable_light(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("fixture", "entity_id"),
|
||||||
[
|
[
|
||||||
("extended-color-light", "light.mock_extended_color_light"),
|
("extended-color-light", "light.mock_extended_color_light_light"),
|
||||||
("color-temperature-light", "light.mock_color_temperature_light"),
|
("color-temperature-light", "light.mock_color_temperature_light_light"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_color_temperature_light(
|
async def test_color_temperature_light(
|
||||||
|
@ -287,7 +287,7 @@ async def test_color_temperature_light(
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("fixture", "entity_id"),
|
("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(
|
async def test_extended_color_light(
|
||||||
|
|
|
@ -41,7 +41,7 @@ async def test_turn_on(
|
||||||
powerplug_node: MatterNode,
|
powerplug_node: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test turning on a switch."""
|
"""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
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ async def test_turn_on(
|
||||||
"switch",
|
"switch",
|
||||||
"turn_on",
|
"turn_on",
|
||||||
{
|
{
|
||||||
"entity_id": "switch.mock_onoffpluginunit_powerplug_switch",
|
"entity_id": "switch.mock_onoffpluginunit_switch",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -64,7 +64,7 @@ async def test_turn_on(
|
||||||
set_node_attribute(powerplug_node, 1, 6, 0, True)
|
set_node_attribute(powerplug_node, 1, 6, 0, True)
|
||||||
await trigger_subscription_callback(hass, matter_client)
|
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
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ async def test_turn_off(
|
||||||
powerplug_node: MatterNode,
|
powerplug_node: MatterNode,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test turning off a switch."""
|
"""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
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ async def test_turn_off(
|
||||||
"switch",
|
"switch",
|
||||||
"turn_off",
|
"turn_off",
|
||||||
{
|
{
|
||||||
"entity_id": "switch.mock_onoffpluginunit_powerplug_switch",
|
"entity_id": "switch.mock_onoffpluginunit_switch",
|
||||||
},
|
},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
@ -109,7 +109,23 @@ async def test_switch_unit(
|
||||||
# A switch entity should be discovered as fallback for ANY Matter device (endpoint)
|
# 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
|
# that has the OnOff cluster and does not fall into an explicit discovery schema
|
||||||
# by another platform (e.g. light, lock etc.).
|
# 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
|
||||||
assert state.state == "off"
|
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"
|
||||||
|
|
Loading…
Reference in New Issue