1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/zha/siren.py
epenet f43cc18aa3
Fix type hints in zha platforms (#73745)
* Adjust binary_sensor

* Adjust device_action

* Adjust device_tracker

* Adjust fan

* Adjust lock

* Adjust siren
2022-06-20 11:31:16 -04:00

166 lines
5.6 KiB
Python

"""Support for ZHA sirens."""
from __future__ import annotations
from collections.abc import Callable
import functools
from typing import TYPE_CHECKING, Any, cast
from zigpy.zcl.clusters.security import IasWd as WD
from homeassistant.components.siren import (
ATTR_DURATION,
SirenEntity,
SirenEntityFeature,
)
from homeassistant.components.siren.const import ATTR_TONE, ATTR_VOLUME_LEVEL
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_call_later
from .core import discovery
from .core.channels.security import IasWd
from .core.const import (
CHANNEL_IAS_WD,
DATA_ZHA,
SIGNAL_ADD_ENTITIES,
WARNING_DEVICE_MODE_BURGLAR,
WARNING_DEVICE_MODE_EMERGENCY,
WARNING_DEVICE_MODE_EMERGENCY_PANIC,
WARNING_DEVICE_MODE_FIRE,
WARNING_DEVICE_MODE_FIRE_PANIC,
WARNING_DEVICE_MODE_POLICE_PANIC,
WARNING_DEVICE_MODE_STOP,
WARNING_DEVICE_SOUND_HIGH,
WARNING_DEVICE_STROBE_HIGH,
WARNING_DEVICE_STROBE_NO,
Strobe,
)
from .core.registries import ZHA_ENTITIES
from .entity import ZhaEntity
if TYPE_CHECKING:
from .core.channels.base import ZigbeeChannel
from .core.device import ZHADevice
MULTI_MATCH = functools.partial(ZHA_ENTITIES.multipass_match, Platform.SIREN)
DEFAULT_DURATION = 5 # seconds
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Zigbee Home Automation siren from config entry."""
entities_to_create = hass.data[DATA_ZHA][Platform.SIREN]
unsub = async_dispatcher_connect(
hass,
SIGNAL_ADD_ENTITIES,
functools.partial(
discovery.async_add_entities,
async_add_entities,
entities_to_create,
),
)
config_entry.async_on_unload(unsub)
@MULTI_MATCH(channel_names=CHANNEL_IAS_WD)
class ZHASiren(ZhaEntity, SirenEntity):
"""Representation of a ZHA siren."""
def __init__(
self,
unique_id: str,
zha_device: ZHADevice,
channels: list[ZigbeeChannel],
**kwargs,
) -> None:
"""Init this siren."""
self._attr_supported_features = (
SirenEntityFeature.TURN_ON
| SirenEntityFeature.TURN_OFF
| SirenEntityFeature.DURATION
| SirenEntityFeature.VOLUME_SET
| SirenEntityFeature.TONES
)
self._attr_available_tones: list[int | str] | dict[int, str] | None = {
WARNING_DEVICE_MODE_BURGLAR: "Burglar",
WARNING_DEVICE_MODE_FIRE: "Fire",
WARNING_DEVICE_MODE_EMERGENCY: "Emergency",
WARNING_DEVICE_MODE_POLICE_PANIC: "Police Panic",
WARNING_DEVICE_MODE_FIRE_PANIC: "Fire Panic",
WARNING_DEVICE_MODE_EMERGENCY_PANIC: "Emergency Panic",
}
super().__init__(unique_id, zha_device, channels, **kwargs)
self._channel: IasWd = cast(IasWd, channels[0])
self._attr_is_on: bool = False
self._off_listener: Callable[[], None] | None = None
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on siren."""
if self._off_listener:
self._off_listener()
self._off_listener = None
tone_cache = self._channel.data_cache.get(WD.Warning.WarningMode.__name__)
siren_tone = (
tone_cache.value
if tone_cache is not None
else WARNING_DEVICE_MODE_EMERGENCY
)
siren_duration = DEFAULT_DURATION
level_cache = self._channel.data_cache.get(WD.Warning.SirenLevel.__name__)
siren_level = (
level_cache.value if level_cache is not None else WARNING_DEVICE_SOUND_HIGH
)
strobe_cache = self._channel.data_cache.get(Strobe.__name__)
should_strobe = (
strobe_cache.value if strobe_cache is not None else Strobe.No_Strobe
)
strobe_level_cache = self._channel.data_cache.get(WD.StrobeLevel.__name__)
strobe_level = (
strobe_level_cache.value
if strobe_level_cache is not None
else WARNING_DEVICE_STROBE_HIGH
)
if (duration := kwargs.get(ATTR_DURATION)) is not None:
siren_duration = duration
if (tone := kwargs.get(ATTR_TONE)) is not None:
siren_tone = tone
if (level := kwargs.get(ATTR_VOLUME_LEVEL)) is not None:
siren_level = int(level)
await self._channel.issue_start_warning(
mode=siren_tone,
warning_duration=siren_duration,
siren_level=siren_level,
strobe=should_strobe,
strobe_duty_cycle=50 if should_strobe else 0,
strobe_intensity=strobe_level,
)
self._attr_is_on = True
self._off_listener = async_call_later(
self._zha_device.hass, siren_duration, self.async_set_off
)
self.async_write_ha_state()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off siren."""
await self._channel.issue_start_warning(
mode=WARNING_DEVICE_MODE_STOP, strobe=WARNING_DEVICE_STROBE_NO
)
self._attr_is_on = False
self.async_write_ha_state()
@callback
def async_set_off(self, _) -> None:
"""Set is_on to False and write HA state."""
self._attr_is_on = False
if self._off_listener:
self._off_listener()
self._off_listener = None
self.async_write_ha_state()