From c92107b8d4608e32e85298e264f006c9abb3180b Mon Sep 17 00:00:00 2001 From: jvmahon Date: Fri, 10 Oct 2025 15:04:01 +0200 Subject: [PATCH] Inherit `MatterEntityDescription` in Matter entities (#154083) --- homeassistant/components/matter/climate.py | 10 ++++++++-- homeassistant/components/matter/cover.py | 18 ++++++++++++------ homeassistant/components/matter/event.py | 10 ++++++++-- homeassistant/components/matter/fan.py | 10 ++++++++-- homeassistant/components/matter/light.py | 18 ++++++++++++------ homeassistant/components/matter/lock.py | 10 ++++++++-- homeassistant/components/matter/models.py | 7 ++++--- homeassistant/components/matter/switch.py | 11 ++++++++--- homeassistant/components/matter/update.py | 9 +++++++-- homeassistant/components/matter/vacuum.py | 14 +++++++++++--- homeassistant/components/matter/valve.py | 13 ++++++++++--- .../components/matter/water_heater.py | 12 ++++++++++-- 12 files changed, 106 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/matter/climate.py b/homeassistant/components/matter/climate.py index 4b28fe7625b..ec07a564621 100644 --- a/homeassistant/components/matter/climate.py +++ b/homeassistant/components/matter/climate.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from enum import IntEnum from typing import Any @@ -26,7 +27,7 @@ from homeassistant.const import ATTR_TEMPERATURE, Platform, UnitOfTemperature from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -182,6 +183,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.CLIMATE, async_add_entities) +@dataclass(frozen=True) +class MatterClimateEntityDescription(ClimateEntityDescription, MatterEntityDescription): + """Describe Matter Climate entities.""" + + class MatterClimate(MatterEntity, ClimateEntity): """Representation of a Matter climate entity.""" @@ -423,7 +429,7 @@ class MatterClimate(MatterEntity, ClimateEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.CLIMATE, - entity_description=ClimateEntityDescription( + entity_description=MatterClimateEntityDescription( key="MatterThermostat", name=None, ), diff --git a/homeassistant/components/matter/cover.py b/homeassistant/components/matter/cover.py index 7bef7ea1853..ac182c798d4 100644 --- a/homeassistant/components/matter/cover.py +++ b/homeassistant/components/matter/cover.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from enum import IntEnum from math import floor from typing import Any @@ -22,7 +23,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .const import LOGGER -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -61,10 +62,15 @@ async def async_setup_entry( matter.register_platform_handler(Platform.COVER, async_add_entities) +@dataclass(frozen=True) +class MatterCoverEntityDescription(CoverEntityDescription, MatterEntityDescription): + """Describe Matter Cover entities.""" + + class MatterCover(MatterEntity, CoverEntity): """Representation of a Matter Cover.""" - entity_description: CoverEntityDescription + entity_description: MatterCoverEntityDescription @property def is_closed(self) -> bool | None: @@ -198,7 +204,7 @@ class MatterCover(MatterEntity, CoverEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.COVER, - entity_description=CoverEntityDescription( + entity_description=MatterCoverEntityDescription( key="MatterCover", name=None, ), @@ -214,7 +220,7 @@ DISCOVERY_SCHEMAS = [ ), MatterDiscoverySchema( platform=Platform.COVER, - entity_description=CoverEntityDescription( + entity_description=MatterCoverEntityDescription( key="MatterCoverPositionAwareLift", name=None ), entity_class=MatterCover, @@ -229,7 +235,7 @@ DISCOVERY_SCHEMAS = [ ), MatterDiscoverySchema( platform=Platform.COVER, - entity_description=CoverEntityDescription( + entity_description=MatterCoverEntityDescription( key="MatterCoverPositionAwareTilt", name=None ), entity_class=MatterCover, @@ -244,7 +250,7 @@ DISCOVERY_SCHEMAS = [ ), MatterDiscoverySchema( platform=Platform.COVER, - entity_description=CoverEntityDescription( + entity_description=MatterCoverEntityDescription( key="MatterCoverPositionAwareLiftAndTilt", name=None ), entity_class=MatterCover, diff --git a/homeassistant/components/matter/event.py b/homeassistant/components/matter/event.py index fa7d96ed1ae..6f4205772a4 100644 --- a/homeassistant/components/matter/event.py +++ b/homeassistant/components/matter/event.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Any from chip.clusters import Objects as clusters @@ -18,7 +19,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -46,6 +47,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.EVENT, async_add_entities) +@dataclass(frozen=True) +class MatterEventEntityDescription(EventEntityDescription, MatterEntityDescription): + """Describe Matter Event entities.""" + + class MatterEventEntity(MatterEntity, EventEntity): """Representation of a Matter Event entity.""" @@ -132,7 +138,7 @@ class MatterEventEntity(MatterEntity, EventEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.EVENT, - entity_description=EventEntityDescription( + entity_description=MatterEventEntityDescription( key="GenericSwitch", device_class=EventDeviceClass.BUTTON, translation_key="button", diff --git a/homeassistant/components/matter/fan.py b/homeassistant/components/matter/fan.py index 2c9e190d58a..a0e85a2df2f 100644 --- a/homeassistant/components/matter/fan.py +++ b/homeassistant/components/matter/fan.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import TYPE_CHECKING, Any from chip.clusters import Objects as clusters @@ -18,7 +19,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -52,6 +53,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.FAN, async_add_entities) +@dataclass(frozen=True) +class MatterFanEntityDescription(FanEntityDescription, MatterEntityDescription): + """Describe Matter Fan entities.""" + + class MatterFan(MatterEntity, FanEntity): """Representation of a Matter fan.""" @@ -308,7 +314,7 @@ class MatterFan(MatterEntity, FanEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.FAN, - entity_description=FanEntityDescription( + entity_description=MatterFanEntityDescription( key="MatterFan", name=None, ), diff --git a/homeassistant/components/matter/light.py b/homeassistant/components/matter/light.py index e01cc54f46d..0a870167d46 100644 --- a/homeassistant/components/matter/light.py +++ b/homeassistant/components/matter/light.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Any from chip.clusters import Objects as clusters @@ -29,7 +30,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.util import color as color_util from .const import LOGGER -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema from .util import ( @@ -85,10 +86,15 @@ async def async_setup_entry( matter.register_platform_handler(Platform.LIGHT, async_add_entities) +@dataclass(frozen=True) +class MatterLightEntityDescription(LightEntityDescription, MatterEntityDescription): + """Describe Matter Light entities.""" + + class MatterLight(MatterEntity, LightEntity): """Representation of a Matter light.""" - entity_description: LightEntityDescription + entity_description: MatterLightEntityDescription _supports_brightness = False _supports_color = False _supports_color_temperature = False @@ -458,7 +464,7 @@ class MatterLight(MatterEntity, LightEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LIGHT, - entity_description=LightEntityDescription( + entity_description=MatterLightEntityDescription( key="MatterLight", name=None, ), @@ -487,7 +493,7 @@ DISCOVERY_SCHEMAS = [ # Additional schema to match (HS Color) lights with incorrect/missing device type MatterDiscoverySchema( platform=Platform.LIGHT, - entity_description=LightEntityDescription( + entity_description=MatterLightEntityDescription( key="MatterHSColorLightFallback", name=None, ), @@ -508,7 +514,7 @@ DISCOVERY_SCHEMAS = [ # Additional schema to match (XY Color) lights with incorrect/missing device type MatterDiscoverySchema( platform=Platform.LIGHT, - entity_description=LightEntityDescription( + entity_description=MatterLightEntityDescription( key="MatterXYColorLightFallback", name=None, ), @@ -529,7 +535,7 @@ DISCOVERY_SCHEMAS = [ # Additional schema to match (color temperature) lights with incorrect/missing device type MatterDiscoverySchema( platform=Platform.LIGHT, - entity_description=LightEntityDescription( + entity_description=MatterLightEntityDescription( key="MatterColorTemperatureLightFallback", name=None, ), diff --git a/homeassistant/components/matter/lock.py b/homeassistant/components/matter/lock.py index c264ce65896..230714accbd 100644 --- a/homeassistant/components/matter/lock.py +++ b/homeassistant/components/matter/lock.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +from dataclasses import dataclass from typing import Any from chip.clusters import Objects as clusters @@ -19,7 +20,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .const import LOGGER -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -52,6 +53,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.LOCK, async_add_entities) +@dataclass(frozen=True) +class MatterLockEntityDescription(LockEntityDescription, MatterEntityDescription): + """Describe Matter Lock entities.""" + + class MatterLock(MatterEntity, LockEntity): """Representation of a Matter lock.""" @@ -254,7 +260,7 @@ class MatterLock(MatterEntity, LockEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.LOCK, - entity_description=LockEntityDescription( + entity_description=MatterLockEntityDescription( key="MatterLock", name=None, ), diff --git a/homeassistant/components/matter/models.py b/homeassistant/components/matter/models.py index acdcc53f660..50d0a5745da 100644 --- a/homeassistant/components/matter/models.py +++ b/homeassistant/components/matter/models.py @@ -11,7 +11,8 @@ from matter_server.client.models.device_types import DeviceType from matter_server.client.models.node import MatterEndpoint from homeassistant.const import Platform -from homeassistant.helpers.entity import EntityDescription + +from .entity import MatterEntityDescription type SensorValueTypes = type[ clusters.uint | int | clusters.Nullable | clusters.float32 | float @@ -54,7 +55,7 @@ class MatterEntityInfo: attributes_to_watch: list[type[ClusterAttributeDescriptor]] # the entity description to use - entity_description: EntityDescription + entity_description: MatterEntityDescription # entity class to use to instantiate the entity entity_class: type @@ -80,7 +81,7 @@ class MatterDiscoverySchema: platform: Platform # platform-specific entity description - entity_description: EntityDescription + entity_description: MatterEntityDescription # entity class to use to instantiate the entity entity_class: type diff --git a/homeassistant/components/matter/switch.py b/homeassistant/components/matter/switch.py index 682285e9c97..d8ae8d66f2b 100644 --- a/homeassistant/components/matter/switch.py +++ b/homeassistant/components/matter/switch.py @@ -42,6 +42,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.SWITCH, async_add_entities) +@dataclass(frozen=True) +class MatterSwitchEntityDescription(SwitchEntityDescription, MatterEntityDescription): + """Describe Matter Switch entities.""" + + class MatterSwitch(MatterEntity, SwitchEntity): """Representation of a Matter switch.""" @@ -168,7 +173,7 @@ class MatterNumericSwitch(MatterSwitch): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.SWITCH, - entity_description=SwitchEntityDescription( + entity_description=MatterSwitchEntityDescription( key="MatterPlug", device_class=SwitchDeviceClass.OUTLET, name=None, @@ -179,7 +184,7 @@ DISCOVERY_SCHEMAS = [ ), MatterDiscoverySchema( platform=Platform.SWITCH, - entity_description=SwitchEntityDescription( + entity_description=MatterSwitchEntityDescription( key="MatterPowerToggle", device_class=SwitchDeviceClass.SWITCH, translation_key="power", @@ -207,7 +212,7 @@ DISCOVERY_SCHEMAS = [ ), MatterDiscoverySchema( platform=Platform.SWITCH, - entity_description=SwitchEntityDescription( + entity_description=MatterSwitchEntityDescription( key="MatterSwitch", device_class=SwitchDeviceClass.OUTLET, name=None, diff --git a/homeassistant/components/matter/update.py b/homeassistant/components/matter/update.py index cea4fe0c810..17506fe4d4c 100644 --- a/homeassistant/components/matter/update.py +++ b/homeassistant/components/matter/update.py @@ -25,7 +25,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.event import async_call_later from homeassistant.helpers.restore_state import ExtraStoredData -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -67,6 +67,11 @@ async def async_setup_entry( matter.register_platform_handler(Platform.UPDATE, async_add_entities) +@dataclass(frozen=True) +class MatterUpdateEntityDescription(UpdateEntityDescription, MatterEntityDescription): + """Describe Matter Update entities.""" + + class MatterUpdate(MatterEntity, UpdateEntity): """Representation of a Matter node capable of updating.""" @@ -250,7 +255,7 @@ class MatterUpdate(MatterEntity, UpdateEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.UPDATE, - entity_description=UpdateEntityDescription( + entity_description=MatterUpdateEntityDescription( key="MatterUpdate", device_class=UpdateDeviceClass.FIRMWARE ), entity_class=MatterUpdate, diff --git a/homeassistant/components/matter/vacuum.py b/homeassistant/components/matter/vacuum.py index cf9f26adecb..2e4ee41b7ec 100644 --- a/homeassistant/components/matter/vacuum.py +++ b/homeassistant/components/matter/vacuum.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from enum import IntEnum from typing import TYPE_CHECKING, Any @@ -20,7 +21,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -58,6 +59,13 @@ async def async_setup_entry( matter.register_platform_handler(Platform.VACUUM, async_add_entities) +@dataclass(frozen=True) +class MatterStateVacuumEntityDescription( + StateVacuumEntityDescription, MatterEntityDescription +): + """Describe Matter Vacuum entities.""" + + class MatterVacuum(MatterEntity, StateVacuumEntity): """Representation of a Matter Vacuum cleaner entity.""" @@ -65,7 +73,7 @@ class MatterVacuum(MatterEntity, StateVacuumEntity): _supported_run_modes: ( dict[int, clusters.RvcRunMode.Structs.ModeOptionStruct] | None ) = None - entity_description: StateVacuumEntityDescription + entity_description: MatterStateVacuumEntityDescription _platform_translation_key = "vacuum" def _get_run_mode_by_tag( @@ -212,7 +220,7 @@ class MatterVacuum(MatterEntity, StateVacuumEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.VACUUM, - entity_description=StateVacuumEntityDescription( + entity_description=MatterStateVacuumEntityDescription( key="MatterVacuumCleaner", name=None ), entity_class=MatterVacuum, diff --git a/homeassistant/components/matter/valve.py b/homeassistant/components/matter/valve.py index 715cdc2a09e..be7a382307b 100644 --- a/homeassistant/components/matter/valve.py +++ b/homeassistant/components/matter/valve.py @@ -2,6 +2,8 @@ from __future__ import annotations +from dataclasses import dataclass + from chip.clusters import Objects as clusters from matter_server.client.models import device_types @@ -16,7 +18,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -34,11 +36,16 @@ async def async_setup_entry( matter.register_platform_handler(Platform.VALVE, async_add_entities) +@dataclass(frozen=True) +class MatterValveEntityDescription(ValveEntityDescription, MatterEntityDescription): + """Describe Matter Valve entities.""" + + class MatterValve(MatterEntity, ValveEntity): """Representation of a Matter Valve.""" _feature_map: int | None = None - entity_description: ValveEntityDescription + entity_description: MatterValveEntityDescription _platform_translation_key = "valve" async def async_open_valve(self) -> None: @@ -128,7 +135,7 @@ class MatterValve(MatterEntity, ValveEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.VALVE, - entity_description=ValveEntityDescription( + entity_description=MatterValveEntityDescription( key="MatterValve", device_class=ValveDeviceClass.WATER, name=None, diff --git a/homeassistant/components/matter/water_heater.py b/homeassistant/components/matter/water_heater.py index e453a8be067..f761af9427d 100644 --- a/homeassistant/components/matter/water_heater.py +++ b/homeassistant/components/matter/water_heater.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import dataclass from typing import Any, cast from chip.clusters import Objects as clusters @@ -26,7 +27,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from .entity import MatterEntity +from .entity import MatterEntity, MatterEntityDescription from .helpers import get_matter from .models import MatterDiscoverySchema @@ -50,6 +51,13 @@ async def async_setup_entry( matter.register_platform_handler(Platform.WATER_HEATER, async_add_entities) +@dataclass(frozen=True) +class MatterWaterHeaterEntityDescription( + WaterHeaterEntityDescription, MatterEntityDescription +): + """Describe Matter Water Heater entities.""" + + class MatterWaterHeater(MatterEntity, WaterHeaterEntity): """Representation of a Matter WaterHeater entity.""" @@ -171,7 +179,7 @@ class MatterWaterHeater(MatterEntity, WaterHeaterEntity): DISCOVERY_SCHEMAS = [ MatterDiscoverySchema( platform=Platform.WATER_HEATER, - entity_description=WaterHeaterEntityDescription( + entity_description=MatterWaterHeaterEntityDescription( key="MatterWaterHeater", name=None, ),