Fix Matter entity names (#120038)

pull/118047/head
Marcel van der Veldt 2024-06-21 16:42:22 +02:00 committed by GitHub
parent 180c244a78
commit 4110f4f393
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 1911 additions and 129 deletions

View File

@ -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,),

View File

@ -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=(

View File

@ -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."""

View File

@ -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=(

View File

@ -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=(

View File

@ -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,),

View File

@ -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

View File

@ -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": {

View File

@ -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

View File

@ -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",

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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,

View File

@ -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)

View File

@ -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(

View File

@ -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"