Add additional entities for the Aqara E1 curtain motor to ZHA (#108243)

* aqara curtain motor opened by hand binary sensor

add icon and translation key for identify button

remove previous inversion entity

add window covering type sensor and aqara curtain motor sensors

add aqara curtain motor hook lock switch

add aqara curtain motor attributes zcl_init_attrs

add aqara curtain motor zcl_init_attrs

translations

* update translation string

* review comments

* use enum sensor after rebase

* remove button change
This commit is contained in:
David F. Mulcahey 2024-01-30 22:40:33 -05:00 committed by GitHub
parent 3115af1041
commit ac8f555a70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 107 additions and 20 deletions

View File

@ -74,7 +74,7 @@ class BinarySensor(ZhaEntity, BinarySensorEntity):
_attribute_name: str
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs) -> None:
"""Initialize the ZHA binary sensor."""
super().__init__(unique_id, zha_device, cluster_handlers, **kwargs)
self._cluster_handler = cluster_handlers[0]
@ -336,3 +336,16 @@ class AqaraLinkageAlarmState(BinarySensor):
_unique_id_suffix = "linkage_alarm_state"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.SMOKE
_attr_translation_key: str = "linkage_alarm_state"
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names="opple_cluster", models={"lumi.curtain.agl001"}
)
class AqaraE1CurtainMotorOpenedByHandBinarySensor(BinarySensor):
"""Opened by hand binary sensor."""
_unique_id_suffix = "hand_open"
_attribute_name = "hand_open"
_attr_translation_key = "hand_open"
_attr_icon = "mdi:hand-wave"
_attr_entity_category = EntityCategory.DIAGNOSTIC

View File

@ -203,6 +203,9 @@ class BasicClusterHandler(ClusterHandler):
):
self.ZCL_INIT_ATTRS = self.ZCL_INIT_ATTRS.copy()
self.ZCL_INIT_ATTRS["transmit_power"] = True
elif self.cluster.endpoint.model == "lumi.curtain.agl001":
self.ZCL_INIT_ATTRS = self.ZCL_INIT_ATTRS.copy()
self.ZCL_INIT_ATTRS["power_source"] = True
@registries.ZIGBEE_CLUSTER_HANDLER_REGISTRY.register(BinaryInput.cluster_id)

View File

@ -160,6 +160,14 @@ class OppleRemoteClusterHandler(ClusterHandler):
"startup_on_off": True,
"decoupled_mode": True,
}
elif self.cluster.endpoint.model == "lumi.curtain.agl001":
self.ZCL_INIT_ATTRS = {
"hooks_state": True,
"hooks_lock": True,
"positions_stored": True,
"light_level": True,
"hand_open": True,
}
async def async_initialize_cluster_handler_specific(self, from_cache: bool) -> None:
"""Initialize cluster handler specific."""

View File

@ -471,25 +471,6 @@ class AqaraT2RelayDecoupledMode(ZCLEnumSelectEntity):
_attr_translation_key: str = "decoupled_mode"
class AqaraE1ReverseDirection(types.enum8):
"""Aqara curtain reversal."""
Normal = 0x00
Inverted = 0x01
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names="window_covering", models={"lumi.curtain.agl001"}
)
class AqaraCurtainMode(ZCLEnumSelectEntity):
"""Representation of a ZHA curtain mode configuration entity."""
_unique_id_suffix = "window_covering_mode"
_attribute_name = "window_covering_mode"
_enum = AqaraE1ReverseDirection
_attr_translation_key: str = "window_covering_mode"
class InovelliOutputMode(types.enum1):
"""Inovelli output mode."""

View File

