diff --git a/homeassistant/components/zha/core/channels/general.py b/homeassistant/components/zha/core/channels/general.py index f5dbab9e38e..ded51455af8 100644 --- a/homeassistant/components/zha/core/channels/general.py +++ b/homeassistant/components/zha/core/channels/general.py @@ -28,6 +28,7 @@ from ..const import ( SIGNAL_UPDATE_DEVICE, ) from .base import AttrReportConfig, ClientChannel, ZigbeeChannel, parse_and_log_command +from .helpers import is_hue_motion_sensor if TYPE_CHECKING: from . import ChannelPool @@ -152,6 +153,15 @@ class BasicChannel(ZigbeeChannel): 6: "Emergency mains and transfer switch", } + def __init__(self, cluster: zigpy.zcl.Cluster, ch_pool: ChannelPool) -> None: + """Initialize Basic channel.""" + super().__init__(cluster, ch_pool) + if is_hue_motion_sensor(self): + self.ZCL_INIT_ATTRS = ( # pylint: disable=invalid-name + self.ZCL_INIT_ATTRS.copy() + ) + self.ZCL_INIT_ATTRS["trigger_indicator"] = True + @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryInput.cluster_id) class BinaryInput(ZigbeeChannel): diff --git a/homeassistant/components/zha/core/channels/helpers.py b/homeassistant/components/zha/core/channels/helpers.py new file mode 100644 index 00000000000..2297af312eb --- /dev/null +++ b/homeassistant/components/zha/core/channels/helpers.py @@ -0,0 +1,15 @@ +"""Helpers for use with ZHA Zigbee channels.""" +from .base import ZigbeeChannel + + +def is_hue_motion_sensor(channel: ZigbeeChannel) -> bool: + """Return true if the manufacturer and model match known Hue motion sensor models.""" + return channel.cluster.endpoint.manufacturer in ( + "Philips", + "Signify Netherlands B.V.", + ) and channel.cluster.endpoint.model in ( + "SML001", + "SML002", + "SML003", + "SML004", + ) diff --git a/homeassistant/components/zha/core/channels/measurement.py b/homeassistant/components/zha/core/channels/measurement.py index fa6f9c07dee..be61a75962e 100644 --- a/homeassistant/components/zha/core/channels/measurement.py +++ b/homeassistant/components/zha/core/channels/measurement.py @@ -1,4 +1,9 @@ """Measurement channels module for Zigbee Home Automation.""" +from __future__ import annotations + +from typing import TYPE_CHECKING + +import zigpy.zcl from zigpy.zcl.clusters import measurement from .. import registries @@ -9,6 +14,10 @@ from ..const import ( REPORT_CONFIG_MIN_INT, ) from .base import AttrReportConfig, ZigbeeChannel +from .helpers import is_hue_motion_sensor + +if TYPE_CHECKING: + from . import ChannelPool @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.FlowMeasurement.cluster_id) @@ -50,6 +59,15 @@ class OccupancySensing(ZigbeeChannel): AttrReportConfig(attr="occupancy", config=REPORT_CONFIG_IMMEDIATE), ) + def __init__(self, cluster: zigpy.zcl.Cluster, ch_pool: ChannelPool) -> None: + """Initialize Occupancy channel.""" + super().__init__(cluster, ch_pool) + if is_hue_motion_sensor(self): + self.ZCL_INIT_ATTRS = ( # pylint: disable=invalid-name + self.ZCL_INIT_ATTRS.copy() + ) + self.ZCL_INIT_ATTRS["sensitivity"] = True + @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.PressureMeasurement.cluster_id) class PressureMeasurement(ZigbeeChannel): diff --git a/homeassistant/components/zha/select.py b/homeassistant/components/zha/select.py index 35746951b47..38f2f417643 100644 --- a/homeassistant/components/zha/select.py +++ b/homeassistant/components/zha/select.py @@ -22,6 +22,7 @@ from .core import discovery from .core.const import ( CHANNEL_IAS_WD, CHANNEL_INOVELLI, + CHANNEL_OCCUPANCY, CHANNEL_ON_OFF, DATA_ZHA, SIGNAL_ADD_ENTITIES, @@ -259,13 +260,57 @@ class AqaraMotionSensitivities(types.enum8): channel_names="opple_cluster", models={"lumi.motion.ac01", "lumi.motion.ac02"} ) class AqaraMotionSensitivity(ZCLEnumSelectEntity, id_suffix="motion_sensitivity"): - """Representation of a ZHA on off transition time configuration entity.""" + """Representation of a ZHA motion sensitivity configuration entity.""" _select_attr = "motion_sensitivity" _enum = AqaraMotionSensitivities _attr_name = "Motion sensitivity" +class HueV1MotionSensitivities(types.enum8): + """Hue v1 motion sensitivities.""" + + Low = 0x00 + Medium = 0x01 + High = 0x02 + + +@CONFIG_DIAGNOSTIC_MATCH( + channel_names=CHANNEL_OCCUPANCY, + manufacturers={"Philips", "Signify Netherlands B.V."}, + models={"SML001"}, +) +class HueV1MotionSensitivity(ZCLEnumSelectEntity, id_suffix="motion_sensitivity"): + """Representation of a ZHA motion sensitivity configuration entity.""" + + _select_attr = "sensitivity" + _attr_name = "Hue motion sensitivity" + _enum = HueV1MotionSensitivities + + +class HueV2MotionSensitivities(types.enum8): + """Hue v2 motion sensitivities.""" + + Lowest = 0x00 + Low = 0x01 + Medium = 0x02 + High = 0x03 + Highest = 0x04 + + +@CONFIG_DIAGNOSTIC_MATCH( + channel_names=CHANNEL_OCCUPANCY, + manufacturers={"Philips", "Signify Netherlands B.V."}, + models={"SML002", "SML003", "SML004"}, +) +class HueV2MotionSensitivity(ZCLEnumSelectEntity, id_suffix="motion_sensitivity"): + """Representation of a ZHA motion sensitivity configuration entity.""" + + _select_attr = "sensitivity" + _attr_name = "Hue motion sensitivity" + _enum = HueV2MotionSensitivities + + class AqaraMonitoringModess(types.enum8): """Aqara monitoring modes.""" diff --git a/homeassistant/components/zha/switch.py b/homeassistant/components/zha/switch.py index e2c956e0722..0bd55cdbe68 100644 --- a/homeassistant/components/zha/switch.py +++ b/homeassistant/components/zha/switch.py @@ -19,6 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from .core import discovery from .core.const import ( + CHANNEL_BASIC, CHANNEL_INOVELLI, CHANNEL_ON_OFF, DATA_ZHA, @@ -305,6 +306,20 @@ class XiaomiPlugPowerOutageMemorySwitch( _attr_name = "Power outage memory" +@CONFIG_DIAGNOSTIC_MATCH( + channel_names=CHANNEL_BASIC, + manufacturers={"Philips", "Signify Netherlands B.V."}, + models={"SML001", "SML002", "SML003", "SML004"}, +) +class HueMotionTriggerIndicatorSwitch( + ZHASwitchConfigurationEntity, id_suffix="trigger_indicator" +): + """Representation of a ZHA motion triggering configuration entity.""" + + _zcl_attribute: str = "trigger_indicator" + _attr_name = "LED trigger indicator" + + @CONFIG_DIAGNOSTIC_MATCH( channel_names="ikea_airpurifier", models={"STARKVIND Air purifier", "STARKVIND Air purifier table"},