171 lines
5.6 KiB
Python
171 lines
5.6 KiB
Python
"""Support for ZHA sirens."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import functools
|
|
from typing import Any
|
|
|
|
from zigpy.zcl.clusters.security import IasWd as WD
|
|
|
|
from homeassistant.components.siren import (
|
|
ATTR_DURATION,
|
|
SUPPORT_DURATION,
|
|
SUPPORT_TURN_OFF,
|
|
SUPPORT_TURN_ON,
|
|
SirenEntity,
|
|
)
|
|
from homeassistant.components.siren.const import (
|
|
ATTR_TONE,
|
|
ATTR_VOLUME_LEVEL,
|
|
SUPPORT_TONES,
|
|
SUPPORT_VOLUME_SET,
|
|
)
|
|
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 .core.typing import ChannelType, ZhaDeviceType
|
|
from .entity import ZhaEntity
|
|
|
|
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,
|
|
update_before_add=False,
|
|
),
|
|
)
|
|
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: ZhaDeviceType,
|
|
channels: list[ChannelType],
|
|
**kwargs,
|
|
) -> None:
|
|
"""Init this siren."""
|
|
self._attr_supported_features = (
|
|
SUPPORT_TURN_ON
|
|
| SUPPORT_TURN_OFF
|
|
| SUPPORT_DURATION
|
|
| SUPPORT_VOLUME_SET
|
|
| SUPPORT_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 = channels[0]
|
|
self._attr_is_on: bool = False
|
|
self._off_listener = 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()
|