@ -10,6 +10,8 @@ import random
from typing import TYPE_CHECKING, Any, Self
from zigpy import types
from zigpy.zcl.clusters.closures import WindowCovering
from zigpy.zcl.clusters.general import Basic
from homeassistant.components.climate import HVACAction
from homeassistant.components.sensor import (
@ -51,6 +53,7 @@ from .core import discovery
from .core.const import (
CLUSTER_HANDLER_ANALOG_INPUT,
CLUSTER_HANDLER_BASIC,
CLUSTER_HANDLER_COVER,
CLUSTER_HANDLER_DEVICE_TEMPERATURE,
CLUSTER_HANDLER_ELECTRICAL_MEASUREMENT,
CLUSTER_HANDLER_HUMIDITY,
@ -1312,3 +1315,55 @@ class SetpointChangeSource(EnumSensor):
_attr_icon: str = "mdi:thermostat"
_attr_entity_category = EntityCategory.DIAGNOSTIC
_enum = SetpointChangeSourceEnum
@CONFIG_DIAGNOSTIC_MATCH(cluster_handler_names=CLUSTER_HANDLER_COVER)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class WindowCoveringTypeSensor(EnumSensor):
"""Sensor that displays the type of a cover device."""
_attribute_name: str = WindowCovering.AttributeDefs.window_covering_type.name
_enum = WindowCovering.WindowCoveringType
_unique_id_suffix: str = WindowCovering.AttributeDefs.window_covering_type.name
_attr_translation_key: str = WindowCovering.AttributeDefs.window_covering_type.name
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_icon = "mdi:curtains"
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names=CLUSTER_HANDLER_BASIC, models={"lumi.curtain.agl001"}
)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class AqaraCurtainMotorPowerSourceSensor(EnumSensor):
"""Sensor that displays the power source of the Aqara E1 curtain motor device."""
_attribute_name: str = Basic.AttributeDefs.power_source.name
_enum = Basic.PowerSource
_unique_id_suffix: str = Basic.AttributeDefs.power_source.name
_attr_translation_key: str = Basic.AttributeDefs.power_source.name
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_icon = "mdi:battery-positive"
class AqaraE1HookState(types.enum8):
"""Aqara hook state."""
Unlocked = 0x00
Locked = 0x01
Locking = 0x02
Unlocking = 0x03
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names="opple_cluster", models={"lumi.curtain.agl001"}
)
# pylint: disable-next=hass-invalid-inheritance # needs fixing
class AqaraCurtainHookStateSensor(EnumSensor):
"""Representation of a ZHA curtain mode configuration entity."""
_attribute_name = "hooks_state"
_enum = AqaraE1HookState
_unique_id_suffix = "hooks_state"
_attr_translation_key: str = "hooks_state"
_attr_icon: str = "mdi:hook"
_attr_entity_category = EntityCategory.DIAGNOSTIC

View File

@ -566,6 +566,9 @@
},
"ias_zone": {
"name": "IAS zone"
},
"hand_open": {
"name": "Opened by hand"
}
},
"button": {
@ -896,6 +899,15 @@
},
"setpoint_change_source": {
"name": "Setpoint change source"
},
"power_source": {
"name": "Power source"
},
"window_covering_type": {
"name": "Window covering type"
},
"hooks_state": {
"name": "Hooks state"
}
},
"switch": {
@ -923,6 +935,9 @@
"inverted": {
"name": "Inverted"
},
"hooks_locked": {
"name": "Hooks locked"
},
"smart_bulb_mode": {
"name": "Smart bulb mode"
},

View File

@ -685,3 +685,15 @@ class WindowCoveringInversionSwitch(ZHASwitchConfigurationEntity):
if send_command:
await self._cluster_handler.write_attributes_safe({name: current_mode})
await self.async_update()
@CONFIG_DIAGNOSTIC_MATCH(
cluster_handler_names="opple_cluster", models={"lumi.curtain.agl001"}
)
class AqaraE1CurtainMotorHooksLockedSwitch(ZHASwitchConfigurationEntity):
"""Representation of a switch that controls whether the curtain motor hooks are locked."""
_unique_id_suffix = "hooks_lock"
_attribute_name = "hooks_lock"
_attr_translation_key = "hooks_locked"
_attr_icon: str = "mdi:lock"