From c792631f152395e079d4d0b382e5b1fc8a6732b0 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 5 Mar 2023 21:21:22 +0100 Subject: [PATCH] Add Reolink siren platform (#88217) Co-authored-by: Franck Nijhof Co-authored-by: Franck Nijhof --- .coveragerc | 1 + homeassistant/components/reolink/__init__.py | 1 + homeassistant/components/reolink/siren.py | 93 ++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 homeassistant/components/reolink/siren.py diff --git a/.coveragerc b/.coveragerc index 6ef51578a5c..69cd7bf4cab 100644 --- a/.coveragerc +++ b/.coveragerc @@ -982,6 +982,7 @@ omit = homeassistant/components/reolink/entity.py homeassistant/components/reolink/host.py homeassistant/components/reolink/number.py + homeassistant/components/reolink/siren.py homeassistant/components/reolink/switch.py homeassistant/components/reolink/update.py homeassistant/components/repetier/__init__.py diff --git a/homeassistant/components/reolink/__init__.py b/homeassistant/components/reolink/__init__.py index f6a5e197644..6bc2874285f 100644 --- a/homeassistant/components/reolink/__init__.py +++ b/homeassistant/components/reolink/__init__.py @@ -28,6 +28,7 @@ PLATFORMS = [ Platform.BUTTON, Platform.CAMERA, Platform.NUMBER, + Platform.SIREN, Platform.SWITCH, Platform.UPDATE, ] diff --git a/homeassistant/components/reolink/siren.py b/homeassistant/components/reolink/siren.py new file mode 100644 index 00000000000..f2b27dda4d1 --- /dev/null +++ b/homeassistant/components/reolink/siren.py @@ -0,0 +1,93 @@ +"""Component providing support for Reolink siren entities.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any + +from reolink_aio.api import Host + +from homeassistant.components.siren import ( + ATTR_DURATION, + ATTR_VOLUME_LEVEL, + SirenEntity, + SirenEntityDescription, + SirenEntityFeature, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import ReolinkData +from .const import DOMAIN +from .entity import ReolinkCoordinatorEntity + + +@dataclass +class ReolinkSirenEntityDescription(SirenEntityDescription): + """A class that describes siren entities.""" + + supported: Callable[[Host, int], bool] = lambda api, ch: True + + +SIREN_ENTITIES = ( + ReolinkSirenEntityDescription( + key="siren", + name="Siren", + icon="mdi:alarm-light", + supported=lambda api, ch: api.supported(ch, "siren"), + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up a Reolink siren entities.""" + reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] + + async_add_entities( + ReolinkSirenEntity(reolink_data, channel, entity_description) + for entity_description in SIREN_ENTITIES + for channel in reolink_data.host.api.channels + if entity_description.supported(reolink_data.host.api, channel) + ) + + +class ReolinkSirenEntity(ReolinkCoordinatorEntity, SirenEntity): + """Base siren entity class for Reolink IP cameras.""" + + _attr_supported_features = ( + SirenEntityFeature.TURN_ON + | SirenEntityFeature.TURN_OFF + | SirenEntityFeature.DURATION + | SirenEntityFeature.VOLUME_SET + ) + entity_description: ReolinkSirenEntityDescription + + def __init__( + self, + reolink_data: ReolinkData, + channel: int, + entity_description: ReolinkSirenEntityDescription, + ) -> None: + """Initialize Reolink siren entity.""" + super().__init__(reolink_data, channel) + self.entity_description = entity_description + + self._attr_unique_id = ( + f"{self._host.unique_id}_{channel}_{entity_description.key}" + ) + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn on the siren.""" + if (volume := kwargs.get(ATTR_VOLUME_LEVEL)) is not None: + await self._host.api.set_volume(self._channel, int(volume * 100)) + duration = kwargs.get(ATTR_DURATION) + await self._host.api.set_siren(self._channel, True, duration) + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn off the siren.""" + await self._host.api.set_siren(self._channel, False, None)