diff --git a/zha/application/discovery.py b/zha/application/discovery.py index 806f87b90..50f4109f2 100644 --- a/zha/application/discovery.py +++ b/zha/application/discovery.py @@ -90,6 +90,7 @@ Platform.CLIMATE, Platform.COVER, Platform.DEVICE_TRACKER, + Platform.EVENT, Platform.FAN, Platform.LIGHT, Platform.LOCK, diff --git a/zha/application/platforms/event/__init__.py b/zha/application/platforms/event/__init__.py new file mode 100644 index 000000000..92188dc5d --- /dev/null +++ b/zha/application/platforms/event/__init__.py @@ -0,0 +1,65 @@ +"""Support for the ZHA event platform.""" + +from __future__ import annotations + +import dataclasses +import functools +import logging +from typing import Any, Final + +from zigpy.quirks.v2 import EventMetadata + +from zha.application import Platform +from zha.application.platforms import PlatformEntity +from zha.application.platforms.helpers import validate_device_class + +from .const import EventDeviceClass + +_LOGGER = logging.getLogger(__name__) + + +@dataclasses.dataclass(frozen=True, kw_only=True) +class EventPlatformEvent: + """Event for the event platform trigger.""" + + event: Final[str] = "trigger_event" + event_type: str + event_attributes: dict[str, Any] | None + + +class EventEntity(PlatformEntity): + """Represent an event entity.""" + + PLATFORM = Platform.EVENT + _attr_event_types: tuple[str] = () + + def _init_from_quirks_metadata(self, entity_metadata: EventMetadata) -> None: + """Init this entity from the quirks metadata.""" + super()._init_from_quirks_metadata(entity_metadata) + + self._attr_event_types = entity_metadata.event_types + + if entity_metadata.device_class is not None: + self._attr_device_class = validate_device_class( + EventDeviceClass, + entity_metadata.device_class, + Platform.EVENT.value, + _LOGGER, + ) + + @functools.cached_property + def event_types(self) -> list[str]: + """Return a list of possible events.""" + return list(self._attr_event_types) + + def trigger_event( + self, event_type: str, event_attributes: dict[str, Any] | None = None + ) -> None: + """Trigger an event.""" + self.emit( + EventPlatformEvent.event_type, + EventPlatformEvent( + event_type=event_type, + event_attributes=event_attributes, + ), + ) diff --git a/zha/application/platforms/event/const.py b/zha/application/platforms/event/const.py new file mode 100644 index 000000000..281dd5491 --- /dev/null +++ b/zha/application/platforms/event/const.py @@ -0,0 +1,11 @@ +"""Constants for the ZHA event platform.""" + +from enum import StrEnum + + +class EventDeviceClass(StrEnum): + """Device class for event entities.""" + + DOORBELL = "doorbell" + BUTTON = "button" + MOTION = "motion" diff --git a/zha/application/platforms/helpers.py b/zha/application/platforms/helpers.py index adc3086df..1e50fa156 100644 --- a/zha/application/platforms/helpers.py +++ b/zha/application/platforms/helpers.py @@ -9,6 +9,7 @@ if TYPE_CHECKING: from zha.application.platforms.binary_sensor.const import BinarySensorDeviceClass + from zha.application.platforms.event.const import EventDeviceClass from zha.application.platforms.number.const import NumberDeviceClass from zha.application.platforms.sensor.const import SensorDeviceClass @@ -78,16 +79,32 @@ def validate_device_class( ) -> NumberDeviceClass | None: ... +@overload +def validate_device_class( + device_class_enum: type[EventDeviceClass], + metadata_value: enum.Enum, + platform: str, + logger: logging.Logger, +) -> EventDeviceClass | None: ... + + def validate_device_class( device_class_enum: ( type[BinarySensorDeviceClass] | type[SensorDeviceClass] | type[NumberDeviceClass] + | type[EventDeviceClass] ), metadata_value: enum.Enum, platform: str, logger: logging.Logger, -) -> BinarySensorDeviceClass | SensorDeviceClass | NumberDeviceClass | None: +) -> ( + BinarySensorDeviceClass + | SensorDeviceClass + | NumberDeviceClass + | EventDeviceClass + | None +): """Validate and return a device class.""" try: return device_class_enum(metadata_value.value)