From 5184bd10df0bedcf4a1de335453c5770a441240e Mon Sep 17 00:00:00 2001 From: zigpy-review-bot <286747149+zigpy-review-bot@users.noreply.github.com> Date: Thu, 25 Jun 2026 21:06:07 +0200 Subject: [PATCH] Derive entity registry key from `_cluster_match` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `@register_entity(cluster_id)` took an explicit cluster ID that was used only as a key into `ENTITY_REGISTRY` to speed up discovery lookups — the actual matching is done entirely by the class's `_cluster_match`. The ID was therefore redundant: in every one of the 304 registrations it was one of the match's mandatory clusters (`server_clusters`/`client_clusters`), and nothing enforced that it was. Make `register_entity` a bare decorator that derives the key from the match. Since every mandatory cluster must be present for a match to succeed, indexing under any single one is a sufficient discovery key, so each class stays in exactly one bucket (no double-evaluation during discovery). The resulting `ENTITY_REGISTRY` is byte-for-byte identical to before — same buckets, same ordering — so discovery behavior is unchanged. Also drop the now-unused `OnOff as OnOffCluster` alias in cover. --- zha/application/platforms/__init__.py | 37 ++++- .../platforms/alarm_control_panel/__init__.py | 2 +- .../platforms/binary_sensor/__init__.py | 44 ++--- zha/application/platforms/button/__init__.py | 10 +- zha/application/platforms/climate/__init__.py | 18 +- zha/application/platforms/cover/__init__.py | 8 +- zha/application/platforms/device_tracker.py | 2 +- zha/application/platforms/fan/__init__.py | 6 +- zha/application/platforms/light/__init__.py | 8 +- zha/application/platforms/lock/__init__.py | 2 +- zha/application/platforms/number/__init__.py | 110 ++++++------ zha/application/platforms/select.py | 76 ++++----- zha/application/platforms/sensor/__init__.py | 156 +++++++++--------- zha/application/platforms/siren.py | 4 +- zha/application/platforms/switch.py | 80 ++++----- zha/application/platforms/update.py | 4 +- zha/application/platforms/virtual.py | 80 ++++----- 17 files changed, 333 insertions(+), 314 deletions(-) diff --git a/zha/application/platforms/__init__.py b/zha/application/platforms/__init__.py index 675918e88..a8cb08269 100644 --- a/zha/application/platforms/__init__.py +++ b/zha/application/platforms/__init__.py @@ -142,16 +142,35 @@ def __post_init__(self) -> None: ) -def register_entity[T: type[PlatformEntity]]( - cluster_id: ClusterId | int, -) -> Callable[[T], T]: - """Register an entity class for discovery.""" - - def inner(cls: T) -> T: - ENTITY_REGISTRY[cluster_id].append(cls) - return cls +def register_entity[T: type[PlatformEntity]](cls: T) -> T: + """Register an entity class for discovery. + + The registry is keyed by cluster ID purely to speed up discovery lookups + (see `discover_entities_for_endpoint`): for each cluster on an endpoint we + only evaluate the entities filed under that cluster. The actual matching is + done entirely by the class's `_cluster_match`. + + The index key is therefore not independent information — it is derived from + the match. Every mandatory cluster (`server_clusters | client_clusters`) + must be present for a match to succeed, so any single one of them is a + sufficient discovery key: if the entity can match at all, that cluster is on + the endpoint and the lookup finds it. We index under exactly one mandatory + cluster (preferring a server cluster) to keep each class in a single bucket, + so discovery evaluates it at most once per endpoint. + """ + match = cls._cluster_match + if match is None: + raise TypeError(f"{cls.__name__} has no `_cluster_match` to register") + + mandatory = match.server_clusters or match.client_clusters + if not mandatory: + raise ValueError( + f"{cls.__name__} declares no mandatory clusters; it cannot be " + "discovered and must not use @register_entity" + ) - return inner + ENTITY_REGISTRY[min(mandatory)].append(cls) + return cls def register_group_entity(cls: type[GroupEntity]) -> type[GroupEntity]: diff --git a/zha/application/platforms/alarm_control_panel/__init__.py b/zha/application/platforms/alarm_control_panel/__init__.py index 2c6b82927..ecaab4bae 100644 --- a/zha/application/platforms/alarm_control_panel/__init__.py +++ b/zha/application/platforms/alarm_control_panel/__init__.py @@ -122,7 +122,7 @@ async def async_alarm_trigger(self, code: str | None = None) -> None: """Send alarm trigger command.""" -@register_entity(AceCluster.cluster_id) +@register_entity class AlarmControlPanel(BaseAlarmControlPanel): """Entity for ZHA alarm control devices.""" diff --git a/zha/application/platforms/binary_sensor/__init__.py b/zha/application/platforms/binary_sensor/__init__.py index 688cb706c..8033d2857 100644 --- a/zha/application/platforms/binary_sensor/__init__.py +++ b/zha/application/platforms/binary_sensor/__init__.py @@ -186,7 +186,7 @@ def parse(value: bool | int) -> bool: return bool(value) -@register_entity(SMARTTHINGS_ACCELERATION_CLUSTER) +@register_entity class Accelerometer(BinarySensor): """ZHA BinarySensor.""" @@ -232,7 +232,7 @@ class Accelerometer(BinarySensor): } -@register_entity(OccupancySensing.cluster_id) +@register_entity class Occupancy(BinarySensor): """ZHA BinarySensor.""" @@ -266,7 +266,7 @@ class Occupancy(BinarySensor): } -@register_entity(OnOff.cluster_id) +@register_entity class Opening(BinarySensor): """ZHA OnOff BinarySensor.""" @@ -300,7 +300,7 @@ class Opening(BinarySensor): ) -@register_entity(BinaryInputCluster.cluster_id) +@register_entity class BinaryInputWithDescription(BinarySensor): """ZHA BinarySensor.""" @@ -342,7 +342,7 @@ def _is_supported(self) -> bool: return super()._is_supported() -@register_entity(BinaryInputCluster.cluster_id) +@register_entity class BinaryInput(BinarySensor): """ZHA BinarySensor.""" @@ -382,7 +382,7 @@ def _is_supported(self) -> bool: return super()._is_supported() -@register_entity(OnOff.cluster_id) +@register_entity class IkeaMotion(BinarySensor): """ZHA OnOff BinarySensor with motion device class for IKEA devices.""" @@ -398,7 +398,7 @@ class IkeaMotion(BinarySensor): ) -@register_entity(OnOff.cluster_id) +@register_entity class PhilipsMotion(BinarySensor): """ZHA OnOff BinarySensor with motion device class for Philips devices.""" @@ -414,7 +414,7 @@ class PhilipsMotion(BinarySensor): ) -@register_entity(IasZone.cluster_id) +@register_entity class IASZone(BinarySensor): """ZHA IAS BinarySensor.""" @@ -478,7 +478,7 @@ async def async_update(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(IasZone.cluster_id) +@register_entity class SinopeLeakStatus(BinarySensor): """Sinope water leak sensor.""" @@ -493,7 +493,7 @@ class SinopeLeakStatus(BinarySensor): ) -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class FrostLock(BinarySensor): """ZHA BinarySensor.""" @@ -509,7 +509,7 @@ class FrostLock(BinarySensor): ) -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class ReplaceFilter(BinarySensor): """ZHA BinarySensor.""" @@ -525,7 +525,7 @@ class ReplaceFilter(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederErrorDetected(BinarySensor): """ZHA aqara pet feeder error detected binary sensor.""" @@ -540,7 +540,7 @@ class AqaraPetFeederErrorDetected(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class XiaomiPlugConsumerConnected(BinarySensor): """ZHA Xiaomi plug consumer connected binary sensor.""" @@ -556,7 +556,7 @@ class XiaomiPlugConsumerConnected(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatWindowOpen(BinarySensor): """ZHA Aqara thermostat window open binary sensor.""" @@ -571,7 +571,7 @@ class AqaraThermostatWindowOpen(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatValveAlarm(BinarySensor): """ZHA Aqara thermostat valve alarm binary sensor.""" @@ -587,7 +587,7 @@ class AqaraThermostatValveAlarm(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatCalibrated(BinarySensor): """ZHA Aqara thermostat calibrated binary sensor.""" @@ -603,7 +603,7 @@ class AqaraThermostatCalibrated(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatExternalSensor(BinarySensor): """ZHA Aqara thermostat external sensor binary sensor.""" @@ -619,7 +619,7 @@ class AqaraThermostatExternalSensor(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraLinkageAlarmState(BinarySensor): """ZHA Aqara linkage alarm state binary sensor.""" @@ -635,7 +635,7 @@ class AqaraLinkageAlarmState(BinarySensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraE1CurtainMotorOpenedByHandBinarySensor(BinarySensor): """Opened by hand binary sensor.""" @@ -651,7 +651,7 @@ class AqaraE1CurtainMotorOpenedByHandBinarySensor(BinarySensor): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossMountingModeActive(BinarySensor): """Danfoss TRV proprietary attribute exposing whether in mounting mode.""" @@ -682,7 +682,7 @@ class DanfossMountingModeActive(BinarySensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossHeatRequired(BinarySensor): """Danfoss TRV proprietary attribute exposing whether heat is required.""" @@ -711,7 +711,7 @@ class DanfossHeatRequired(BinarySensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossPreheatStatus(BinarySensor): """Danfoss TRV proprietary attribute exposing whether in pre-heating mode.""" diff --git a/zha/application/platforms/button/__init__.py b/zha/application/platforms/button/__init__.py index ec664037c..7cc465670 100644 --- a/zha/application/platforms/button/__init__.py +++ b/zha/application/platforms/button/__init__.py @@ -123,7 +123,7 @@ async def async_press(self) -> None: await command(*arguments, **kwargs) -@register_entity(Identify.cluster_id) +@register_entity class IdentifyButton(Button): """Defines a ZHA identify button.""" @@ -184,7 +184,7 @@ async def async_press(self) -> None: ) -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class FrostLockResetButton(WriteAttributeButton): """Defines a ZHA frost lock reset button.""" @@ -202,7 +202,7 @@ class FrostLockResetButton(WriteAttributeButton): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class NoPresenceStatusResetButton(WriteAttributeButton): """Defines a ZHA no presence status reset button.""" @@ -220,7 +220,7 @@ class NoPresenceStatusResetButton(WriteAttributeButton): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederFeedButton(WriteAttributeButton): """Defines a feed button for the aqara c1 pet feeder.""" @@ -236,7 +236,7 @@ class AqaraPetFeederFeedButton(WriteAttributeButton): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraSelfTestButton(WriteAttributeButton): """Defines a ZHA self-test button for Aqara smoke sensors.""" diff --git a/zha/application/platforms/climate/__init__.py b/zha/application/platforms/climate/__init__.py index 6e5d9a27a..8078a1395 100644 --- a/zha/application/platforms/climate/__init__.py +++ b/zha/application/platforms/climate/__init__.py @@ -195,7 +195,7 @@ async def async_set_temperature( """Set new target temperature.""" -@register_entity(ThermostatCluster.cluster_id) +@register_entity class Thermostat(BaseThermostat): """Representation of a ZHA Thermostat device.""" @@ -919,7 +919,7 @@ async def async_preset_handler(self, preset: str, enable: bool = False) -> None: SINOPE_MANUFACTURER_CLUSTER = 0xFF01 -@register_entity(ThermostatCluster.cluster_id) +@register_entity class SinopeTechnologiesThermostat(Thermostat): """Sinope Technologies Thermostat.""" @@ -1034,7 +1034,7 @@ async def async_preset_handler_away(self, is_away: bool = False) -> None: ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class ZenWithinThermostat(Thermostat): """Zen Within Thermostat implementation.""" @@ -1046,7 +1046,7 @@ class ZenWithinThermostat(Thermostat): ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class ZehnderThermostat(Thermostat): """Zehnder thermostat to adapt AUTO mode behavior.""" @@ -1118,7 +1118,7 @@ def hvac_mode(self) -> HVACMode | None: return ZehnderThermostat.ZEHNDER_SYSTEM_MODE_2_HVAC.get(self._system_mode) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class CentralitePearl(Thermostat): """Centralite Pearl Thermostat implementation.""" @@ -1150,7 +1150,7 @@ class CentralitePearl(Thermostat): ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class MoesThermostat(Thermostat): """Moes Thermostat implementation.""" @@ -1237,7 +1237,7 @@ async def async_preset_handler(self, preset: str, enable: bool = False) -> None: ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class BecaThermostat(Thermostat): """Beca Thermostat implementation.""" @@ -1317,7 +1317,7 @@ async def async_preset_handler(self, preset: str, enable: bool = False) -> None: ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class StelproFanHeater(Thermostat): """Stelpro Fan Heater implementation.""" @@ -1348,7 +1348,7 @@ def hvac_modes(self) -> list[HVACMode]: ) -@register_entity(ThermostatCluster.cluster_id) +@register_entity class ZONNSMARTThermostat(Thermostat): """ZONNSMART Thermostat implementation. diff --git a/zha/application/platforms/cover/__init__.py b/zha/application/platforms/cover/__init__.py index 8f6385e2b..a05ff3efe 100644 --- a/zha/application/platforms/cover/__init__.py +++ b/zha/application/platforms/cover/__init__.py @@ -24,7 +24,7 @@ WindowCovering, WindowCoveringType, ) -from zigpy.zcl.clusters.general import LevelControl, OnOff, OnOff as OnOffCluster +from zigpy.zcl.clusters.general import LevelControl, OnOff from zigpy.zcl.foundation import Status from zha.application import Platform @@ -126,7 +126,7 @@ async def async_stop_cover(self) -> None: """Stop the cover.""" -@register_entity(WindowCovering.cluster_id) +@register_entity class Cover(BaseCover): """Representation of a ZHA cover.""" @@ -746,7 +746,7 @@ def _ha_position_to_zcl(position: int) -> int: return 100 - position -@register_entity(OnOffCluster.cluster_id) +@register_entity class Shade(BaseCover): """ZHA Shade.""" @@ -1008,7 +1008,7 @@ def _zcl_level_to_ha_position(level: int | None) -> int | None: return round(level * 100 / 255) -@register_entity(OnOff.cluster_id) +@register_entity class KeenVent(Shade): """Keen vent cover.""" diff --git a/zha/application/platforms/device_tracker.py b/zha/application/platforms/device_tracker.py index 0328195e0..3dbd0d3db 100644 --- a/zha/application/platforms/device_tracker.py +++ b/zha/application/platforms/device_tracker.py @@ -81,7 +81,7 @@ def source_type(self) -> SourceType: """Return the source type, eg gps or router, of the device.""" -@register_entity(PowerConfiguration.cluster_id) +@register_entity class DeviceScannerEntity(BaseDeviceTracker): """Represent a tracked device.""" diff --git a/zha/application/platforms/fan/__init__.py b/zha/application/platforms/fan/__init__.py index 5f60e4663..c24e29740 100644 --- a/zha/application/platforms/fan/__init__.py +++ b/zha/application/platforms/fan/__init__.py @@ -245,7 +245,7 @@ def percentage_to_speed(self, percentage: int) -> str: return percentage_to_ordered_list_item(LEGACY_SPEED_LIST, percentage) -@register_entity(hvac.Fan.cluster_id) +@register_entity class Fan(BaseFan, PlatformEntity): """Representation of a ZHA fan.""" @@ -394,7 +394,7 @@ def update(self, _: Any = None) -> None: self.maybe_emit_state_changed_event() -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class IkeaFan(BaseFan, PlatformEntity): """Representation of an Ikea fan.""" @@ -569,7 +569,7 @@ async def async_update(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(hvac.Fan.cluster_id) +@register_entity class KofFan(Fan): """Representation of a fan made by King Of Fans.""" diff --git a/zha/application/platforms/light/__init__.py b/zha/application/platforms/light/__init__.py index c6f1249f4..4fa7a1581 100644 --- a/zha/application/platforms/light/__init__.py +++ b/zha/application/platforms/light/__init__.py @@ -876,7 +876,7 @@ async def on_remove(self) -> None: await super().on_remove() -@register_entity(OnOff.cluster_id) +@register_entity class Light(BaseSharedLight, PlatformEntity): """Representation of a ZHA or ZLL light.""" @@ -1297,7 +1297,7 @@ async def async_update(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(OnOff.cluster_id) +@register_entity class HueLight(Light): """Representation of a HUE light which does not report attributes.""" @@ -1313,7 +1313,7 @@ class HueLight(Light): ) -@register_entity(OnOff.cluster_id) +@register_entity class ForceOnLight(Light): """Representation of a light which does not respect on/off for move_to_level_with_on_off commands.""" @@ -1337,7 +1337,7 @@ class ForceOnLight(Light): ) -@register_entity(OnOff.cluster_id) +@register_entity class MinTransitionLight(Light): """Representation of a light which does not react to any "move to" calls with 0 as a transition.""" diff --git a/zha/application/platforms/lock/__init__.py b/zha/application/platforms/lock/__init__.py index 563e51b99..92a7d15fc 100644 --- a/zha/application/platforms/lock/__init__.py +++ b/zha/application/platforms/lock/__init__.py @@ -61,7 +61,7 @@ async def async_unlock(self) -> None: """Unlock the lock.""" -@register_entity(DoorLockCluster.cluster_id) +@register_entity class DoorLock(BaseLock): """Representation of a ZHA lock.""" diff --git a/zha/application/platforms/number/__init__.py b/zha/application/platforms/number/__init__.py index 40f4f8e84..7ba5ee068 100644 --- a/zha/application/platforms/number/__init__.py +++ b/zha/application/platforms/number/__init__.py @@ -131,7 +131,7 @@ async def async_set_native_value(self, value: float) -> None: """Update the current value from HA.""" -@register_entity(AnalogOutput.cluster_id) +@register_entity class AnalogOutputNumber(BaseNumber): """Representation of a ZHA Number entity.""" @@ -377,7 +377,7 @@ def handle_attribute_updated( self.maybe_emit_state_changed_event() -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionDetectionInterval(NumberConfigurationEntity): """Representation of a ZHA motion detection interval configuration entity.""" @@ -394,7 +394,7 @@ class AqaraMotionDetectionInterval(NumberConfigurationEntity): ) -@register_entity(LevelControl.cluster_id) +@register_entity class OnOffTransitionTimeConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA on off transition time configuration entity.""" @@ -442,7 +442,7 @@ class OnOffTransitionTimeConfigurationEntity(NumberConfigurationEntity): } -@register_entity(LevelControl.cluster_id) +@register_entity class OnLevelConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA on level configuration entity.""" @@ -458,7 +458,7 @@ class OnLevelConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(LevelControl.cluster_id) +@register_entity class OnTransitionTimeConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA on transition time configuration entity.""" @@ -474,7 +474,7 @@ class OnTransitionTimeConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(LevelControl.cluster_id) +@register_entity class OffTransitionTimeConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA off transition time configuration entity.""" @@ -490,7 +490,7 @@ class OffTransitionTimeConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(LevelControl.cluster_id) +@register_entity class DefaultMoveRateConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA default move rate configuration entity.""" @@ -507,7 +507,7 @@ class DefaultMoveRateConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(LevelControl.cluster_id) +@register_entity class StartUpCurrentLevelConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA startup current level configuration entity.""" @@ -523,7 +523,7 @@ class StartUpCurrentLevelConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(Color.cluster_id) +@register_entity class StartUpColorTemperatureConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA startup color temperature configuration entity.""" @@ -602,7 +602,7 @@ def recompute_capabilities(self) -> None: self._attr_native_max_value = max_mireds -@register_entity(Ballast.cluster_id) +@register_entity class BallastMinLevel(NumberConfigurationEntity): """Ballast minimum level configuration entity.""" @@ -633,7 +633,7 @@ class BallastMinLevel(NumberConfigurationEntity): } -@register_entity(Ballast.cluster_id) +@register_entity class BallastMaxLevel(NumberConfigurationEntity): """Ballast maximum level configuration entity.""" @@ -650,7 +650,7 @@ class BallastMaxLevel(NumberConfigurationEntity): ) -@register_entity(OccupancySensing.cluster_id) +@register_entity class PIROccupiedToUnoccupiedDelayConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA PIR occupied to unoccupied delay configuration entity.""" @@ -688,7 +688,7 @@ class PIROccupiedToUnoccupiedDelayConfigurationEntity(NumberConfigurationEntity) } -@register_entity(OccupancySensing.cluster_id) +@register_entity class PIRUnoccupiedToOccupiedDelayConfigurationEntity(NumberConfigurationEntity): """Representation of a ZHA PIR unoccupied to occupied delay configuration entity.""" @@ -706,7 +706,7 @@ class PIRUnoccupiedToOccupiedDelayConfigurationEntity(NumberConfigurationEntity) ) -@register_entity(OccupancySensing.cluster_id) +@register_entity class SonoffPresenceSenorTimeout(NumberConfigurationEntity): """Configuration of Sonoff sensor presence detection timeout.""" @@ -726,7 +726,7 @@ class SonoffPresenceSenorTimeout(NumberConfigurationEntity): ) -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class TimerDurationMinutes(NumberConfigurationEntity): """Representation of a ZHA timer duration configuration entity.""" @@ -745,7 +745,7 @@ class TimerDurationMinutes(NumberConfigurationEntity): ) -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class FilterLifeTime(NumberConfigurationEntity): """Representation of a ZHA filter lifetime configuration entity.""" @@ -763,7 +763,7 @@ class FilterLifeTime(NumberConfigurationEntity): ) -@register_entity(Basic.cluster_id) +@register_entity class TiRouterTransmitPower(NumberConfigurationEntity): """Representation of a ZHA TI transmit power configuration entity.""" @@ -790,7 +790,7 @@ class TiRouterTransmitPower(NumberConfigurationEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRemoteDimmingUpSpeed(NumberConfigurationEntity): """Inovelli remote dimming up speed configuration entity.""" @@ -808,7 +808,7 @@ class InovelliRemoteDimmingUpSpeed(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliButtonDelay(NumberConfigurationEntity): """Inovelli button delay configuration entity.""" @@ -826,7 +826,7 @@ class InovelliButtonDelay(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalDimmingUpSpeed(NumberConfigurationEntity): """Inovelli local dimming up speed configuration entity.""" @@ -844,7 +844,7 @@ class InovelliLocalDimmingUpSpeed(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalRampRateOffToOn(NumberConfigurationEntity): """Inovelli off to on local ramp rate configuration entity.""" @@ -862,7 +862,7 @@ class InovelliLocalRampRateOffToOn(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRemoteDimmingSpeedOffToOn(NumberConfigurationEntity): """Inovelli off to on remote ramp rate configuration entity.""" @@ -880,7 +880,7 @@ class InovelliRemoteDimmingSpeedOffToOn(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRemoteDimmingDownSpeed(NumberConfigurationEntity): """Inovelli remote dimming down speed configuration entity.""" @@ -898,7 +898,7 @@ class InovelliRemoteDimmingDownSpeed(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalDimmingDownSpeed(NumberConfigurationEntity): """Inovelli local dimming down speed configuration entity.""" @@ -916,7 +916,7 @@ class InovelliLocalDimmingDownSpeed(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalRampRateOnToOff(NumberConfigurationEntity): """Inovelli local on to off ramp rate configuration entity.""" @@ -934,7 +934,7 @@ class InovelliLocalRampRateOnToOff(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRemoteDimmingSpeedOnToOff(NumberConfigurationEntity): """Inovelli remote on to off ramp rate configuration entity.""" @@ -952,7 +952,7 @@ class InovelliRemoteDimmingSpeedOnToOff(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliMinimumLoadDimmingLevel(NumberConfigurationEntity): """Inovelli minimum load dimming level configuration entity.""" @@ -970,7 +970,7 @@ class InovelliMinimumLoadDimmingLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliMaximumLoadDimmingLevel(NumberConfigurationEntity): """Inovelli maximum load dimming level configuration entity.""" @@ -988,7 +988,7 @@ class InovelliMaximumLoadDimmingLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliAutoShutoffTimer(NumberConfigurationEntity): """Inovelli automatic switch shutoff timer configuration entity.""" @@ -1006,7 +1006,7 @@ class InovelliAutoShutoffTimer(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalDefaultLevel(NumberConfigurationEntity): """Inovelli local default dimming/fan level configuration entity.""" @@ -1024,7 +1024,7 @@ class InovelliLocalDefaultLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRemoteDefaultLevel(NumberConfigurationEntity): """Inovelli remote default dimming/fan level configuration entity.""" @@ -1042,7 +1042,7 @@ class InovelliRemoteDefaultLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliStartupDefaultLevel(NumberConfigurationEntity): """Inovelli start-up default dimming/fan level configuration entity.""" @@ -1060,7 +1060,7 @@ class InovelliStartupDefaultLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliQuickStartTime(NumberConfigurationEntity): """Inovelli fan quick start time configuration entity.""" @@ -1079,7 +1079,7 @@ class InovelliQuickStartTime(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLoadLevelIndicatorTimeout(NumberConfigurationEntity): """Inovelli load level indicator timeout configuration entity.""" @@ -1097,7 +1097,7 @@ class InovelliLoadLevelIndicatorTimeout(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDefaultAllLEDOnColor(NumberConfigurationEntity): """Inovelli default all led color when on configuration entity.""" @@ -1115,7 +1115,7 @@ class InovelliDefaultAllLEDOnColor(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDefaultAllLEDOffColor(NumberConfigurationEntity): """Inovelli default all led color when off configuration entity.""" @@ -1133,7 +1133,7 @@ class InovelliDefaultAllLEDOffColor(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDefaultAllLEDOnIntensity(NumberConfigurationEntity): """Inovelli default all led intensity when on configuration entity.""" @@ -1151,7 +1151,7 @@ class InovelliDefaultAllLEDOnIntensity(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDefaultAllLEDOffIntensity(NumberConfigurationEntity): """Inovelli default all led intensity when off configuration entity.""" @@ -1169,7 +1169,7 @@ class InovelliDefaultAllLEDOffIntensity(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDoubleTapUpLevel(NumberConfigurationEntity): """Inovelli double tap up level configuration entity.""" @@ -1187,7 +1187,7 @@ class InovelliDoubleTapUpLevel(NumberConfigurationEntity): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDoubleTapDownLevel(NumberConfigurationEntity): """Inovelli double tap down level configuration entity.""" @@ -1205,7 +1205,7 @@ class InovelliDoubleTapDownLevel(NumberConfigurationEntity): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederServingSize(NumberConfigurationEntity): """Aqara pet feeder serving size configuration entity.""" @@ -1225,7 +1225,7 @@ class AqaraPetFeederServingSize(NumberConfigurationEntity): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederPortionWeight(NumberConfigurationEntity): """Aqara pet feeder portion weight configuration entity.""" @@ -1246,7 +1246,7 @@ class AqaraPetFeederPortionWeight(NumberConfigurationEntity): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatAwayTemp(NumberConfigurationEntity): """Aqara away preset temperature configuration entity.""" @@ -1268,7 +1268,7 @@ class AqaraThermostatAwayTemp(NumberConfigurationEntity): ) -@register_entity(Thermostat.cluster_id) +@register_entity class ThermostatLocalTempCalibration(NumberConfigurationEntity): """Local temperature calibration.""" @@ -1400,7 +1400,7 @@ class ThermostatLocalTempCalibration(NumberConfigurationEntity): } -@register_entity(Thermostat.cluster_id) +@register_entity class SonoffThermostatLocalTempCalibration(ThermostatLocalTempCalibration): """Local temperature calibration for the Sonoff TRVZB.""" @@ -1415,7 +1415,7 @@ class SonoffThermostatLocalTempCalibration(ThermostatLocalTempCalibration): ) -@register_entity(Thermostat.cluster_id) +@register_entity class BoschThermostatLocalTempCalibration(ThermostatLocalTempCalibration): """Local temperature calibration for the Bosch TRV/RTH.""" @@ -1468,7 +1468,7 @@ def recompute_capabilities(self) -> None: ) -@register_entity(Thermostat.cluster_id) +@register_entity class MaxHeatSetpointLimit(ZCLHeatSetpointLimitEntity): """Max heat setpoint setting on thermostats. @@ -1496,7 +1496,7 @@ def recompute_capabilities(self) -> None: ) -@register_entity(Thermostat.cluster_id) +@register_entity class MinHeatSetpointLimit(ZCLHeatSetpointLimitEntity): """Min heat setpoint setting on thermostats. @@ -1524,7 +1524,7 @@ def recompute_capabilities(self) -> None: ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossExerciseTriggerTime(NumberConfigurationEntity): """Danfoss proprietary attribute to set the time to exercise the valve.""" @@ -1543,7 +1543,7 @@ class DanfossExerciseTriggerTime(NumberConfigurationEntity): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossExternalMeasuredRoomSensor(ZCLTemperatureEntity): """Danfoss proprietary attribute to communicate the value of the external temperature sensor.""" @@ -1560,7 +1560,7 @@ class DanfossExternalMeasuredRoomSensor(ZCLTemperatureEntity): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossLoadRoomMean(NumberConfigurationEntity): """Danfoss proprietary attribute to set a value for the load.""" @@ -1578,7 +1578,7 @@ class DanfossLoadRoomMean(NumberConfigurationEntity): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossRegulationSetpointOffset(NumberConfigurationEntity): """Danfoss proprietary attribute to set the regulation setpoint offset.""" @@ -1599,7 +1599,7 @@ class DanfossRegulationSetpointOffset(NumberConfigurationEntity): ) -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeDimmerOnLevelConfigurationEntity(NumberConfigurationEntity): """Representation of a Sinope dimmer switch on level.""" @@ -1617,7 +1617,7 @@ class SinopeDimmerOnLevelConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeLightLEDOnIntensityConfigurationEntity(NumberConfigurationEntity): """Representation of a Sinope switch LED on-level brightness.""" @@ -1644,7 +1644,7 @@ class SinopeLightLEDOnIntensityConfigurationEntity(NumberConfigurationEntity): ) -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeLightLEDOffIntensityConfigurationEntity(NumberConfigurationEntity): """Representation of a Sinope switch LED off-level brightness.""" diff --git a/zha/application/platforms/select.py b/zha/application/platforms/select.py index 5131bf6c6..2291f2ab4 100644 --- a/zha/application/platforms/select.py +++ b/zha/application/platforms/select.py @@ -178,7 +178,7 @@ def restore_external_state_attributes( self._siren().defaults[self._enum] = self._option_to_member[state] -@register_entity(IasWd.cluster_id) +@register_entity class DefaultToneSelectEntity(SirenDefaultSelectEntity): """Representation of a ZHA default siren tone select entity.""" @@ -192,7 +192,7 @@ class DefaultToneSelectEntity(SirenDefaultSelectEntity): ) -@register_entity(IasWd.cluster_id) +@register_entity class DefaultSirenLevelSelectEntity(SirenDefaultSelectEntity): """Representation of a ZHA default siren level select entity.""" @@ -206,7 +206,7 @@ class DefaultSirenLevelSelectEntity(SirenDefaultSelectEntity): ) -@register_entity(IasWd.cluster_id) +@register_entity class DefaultStrobeLevelSelectEntity(SirenDefaultSelectEntity): """Representation of a ZHA default siren strobe level select entity.""" @@ -220,7 +220,7 @@ class DefaultStrobeLevelSelectEntity(SirenDefaultSelectEntity): ) -@register_entity(IasWd.cluster_id) +@register_entity class DefaultStrobeSelectEntity(SirenDefaultSelectEntity): """Representation of a ZHA default siren strobe select entity.""" @@ -341,7 +341,7 @@ def restore_external_state_attributes( # Select entities backed by the ZCL cache don't need to restore their state! -@register_entity(OnOff.cluster_id) +@register_entity class StartupOnOffSelectEntity(ZCLEnumSelectEntity): """Representation of a ZHA startup onoff select entity.""" @@ -381,7 +381,7 @@ class TuyaPowerOnState(types.enum8): LastState = 0x02 -@register_entity(OnOff.cluster_id) +@register_entity class TuyaPowerOnStateSelectEntity(ZCLEnumSelectEntity): """Representation of a ZHA power on state select entity.""" @@ -405,7 +405,7 @@ class TuyaPowerOnStateSelectEntity(ZCLEnumSelectEntity): } -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class TuyaManufacturerPowerOnStateSelectEntity(ZCLEnumSelectEntity): """Representation of a ZHA power on state select entity.""" @@ -429,7 +429,7 @@ class TuyaBacklightMode(types.enum8): LightWhenOff = 0x02 -@register_entity(OnOff.cluster_id) +@register_entity class TuyaBacklightModeSelectEntity(ZCLEnumSelectEntity): """Representation of a ZHA backlight mode select entity.""" @@ -462,7 +462,7 @@ class MoesBacklightMode(types.enum8): Freeze = 0x03 -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class MoesBacklightModeSelectEntity(ZCLEnumSelectEntity): """Moes devices have a different backlight mode select options.""" @@ -486,7 +486,7 @@ class AqaraMotionSensitivities(types.enum8): High = 0x03 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionSensitivity(ZCLEnumSelectEntity): """Representation of a ZHA motion sensitivity configuration entity.""" @@ -510,7 +510,7 @@ class HueV1MotionSensitivities(types.enum8): High = 0x02 -@register_entity(OccupancySensing.cluster_id) +@register_entity class HueV1MotionSensitivity(ZCLEnumSelectEntity): """Representation of a ZHA motion sensitivity configuration entity.""" @@ -557,7 +557,7 @@ class HueV2MotionSensitivities(types.enum8): Highest = 0x04 -@register_entity(OccupancySensing.cluster_id) +@register_entity class HueV2MotionSensitivity(ZCLEnumSelectEntity): """Representation of a ZHA motion sensitivity configuration entity.""" @@ -581,7 +581,7 @@ class AqaraMonitoringModess(types.enum8): Left_Right = 0x01 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMonitoringMode(ZCLEnumSelectEntity): """Representation of a ZHA monitoring mode configuration entity.""" @@ -605,7 +605,7 @@ class AqaraApproachDistances(types.enum8): Near = 0x02 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraApproachDistance(ZCLEnumSelectEntity): """Representation of a ZHA approach distance configuration entity.""" @@ -621,7 +621,7 @@ class AqaraApproachDistance(ZCLEnumSelectEntity): ) -@register_entity(MagnetAC01OppleCluster.cluster_id) +@register_entity class AqaraMagnetAC01DetectionDistance(ZCLEnumSelectEntity): """Representation of a ZHA detection distance configuration entity.""" @@ -637,7 +637,7 @@ class AqaraMagnetAC01DetectionDistance(ZCLEnumSelectEntity): ) -@register_entity(T2RelayOppleCluster.cluster_id) +@register_entity class AqaraT2RelaySwitchMode(ZCLEnumSelectEntity): """Representation of a ZHA switch mode configuration entity.""" @@ -653,7 +653,7 @@ class AqaraT2RelaySwitchMode(ZCLEnumSelectEntity): ) -@register_entity(T2RelayOppleCluster.cluster_id) +@register_entity class AqaraT2RelaySwitchType(ZCLEnumSelectEntity): """Representation of a ZHA switch type configuration entity.""" @@ -669,7 +669,7 @@ class AqaraT2RelaySwitchType(ZCLEnumSelectEntity): ) -@register_entity(T2RelayOppleCluster.cluster_id) +@register_entity class AqaraT2RelayStartupOnOff(ZCLEnumSelectEntity): """Representation of a ZHA startup on off configuration entity.""" @@ -685,7 +685,7 @@ class AqaraT2RelayStartupOnOff(ZCLEnumSelectEntity): ) -@register_entity(T2RelayOppleCluster.cluster_id) +@register_entity class AqaraT2RelayDecoupledMode(ZCLEnumSelectEntity): """Representation of a ZHA switch decoupled mode configuration entity.""" @@ -708,7 +708,7 @@ class InovelliOutputMode(types.enum1): OnOff = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliOutputModeEntity(ZCLEnumSelectEntity): """Inovelli output mode control.""" @@ -732,7 +732,7 @@ class InovelliSwitchType(types.enum8): Single_Pole_Full_Sine = 0x03 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliSwitchTypeEntity(ZCLEnumSelectEntity): """Inovelli switch type control.""" @@ -755,7 +755,7 @@ class InovelliFanSwitchType(types.enum1): Three_Way_AUX = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliFanSwitchTypeEntity(ZCLEnumSelectEntity): """Inovelli fan switch type control.""" @@ -778,7 +778,7 @@ class InovelliLedScalingMode(types.enum1): LZW31SN = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLedScalingModeEntity(ZCLEnumSelectEntity): """Inovelli led mode control.""" @@ -809,7 +809,7 @@ class InovelliFanLedScalingMode(types.enum8): Adaptive = 0x0A -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliFanLedScalingModeEntity(ZCLEnumSelectEntity): """Inovelli fan switch led mode control.""" @@ -832,7 +832,7 @@ class InovelliNonNeutralOutput(types.enum1): High = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliNonNeutralOutputEntity(ZCLEnumSelectEntity): """Inovelli non neutral output control.""" @@ -854,7 +854,7 @@ class InovelliDimmingMode(types.enum1): TrailingEdge = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDimmingModeEntity(ZCLEnumSelectEntity): """Inovelli dimming mode control.""" @@ -877,7 +877,7 @@ class AqaraFeedingMode(types.enum8): Schedule = 0x01 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederMode(ZCLEnumSelectEntity): """Representation of an Aqara pet feeder mode configuration entity.""" @@ -901,7 +901,7 @@ class AqaraThermostatPresetMode(types.enum8): Away = 0x02 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatPreset(ZCLEnumSelectEntity): """Representation of an Aqara thermostat preset configuration entity.""" @@ -925,7 +925,7 @@ class SonoffPresenceDetectionSensitivityEnum(types.enum8): High = 0x03 -@register_entity(OccupancySensing.cluster_id) +@register_entity class SonoffPresenceDetectionSensitivity(ZCLEnumSelectEntity): """Entity to set the detection sensitivity of the Sonoff SNZB-06P.""" @@ -951,7 +951,7 @@ class KeypadLockoutEnum(types.enum8): Lock4 = 0x04 -@register_entity(UserInterface.cluster_id) +@register_entity class KeypadLockout(ZCLEnumSelectEntity): """Mandatory attribute for thermostat_ui cluster. @@ -981,7 +981,7 @@ class KeypadLockout(ZCLEnumSelectEntity): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossExerciseDayOfTheWeek(ZCLEnumSelectEntity): """Danfoss proprietary attribute for setting the day of the week for exercising.""" @@ -1114,7 +1114,7 @@ class DanfossOrientationEnum(types.enum8): Vertical = 0x01 -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossOrientation(ZCLEnumSelectEntity): """Danfoss proprietary attribute for setting the orientation of the valve. @@ -1134,7 +1134,7 @@ class DanfossOrientation(ZCLEnumSelectEntity): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossAdaptationRunControl(ZCLEnumSelectEntity): """Danfoss proprietary attribute for controlling the current adaptation run.""" @@ -1175,7 +1175,7 @@ class DanfossControlAlgorithmScaleFactorEnum(types.enum8): quick_open_disabled = 0x11 # not sure what it does; also requires lower 4 bits to be in [1, 10] I assume -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossControlAlgorithmScaleFactor(ZCLEnumSelectEntity): """Danfoss proprietary attribute for setting the scale factor of the setpoint filter time constant.""" @@ -1191,7 +1191,7 @@ class DanfossControlAlgorithmScaleFactor(ZCLEnumSelectEntity): ) -@register_entity(UserInterface.cluster_id) +@register_entity class DanfossViewingDirection(ZCLEnumSelectEntity): """Danfoss proprietary attribute for setting the viewing direction of the screen.""" @@ -1238,7 +1238,7 @@ class SinopeLightLedColors(types.enum32): ) -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeLightLEDOffColorSelect(ZCLEnumSelectEntity): """Representation of the marker LED Off-state color of Sinope light switches.""" @@ -1254,7 +1254,7 @@ class SinopeLightLEDOffColorSelect(ZCLEnumSelectEntity): ) -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeLightLEDOnColorSelect(ZCLEnumSelectEntity): """Representation of the marker LED On-state color of Sinope light switches.""" @@ -1277,7 +1277,7 @@ class BegaColorTemperatureChannel(types.enum8): Cool_white = 0x01 -@register_entity(LevelControl.cluster_id) +@register_entity class BegaColorTemperatureChannelSelect(ZCLEnumSelectEntity): """Select entity for switching BEGA light color temperature channel.""" diff --git a/zha/application/platforms/sensor/__init__.py b/zha/application/platforms/sensor/__init__.py index 5ac490b1b..41b070998 100644 --- a/zha/application/platforms/sensor/__init__.py +++ b/zha/application/platforms/sensor/__init__.py @@ -561,7 +561,7 @@ def formatter(self, value: int) -> str | None: return self._enum(value).name -@register_entity(AnalogInput.cluster_id) +@register_entity class DigiAnalogInput(Sensor): """Sensor that displays analog input values.""" @@ -616,7 +616,7 @@ class DigiAnalogInput(Sensor): } -@register_entity(AnalogInput.cluster_id) +@register_entity class AnalogInputSensor(Sensor): """Sensor that displays analog input values.""" @@ -722,7 +722,7 @@ def _is_supported(self) -> bool: return super()._is_supported() -@register_entity(PowerConfiguration.cluster_id) +@register_entity class Battery(Sensor): """Battery sensor of power configuration cluster.""" @@ -943,7 +943,7 @@ async def async_update(self) -> None: ) -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementPoller(AggregatedClusterPoller): """Polls the EM cluster on behalf of sibling entities that need updates.""" @@ -955,7 +955,7 @@ class ElectricalMeasurementPoller(AggregatedClusterPoller): ) -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementReportingDevice(VirtualEntity): """Claims the EM polling slot for devices that support reporting. @@ -972,7 +972,7 @@ class ElectricalMeasurementReportingDevice(VirtualEntity): ) -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementActivePower(BaseElectricalMeasurement): """Active power measurement.""" @@ -1037,7 +1037,7 @@ class ElectricalMeasurementActivePower(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementActivePowerPhB(BaseElectricalMeasurement): """Active power phase B measurement.""" @@ -1105,7 +1105,7 @@ class ElectricalMeasurementActivePowerPhB(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementActivePowerPhC(BaseElectricalMeasurement): """Active power phase C measurement.""" @@ -1173,7 +1173,7 @@ class ElectricalMeasurementActivePowerPhC(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementTotalActivePower(BaseElectricalMeasurement): """Total active power measurement.""" @@ -1241,7 +1241,7 @@ class ElectricalMeasurementTotalActivePower(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementApparentPower(BaseElectricalMeasurement): """Apparent power measurement.""" @@ -1304,7 +1304,7 @@ class ElectricalMeasurementApparentPower(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSCurrent(BaseElectricalMeasurement): """RMS current measurement.""" @@ -1358,7 +1358,7 @@ class ElectricalMeasurementRMSCurrent(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSCurrentPhB(ElectricalMeasurementRMSCurrent): """RMS current phase B measurement.""" @@ -1405,7 +1405,7 @@ class ElectricalMeasurementRMSCurrentPhB(ElectricalMeasurementRMSCurrent): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSCurrentPhC(ElectricalMeasurementRMSCurrent): """RMS current phase C measurement.""" @@ -1452,7 +1452,7 @@ class ElectricalMeasurementRMSCurrentPhC(ElectricalMeasurementRMSCurrent): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSVoltage(BaseElectricalMeasurement): """RMS Voltage measurement.""" @@ -1506,7 +1506,7 @@ class ElectricalMeasurementRMSVoltage(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSVoltagePhB(ElectricalMeasurementRMSVoltage): """RMS voltage phase B measurement.""" @@ -1553,7 +1553,7 @@ class ElectricalMeasurementRMSVoltagePhB(ElectricalMeasurementRMSVoltage): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementRMSVoltagePhC(ElectricalMeasurementRMSVoltage): """RMS voltage phase C measurement.""" @@ -1600,7 +1600,7 @@ class ElectricalMeasurementRMSVoltagePhC(ElectricalMeasurementRMSVoltage): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementFrequency(BaseElectricalMeasurement): """Frequency measurement.""" @@ -1649,7 +1649,7 @@ class ElectricalMeasurementFrequency(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementPowerFactor(BaseElectricalMeasurement): """Power Factor measurement.""" @@ -1685,7 +1685,7 @@ class ElectricalMeasurementPowerFactor(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementPowerFactorPhB(ElectricalMeasurementPowerFactor): """Power factor phase B measurement.""" @@ -1713,7 +1713,7 @@ class ElectricalMeasurementPowerFactorPhB(ElectricalMeasurementPowerFactor): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementPowerFactorPhC(ElectricalMeasurementPowerFactor): """Power factor phase C measurement.""" @@ -1741,7 +1741,7 @@ class ElectricalMeasurementPowerFactorPhC(ElectricalMeasurementPowerFactor): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementDCVoltage(BaseElectricalMeasurement): """DC Voltage measurement.""" @@ -1794,7 +1794,7 @@ class ElectricalMeasurementDCVoltage(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementDCCurrent(BaseElectricalMeasurement): """DC Current measurement.""" @@ -1847,7 +1847,7 @@ class ElectricalMeasurementDCCurrent(BaseElectricalMeasurement): } -@register_entity(ElectricalMeasurement.cluster_id) +@register_entity class ElectricalMeasurementDCPower(BaseElectricalMeasurement): """DC Power measurement.""" @@ -1912,7 +1912,7 @@ class ElectricalMeasurementDCPower(BaseElectricalMeasurement): } -@register_entity(RelativeHumidity.cluster_id) +@register_entity class Humidity(Sensor): """Humidity sensor.""" @@ -1943,7 +1943,7 @@ class Humidity(Sensor): } -@register_entity(SMARTTHINGS_HUMIDITY_CLUSTER) +@register_entity class SmartThingsHumidity(Sensor): """Humidity sensor.""" @@ -1974,7 +1974,7 @@ class SmartThingsHumidity(Sensor): } -@register_entity(SoilMoistureCluster.cluster_id) +@register_entity class SoilMoisture(Sensor): """Soil Moisture sensor.""" @@ -2006,7 +2006,7 @@ class SoilMoisture(Sensor): } -@register_entity(LeafWetnessCluster.cluster_id) +@register_entity class LeafWetness(Sensor): """Leaf Wetness sensor.""" @@ -2038,7 +2038,7 @@ class LeafWetness(Sensor): } -@register_entity(IlluminanceMeasurement.cluster_id) +@register_entity class Illuminance(Sensor): """Illuminance Sensor.""" @@ -2087,7 +2087,7 @@ class SmartEnergyMeteringEntityDescription: device_class: SensorDeviceClass | None = None -@register_entity(Metering.cluster_id) +@register_entity class MeteringPoller(AggregatedClusterPoller): """Polls the Metering cluster for models known to need polling. @@ -2103,7 +2103,7 @@ class MeteringPoller(AggregatedClusterPoller): ) -@register_entity(Metering.cluster_id) +@register_entity class ExposedFeatureMeteringPoller(MeteringPoller): """Polls the Metering cluster for devices whose quirk exposes SE_POLL_SUMMATION.""" @@ -2114,7 +2114,7 @@ class ExposedFeatureMeteringPoller(MeteringPoller): ) -@register_entity(Metering.cluster_id) +@register_entity class SmartEnergyMetering(Sensor): """Metering sensor.""" @@ -2383,7 +2383,7 @@ class SmartEnergySummationEntityDescription(SmartEnergyMeteringEntityDescription state_class: SensorStateClass | None = SensorStateClass.TOTAL_INCREASING -@register_entity(Metering.cluster_id) +@register_entity class SmartEnergySummation(SmartEnergyMetering): """Smart Energy Metering summation sensor.""" @@ -2473,7 +2473,7 @@ def formatter(self, value: int) -> int | float: return float(summation_formater.format(scaled_value)) -@register_entity(Metering.cluster_id) +@register_entity class Tier1SmartEnergySummation(SmartEnergySummation): """Tier 1 Smart Energy Metering summation sensor.""" @@ -2487,7 +2487,7 @@ class Tier1SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class Tier2SmartEnergySummation(SmartEnergySummation): """Tier 2 Smart Energy Metering summation sensor.""" @@ -2501,7 +2501,7 @@ class Tier2SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class Tier3SmartEnergySummation(SmartEnergySummation): """Tier 3 Smart Energy Metering summation sensor.""" @@ -2515,7 +2515,7 @@ class Tier3SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class Tier4SmartEnergySummation(SmartEnergySummation): """Tier 4 Smart Energy Metering summation sensor.""" @@ -2529,7 +2529,7 @@ class Tier4SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class Tier5SmartEnergySummation(SmartEnergySummation): """Tier 5 Smart Energy Metering summation sensor.""" @@ -2543,7 +2543,7 @@ class Tier5SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class Tier6SmartEnergySummation(SmartEnergySummation): """Tier 6 Smart Energy Metering summation sensor.""" @@ -2557,7 +2557,7 @@ class Tier6SmartEnergySummation(SmartEnergySummation): ) -@register_entity(Metering.cluster_id) +@register_entity class SmartEnergySummationReceived(SmartEnergySummation): """Smart Energy Metering summation received sensor.""" @@ -2577,7 +2577,7 @@ class SmartEnergySummationReceived(SmartEnergySummation): ) -@register_entity(PressureMeasurement.cluster_id) +@register_entity class Pressure(Sensor): """Pressure sensor.""" @@ -2608,7 +2608,7 @@ class Pressure(Sensor): } -@register_entity(FlowMeasurement.cluster_id) +@register_entity class Flow(Sensor): """Flow Measurement sensor.""" @@ -2639,7 +2639,7 @@ class Flow(Sensor): } -@register_entity(TemperatureMeasurement.cluster_id) +@register_entity class Temperature(Sensor): """Temperature Sensor.""" @@ -2670,7 +2670,7 @@ class Temperature(Sensor): } -@register_entity(DeviceTemperatureCluster.cluster_id) +@register_entity class DeviceTemperature(Sensor): """Device Temperature Sensor.""" @@ -2703,7 +2703,7 @@ class DeviceTemperature(Sensor): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliInternalTemperature(Sensor): """Switch Internal Temperature Sensor.""" @@ -2727,7 +2727,7 @@ class InovelliOverheatedState(types.enum8): Overheated = 0x01 -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliOverheated(EnumSensor): """Sensor that displays the overheat protection state.""" @@ -2743,7 +2743,7 @@ class InovelliOverheated(EnumSensor): ) -@register_entity(CarbonDioxideConcentrationCluster.cluster_id) +@register_entity class CarbonDioxideConcentration(Sensor): """Carbon Dioxide Concentration sensor.""" @@ -2775,7 +2775,7 @@ class CarbonDioxideConcentration(Sensor): } -@register_entity(CarbonMonoxideConcentrationCluster.cluster_id) +@register_entity class CarbonMonoxideConcentration(Sensor): """Carbon Monoxide Concentration sensor.""" @@ -2807,7 +2807,7 @@ class CarbonMonoxideConcentration(Sensor): } -@register_entity(VOC_LEVEL_CLUSTER) +@register_entity class VOCLevel(Sensor): """VOC Level sensor.""" @@ -2829,7 +2829,7 @@ class VOCLevel(Sensor): } -@register_entity(VOC_LEVEL_CLUSTER) +@register_entity class PPBVOCLevel(Sensor): """VOC Level sensor.""" @@ -2854,7 +2854,7 @@ class PPBVOCLevel(Sensor): } -@register_entity(PM25Cluster.cluster_id) +@register_entity class PM25(Sensor): """Particulate Matter 2.5 microns or less sensor.""" @@ -2885,7 +2885,7 @@ class PM25(Sensor): } -@register_entity(ElectricalConductivityCluster.cluster_id) +@register_entity class ElectricalConductivity(Sensor): """Electrical Conductivity sensor.""" @@ -2914,7 +2914,7 @@ class ElectricalConductivity(Sensor): } -@register_entity(FormaldehydeConcentrationCluster.cluster_id) +@register_entity class FormaldehydeConcentration(Sensor): """Formaldehyde Concentration sensor.""" @@ -2946,7 +2946,7 @@ class FormaldehydeConcentration(Sensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class ThermostatHVACAction(Sensor): """Thermostat HVAC action sensor.""" @@ -3160,7 +3160,7 @@ def _pi_demand_action(self) -> HVACAction: return HVACAction.OFF -@register_entity(Thermostat.cluster_id) +@register_entity class SinopeHVACAction(ThermostatHVACAction): """Sinope Thermostat HVAC action sensor.""" @@ -3195,7 +3195,7 @@ def _rm_rs_action(self) -> HVACAction: return HVACAction.OFF -@register_entity(Basic.cluster_id) +@register_entity class RSSISensor(Sensor): """RSSI sensor for a device.""" @@ -3277,7 +3277,7 @@ def update(self): ) -@register_entity(Basic.cluster_id) +@register_entity class LQISensor(RSSISensor): """LQI sensor for a device.""" @@ -3305,7 +3305,7 @@ def native_value(self) -> str | int | float | None: return self._device.device.lqi -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class TimeLeft(Sensor): """Sensor that displays time left value.""" @@ -3322,7 +3322,7 @@ class TimeLeft(Sensor): ) -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class IkeaDeviceRunTime(Sensor): """Sensor that displays device run time (in minutes).""" @@ -3339,7 +3339,7 @@ class IkeaDeviceRunTime(Sensor): ) -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class IkeaFilterRunTime(Sensor): """Sensor that displays run time of the current filter (in minutes).""" @@ -3363,7 +3363,7 @@ class AqaraFeedingSource(types.enum8): HomeAssistant = 0x02 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederLastFeedingSource(EnumSensor): """Sensor that displays the last feeding source of pet feeder.""" @@ -3379,7 +3379,7 @@ class AqaraPetFeederLastFeedingSource(EnumSensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederLastFeedingSize(Sensor): """Sensor that displays the last feeding size of the pet feeder.""" @@ -3394,7 +3394,7 @@ class AqaraPetFeederLastFeedingSize(Sensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederPortionsDispensed(Sensor): """Sensor that displays the number of portions dispensed by the pet feeder.""" @@ -3410,7 +3410,7 @@ class AqaraPetFeederPortionsDispensed(Sensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederWeightDispensed(Sensor): """Sensor that displays the weight dispensed by the pet feeder.""" @@ -3427,7 +3427,7 @@ class AqaraPetFeederWeightDispensed(Sensor): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraSmokeDensityDbm(Sensor): """Sensor that displays the smoke density of an Aqara smoke sensor in dB/m.""" @@ -3452,7 +3452,7 @@ class SonoffIlluminationStates(types.enum8): Light = 0x01 -@register_entity(SONOFF_CLUSTER) +@register_entity class SonoffPresenceSenorIlluminationStatus(EnumSensor): """Sensor that displays the illumination status the last time peresence was detected.""" @@ -3468,7 +3468,7 @@ class SonoffPresenceSenorIlluminationStatus(EnumSensor): ) -@register_entity(Thermostat.cluster_id) +@register_entity class PiHeatingDemand(Sensor): """Sensor that displays the percentage of heating power demanded. @@ -3498,7 +3498,7 @@ class SetpointChangeSourceEnum(types.enum8): External = 0x02 -@register_entity(Thermostat.cluster_id) +@register_entity class SetpointChangeSource(EnumSensor): """Sensor that displays the source of the setpoint change. @@ -3517,7 +3517,7 @@ class SetpointChangeSource(EnumSensor): ) -@register_entity(Thermostat.cluster_id) +@register_entity class SetpointChangeSourceTimestamp(TimestampSensor): """Sensor that displays the timestamp the setpoint change. @@ -3540,7 +3540,7 @@ def formatter(self, value: types.UTCTime) -> datetime: return ZCL_EPOCH + timedelta(seconds=value) -@register_entity(WindowCovering.cluster_id) +@register_entity class WindowCoveringTypeSensor(EnumSensor): """Sensor that displays the type of a cover device.""" @@ -3567,7 +3567,7 @@ class WindowCoveringTypeSensor(EnumSensor): } -@register_entity(Basic.cluster_id) +@register_entity class AqaraCurtainMotorPowerSourceSensor(EnumSensor): """Sensor that displays the power source of the Aqara E1 curtain motor device.""" @@ -3603,7 +3603,7 @@ class AqaraE1HookState(types.enum8): Unlocking = 0x03 -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraCurtainHookStateSensor(EnumSensor): """Representation of a ZHA curtain mode configuration entity.""" @@ -3670,7 +3670,7 @@ def formatter(self, _value: int) -> str: return "something" if binary_state_attributes else "nothing" -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossOpenWindowDetection(EnumSensor): """Danfoss proprietary attribute. @@ -3703,7 +3703,7 @@ class DanfossOpenWindowDetection(EnumSensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossLoadEstimate(Sensor): """Danfoss proprietary attribute for communicating its estimate of the radiator load.""" @@ -3733,7 +3733,7 @@ class DanfossLoadEstimate(Sensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossAdaptationRunStatus(BitMapSensor): """Danfoss proprietary attribute for showing the status of the adaptation run.""" @@ -3764,7 +3764,7 @@ class DanfossAdaptationRunStatus(BitMapSensor): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossPreheatTime(Sensor): """Danfoss proprietary attribute for communicating the time when it starts pre-heating.""" @@ -3795,7 +3795,7 @@ class DanfossPreheatTime(Sensor): } -@register_entity(Diagnostic.cluster_id) +@register_entity class DanfossSoftwareErrorCode(BitMapSensor): """Danfoss proprietary attribute for communicating the error code.""" @@ -3826,7 +3826,7 @@ class DanfossSoftwareErrorCode(BitMapSensor): } -@register_entity(Diagnostic.cluster_id) +@register_entity class DanfossMotorStepCounter(Sensor): """Danfoss proprietary attribute for communicating the motor step counter.""" @@ -3856,7 +3856,7 @@ class DanfossMotorStepCounter(Sensor): } -@register_entity(WindSpeedCluster.cluster_id) +@register_entity class WindSpeed(Sensor): """Wind Speed sensor.""" diff --git a/zha/application/platforms/siren.py b/zha/application/platforms/siren.py index 4a3688681..1a001988e 100644 --- a/zha/application/platforms/siren.py +++ b/zha/application/platforms/siren.py @@ -217,7 +217,7 @@ def _async_set_off(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(IasWd.cluster_id) +@register_entity class AdvancedSiren(BaseZclSiren): """Representation of a ZHA siren with full tone, level, and strobe support.""" @@ -328,7 +328,7 @@ async def async_turn_on( self.maybe_emit_state_changed_event() -@register_entity(IasWd.cluster_id) +@register_entity class BasicSiren(BaseZclSiren): """Representation of a basic ZHA siren with fixed tone, level, and strobe.""" diff --git a/zha/application/platforms/switch.py b/zha/application/platforms/switch.py index a6474a2ce..f1aa0cec4 100644 --- a/zha/application/platforms/switch.py +++ b/zha/application/platforms/switch.py @@ -94,7 +94,7 @@ async def async_turn_off(self) -> None: """Turn the entity off.""" -@register_entity(OnOff.cluster_id) +@register_entity class Switch(PlatformEntity, BaseSwitch): """ZHA switch.""" @@ -235,7 +235,7 @@ async def async_update(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(BinaryOutput.cluster_id) +@register_entity class BinaryOutputSwitch(PlatformEntity, BaseSwitch): """BinaryOutputCluster switch.""" @@ -563,7 +563,7 @@ async def async_update(self) -> None: self.maybe_emit_state_changed_event() -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class OnOffWindowDetectionFunctionConfigurationEntity(ConfigurableAttributeSwitch): """Representation of a ZHA window detection configuration entity.""" @@ -579,7 +579,7 @@ class OnOffWindowDetectionFunctionConfigurationEntity(ConfigurableAttributeSwitc ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class P1MotionTriggerIndicatorSwitch(ConfigurableAttributeSwitch): """Representation of a ZHA motion triggering configuration entity.""" @@ -594,7 +594,7 @@ class P1MotionTriggerIndicatorSwitch(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class XiaomiPlugPowerOutageMemorySwitch(ConfigurableAttributeSwitch): """Representation of a ZHA power outage memory configuration entity.""" @@ -609,7 +609,7 @@ class XiaomiPlugPowerOutageMemorySwitch(ConfigurableAttributeSwitch): ) -@register_entity(Basic.cluster_id) +@register_entity class HueMotionTriggerIndicatorSwitch(ConfigurableAttributeSwitch): """Representation of a ZHA motion triggering configuration entity.""" @@ -633,7 +633,7 @@ class HueMotionTriggerIndicatorSwitch(ConfigurableAttributeSwitch): } -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class ChildLock(ConfigurableAttributeSwitch): """ZHA BinarySensor.""" @@ -648,7 +648,7 @@ class ChildLock(ConfigurableAttributeSwitch): ) -@register_entity(IKEA_AIR_PURIFIER_CLUSTER) +@register_entity class DisableLed(ConfigurableAttributeSwitch): """ZHA BinarySensor.""" @@ -663,7 +663,7 @@ class DisableLed(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliInvertSwitch(ConfigurableAttributeSwitch): """Inovelli invert switch control.""" @@ -678,7 +678,7 @@ class InovelliInvertSwitch(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliSmartBulbMode(ConfigurableAttributeSwitch): """Inovelli smart bulb mode control.""" @@ -693,7 +693,7 @@ class InovelliSmartBulbMode(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliSmartFanMode(ConfigurableAttributeSwitch): """Inovelli smart fan mode control.""" @@ -709,7 +709,7 @@ class InovelliSmartFanMode(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDoubleTapUpEnabled(ConfigurableAttributeSwitch): """Inovelli double tap up enabled.""" @@ -724,7 +724,7 @@ class InovelliDoubleTapUpEnabled(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDoubleTapDownEnabled(ConfigurableAttributeSwitch): """Inovelli double tap down enabled.""" @@ -739,7 +739,7 @@ class InovelliDoubleTapDownEnabled(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliAuxSwitchScenes(ConfigurableAttributeSwitch): """Inovelli unique aux switch scenes.""" @@ -754,7 +754,7 @@ class InovelliAuxSwitchScenes(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliBindingOffToOnSyncLevel(ConfigurableAttributeSwitch): """Inovelli send move to level with on/off to bound devices.""" @@ -769,7 +769,7 @@ class InovelliBindingOffToOnSyncLevel(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliLocalProtection(ConfigurableAttributeSwitch): """Inovelli local protection control.""" @@ -784,7 +784,7 @@ class InovelliLocalProtection(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliOnOffLEDMode(ConfigurableAttributeSwitch): """Inovelli only 1 LED mode control.""" @@ -799,7 +799,7 @@ class InovelliOnOffLEDMode(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliFirmwareProgressLED(ConfigurableAttributeSwitch): """Inovelli firmware progress LED control.""" @@ -814,7 +814,7 @@ class InovelliFirmwareProgressLED(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliRelayClickInOnOffMode(ConfigurableAttributeSwitch): """Inovelli relay click in on off mode control.""" @@ -829,7 +829,7 @@ class InovelliRelayClickInOnOffMode(ConfigurableAttributeSwitch): ) -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliDisableDoubleTapClearNotificationsMode(ConfigurableAttributeSwitch): """Inovelli disable clear notifications double tap control.""" @@ -844,7 +844,7 @@ class InovelliDisableDoubleTapClearNotificationsMode(ConfigurableAttributeSwitch ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederLEDIndicator(ConfigurableAttributeSwitch): """Representation of a LED indicator configuration entity.""" @@ -860,7 +860,7 @@ class AqaraPetFeederLEDIndicator(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPetFeederChildLock(ConfigurableAttributeSwitch): """Representation of a child lock configuration entity.""" @@ -875,7 +875,7 @@ class AqaraPetFeederChildLock(ConfigurableAttributeSwitch): ) -@register_entity(OnOff.cluster_id) +@register_entity class TuyaChildLockSwitch(ConfigurableAttributeSwitch): """Representation of a child lock configuration entity.""" @@ -899,7 +899,7 @@ class TuyaChildLockSwitch(ConfigurableAttributeSwitch): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatWindowDetection(ConfigurableAttributeSwitch): """Representation of an Aqara thermostat window detection configuration entity.""" @@ -914,7 +914,7 @@ class AqaraThermostatWindowDetection(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatValveDetection(ConfigurableAttributeSwitch): """Representation of an Aqara thermostat valve detection configuration entity.""" @@ -929,7 +929,7 @@ class AqaraThermostatValveDetection(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatChildLock(ConfigurableAttributeSwitch): """Representation of an Aqara thermostat child lock configuration entity.""" @@ -944,7 +944,7 @@ class AqaraThermostatChildLock(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraHeartbeatIndicator(ConfigurableAttributeSwitch): """Representation of a heartbeat indicator configuration entity for Aqara smoke sensors.""" @@ -959,7 +959,7 @@ class AqaraHeartbeatIndicator(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraLinkageAlarm(ConfigurableAttributeSwitch): """Representation of a linkage alarm configuration entity for Aqara smoke sensors.""" @@ -974,7 +974,7 @@ class AqaraLinkageAlarm(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraBuzzerManualMute(ConfigurableAttributeSwitch): """Representation of a buzzer manual mute configuration entity for Aqara smoke sensors.""" @@ -989,7 +989,7 @@ class AqaraBuzzerManualMute(ConfigurableAttributeSwitch): ) -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraBuzzerManualAlarm(ConfigurableAttributeSwitch): """Representation of a buzzer manual mute configuration entity for Aqara smoke sensors.""" @@ -1004,7 +1004,7 @@ class AqaraBuzzerManualAlarm(ConfigurableAttributeSwitch): ) -@register_entity(WindowCovering.cluster_id) +@register_entity class WindowCoveringInversionSwitch(ConfigurableAttributeSwitch): """Representation of a switch that controls inversion for window covering devices. @@ -1098,7 +1098,7 @@ async def _async_on_off(self, invert: bool) -> None: await self.async_update() -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraE1CurtainMotorHooksLockedSwitch(ConfigurableAttributeSwitch): """Representation of a switch that controls whether the curtain motor hooks are locked.""" @@ -1113,7 +1113,7 @@ class AqaraE1CurtainMotorHooksLockedSwitch(ConfigurableAttributeSwitch): ) -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossExternalOpenWindowDetected(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for communicating an open window.""" @@ -1138,7 +1138,7 @@ class DanfossExternalOpenWindowDetected(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossWindowOpenFeature(ConfigurableAttributeSwitch): """Danfoss proprietary attribute enabling open window detection.""" @@ -1163,7 +1163,7 @@ class DanfossWindowOpenFeature(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossMountingModeControl(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for switching to mounting mode.""" @@ -1188,7 +1188,7 @@ class DanfossMountingModeControl(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossRadiatorCovered(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for communicating full usage of the external temperature sensor.""" @@ -1213,7 +1213,7 @@ class DanfossRadiatorCovered(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossHeatAvailable(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for communicating available heat.""" @@ -1238,7 +1238,7 @@ class DanfossHeatAvailable(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossLoadBalancingEnable(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for enabling load balancing.""" @@ -1263,7 +1263,7 @@ class DanfossLoadBalancingEnable(ConfigurableAttributeSwitch): } -@register_entity(Thermostat.cluster_id) +@register_entity class DanfossAdaptationRunSettings(ConfigurableAttributeSwitch): """Danfoss proprietary attribute for enabling daily adaptation run. @@ -1291,7 +1291,7 @@ class DanfossAdaptationRunSettings(ConfigurableAttributeSwitch): } -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeLightDoubleTapFullSwitch(ConfigurableAttributeSwitch): """Representation of a config option that controls whether Double Tap Full option is enabled on a Sinope light switch.""" diff --git a/zha/application/platforms/update.py b/zha/application/platforms/update.py index cc7ce0a92..aedf5f776 100644 --- a/zha/application/platforms/update.py +++ b/zha/application/platforms/update.py @@ -287,7 +287,7 @@ async def on_remove(self) -> None: await super().on_remove() -@register_entity(Ota.cluster_id) +@register_entity class FirmwareUpdateEntity(BaseFirmwareUpdateEntity): """Representation of a ZHA firmware update entity.""" @@ -357,7 +357,7 @@ def _get_cluster_version(self) -> str | None: return None -@register_entity(Ota.cluster_id) +@register_entity class FirmwareUpdateServerEntity(FirmwareUpdateEntity): """Representation of a ZHA firmware update entity for devices exposing OTA as a server cluster.""" diff --git a/zha/application/platforms/virtual.py b/zha/application/platforms/virtual.py index 4585ca960..5db0d0fe8 100644 --- a/zha/application/platforms/virtual.py +++ b/zha/application/platforms/virtual.py @@ -117,7 +117,7 @@ def emit_cluster_zha_event( ) -@register_entity(IasZone.cluster_id) +@register_entity class IasZoneEnrollment(VirtualEntity): """Drives the IAS Zone enrollment handshake. @@ -183,7 +183,7 @@ def cluster_command(self, tsn: int, command_id: int, args: list[Any]) -> None: ) -@register_entity(LightLink.cluster_id) +@register_entity class LightLinkGroupJoin(VirtualEntity): """Adds the coordinator to the device's LightLink groups.""" @@ -225,7 +225,7 @@ async def async_configure_cluster(self, cluster: zigpy.zcl.Cluster) -> None: await coordinator.add_to_group(0x0000, name="Lightlink Group") -@register_entity(OnOff.cluster_id) +@register_entity class OnOffClientCacheSync(VirtualEntity): """Mirrors incoming OnOff client commands to the server attribute cache. @@ -366,7 +366,7 @@ def handle_attribute_updated( ) -@register_entity(Scenes.cluster_id) +@register_entity class ScenesClientBind(_ClientClusterZhaEventEmitter): """Bind the Scenes client cluster and emit zha_events for its commands.""" @@ -381,7 +381,7 @@ class ScenesClientBind(_ClientClusterZhaEventEmitter): } -@register_entity(LevelControl.cluster_id) +@register_entity class LevelControlClientBind(_ClientClusterZhaEventEmitter): """Bind LevelControl client cluster and emit zha_events for its commands.""" @@ -397,7 +397,7 @@ class LevelControlClientBind(_ClientClusterZhaEventEmitter): } -@register_entity(Color.cluster_id) +@register_entity class ColorClientBind(_ClientClusterZhaEventEmitter): """Bind the Color client cluster and emit zha_events for its commands.""" @@ -412,7 +412,7 @@ class ColorClientBind(_ClientClusterZhaEventEmitter): } -@register_entity(WindowCovering.cluster_id) +@register_entity class WindowCoveringClientBind(_ClientClusterZhaEventEmitter): """Bind WindowCovering client cluster and emit zha_events for its commands.""" @@ -427,7 +427,7 @@ class WindowCoveringClientBind(_ClientClusterZhaEventEmitter): } -@register_entity(PHILIPS_REMOTE_CLUSTER) +@register_entity class PhilipsRemoteBind(VirtualEntity): """Bind the Philips remote cluster on every device that exposes it.""" @@ -441,7 +441,7 @@ class PhilipsRemoteBind(VirtualEntity): } -@register_entity(OSRAM_CLUSTER) +@register_entity class OsramClusterBind(VirtualEntity): """Bind the Osram manufacturer cluster on every device that exposes it.""" @@ -455,7 +455,7 @@ class OsramClusterBind(VirtualEntity): } -@register_entity(Ota.cluster_id) +@register_entity class OtaCurrentFileVersionCache(VirtualEntity): """Updates `current_file_version` on every query_next_image from the device.""" @@ -480,7 +480,7 @@ def cluster_command(self, tsn: int, command_id: int, args: list[Any]) -> None: ) -@register_entity(DoorLock.cluster_id) +@register_entity class DoorLockOperationEvent(VirtualEntity): """Emits zha_event for DoorLock operation_event_notification commands.""" @@ -516,7 +516,7 @@ def cluster_command(self, tsn: int, command_id: int, args: list[Any]) -> None: ) -@register_entity(SMARTTHINGS_ACCELERATION_CLUSTER) +@register_entity class SmartThingsAccelerationEvent(VirtualEntity): """Emits a zha_event for every attribute update on the SmartThings accel cluster.""" @@ -549,7 +549,7 @@ def handle_attribute_updated( ) -@register_entity(Identify.cluster_id) +@register_entity class IdentifyTriggerEffectEvent(VirtualEntity): """Emits a zha_event when the device sends `trigger_effect`.""" @@ -590,7 +590,7 @@ class _AqaraOppleInitBase(VirtualEntity): _unique_id_suffix = "aqara_opple_init" -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraOppleBind(VirtualEntity): """Bind the Aqara Opple cluster on every device that exposes it.""" @@ -604,7 +604,7 @@ class AqaraOppleBind(VirtualEntity): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionAc02Init(_AqaraOppleInitBase): """Aqara P1 motion sensor attribute init.""" @@ -623,7 +623,7 @@ class AqaraMotionAc02Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionAgl04Init(_AqaraOppleInitBase): """Aqara high-precision motion sensor attribute init.""" @@ -641,7 +641,7 @@ class AqaraMotionAgl04Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionAc01Init(_AqaraOppleInitBase): """Aqara FP1 presence sensor attribute init.""" @@ -661,7 +661,7 @@ class AqaraMotionAc01Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraPlugInit(_AqaraOppleInitBase): """Aqara EU plug attribute init.""" @@ -679,7 +679,7 @@ class AqaraPlugInit(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraFeederInit(_AqaraOppleInitBase): """Aqara pet feeder attribute init.""" @@ -703,7 +703,7 @@ class AqaraFeederInit(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraThermostatAgl001Init(_AqaraOppleInitBase): """Aqara E1 radiator thermostat attribute init.""" @@ -730,7 +730,7 @@ class AqaraThermostatAgl001Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraSmokeAcn03Init(_AqaraOppleInitBase): """Aqara smoke sensor attribute init.""" @@ -752,7 +752,7 @@ class AqaraSmokeAcn03Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMagnetAc01Init(_AqaraOppleInitBase): """Aqara P1 door sensor attribute init.""" @@ -769,7 +769,7 @@ class AqaraMagnetAc01Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraSwitchAcn047Init(_AqaraOppleInitBase): """Aqara H1M wall switch attribute init.""" @@ -789,7 +789,7 @@ class AqaraSwitchAcn047Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraCurtainAgl001Init(_AqaraOppleInitBase): """Aqara E1 curtain motor attribute init.""" @@ -810,7 +810,7 @@ class AqaraCurtainAgl001Init(_AqaraOppleInitBase): } -@register_entity(AQARA_OPPLE_CLUSTER) +@register_entity class AqaraMotionDetectionIntervalSync(_AqaraOppleInitBase): """Propagate the Aqara motion sensor's `detection_interval` to `ias_zone.reset_s`. @@ -847,7 +847,7 @@ async def async_initialize_cluster(self, cluster: zigpy.zcl.Cluster) -> None: # === Other manufacturer-specific clusters === -@register_entity(SONOFF_CLUSTER) +@register_entity class SonoffManufacturerBind(VirtualEntity): """Bind the Sonoff manufacturer cluster on every device that exposes it.""" @@ -861,7 +861,7 @@ class SonoffManufacturerBind(VirtualEntity): } -@register_entity(SONOFF_CLUSTER) +@register_entity class SonoffPresenceSensorInit(VirtualEntity): """Sonoff SNZB-06P presence sensor attribute init.""" @@ -880,7 +880,7 @@ class SonoffPresenceSensorInit(VirtualEntity): } -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class TuyaManufacturerBind(VirtualEntity): """Bind the Tuya manufacturer cluster on every device that exposes it.""" @@ -894,7 +894,7 @@ class TuyaManufacturerBind(VirtualEntity): } -@register_entity(TUYA_MANUFACTURER_CLUSTER) +@register_entity class TuyaPlugManufacturerInit(VirtualEntity): """Tuya plug manufacturer-cluster attribute init.""" @@ -914,7 +914,7 @@ class TuyaPlugManufacturerInit(VirtualEntity): } -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeManufacturerBind(VirtualEntity): """Bind the Sinope manufacturer cluster on every device that exposes it.""" @@ -928,7 +928,7 @@ class SinopeManufacturerBind(VirtualEntity): } -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeSwitchInit(VirtualEntity): """Sinope SW2500/DM2500/DM2550 manufacturer-cluster init + reporting.""" @@ -967,7 +967,7 @@ class SinopeSwitchInit(VirtualEntity): } -@register_entity(SINOPE_MANUFACTURER_CLUSTER) +@register_entity class SinopeDimmerInit(VirtualEntity): """Extra Sinope dimmer attribute (DM2500/DM2550 only).""" @@ -986,7 +986,7 @@ class SinopeDimmerInit(VirtualEntity): } -@register_entity(IKEA_REMOTE_CLUSTER) +@register_entity class IkeaRemoteClientBind(VirtualEntity): """Bind the IKEA remote client cluster on every device that exposes it. @@ -1005,7 +1005,7 @@ class IkeaRemoteClientBind(VirtualEntity): } -@register_entity(IKEA_REMOTE_CLUSTER) +@register_entity class IkeaRemoteServerBind(VirtualEntity): """Bind the IKEA remote server cluster on every device that exposes it.""" @@ -1020,7 +1020,7 @@ class IkeaRemoteServerBind(VirtualEntity): } -@register_entity(IKEA_SHORTCUT_V1_CLUSTER) +@register_entity class IkeaSymfoniskRemoteClientBind(VirtualEntity): """Bind the IKEA Symfonisk shortcut v1 client cluster.""" @@ -1035,7 +1035,7 @@ class IkeaSymfoniskRemoteClientBind(VirtualEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliBind(VirtualEntity): """Bind the Inovelli manufacturer cluster on every device that exposes it.""" @@ -1049,7 +1049,7 @@ class InovelliBind(VirtualEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliClientBind(VirtualEntity): """Bind the Inovelli manufacturer client cluster on every device that exposes it.""" @@ -1063,7 +1063,7 @@ class InovelliClientBind(VirtualEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliVzm30Init(VirtualEntity): """Inovelli VZM30-SN switch attribute init.""" @@ -1120,7 +1120,7 @@ class InovelliVzm30Init(VirtualEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliVzm31Init(VirtualEntity): """Inovelli VZM31-SN dimmer attribute init.""" @@ -1187,7 +1187,7 @@ class InovelliVzm31Init(VirtualEntity): } -@register_entity(INOVELLI_CLUSTER) +@register_entity class InovelliVzm35Init(VirtualEntity): """Inovelli VZM35-SN fan switch attribute init."""