Add common reolink entity description (#104142)

Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
starkillerOG 2023-11-30 11:26:33 +01:00 committed by GitHub
parent dd00357e9c
commit 69af4c8603
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 109 additions and 99 deletions

View File

@ -25,16 +25,18 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkBinarySensorEntityDescription(BinarySensorEntityDescription): class ReolinkBinarySensorEntityDescription(
BinarySensorEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes binary sensor entities.""" """A class that describes binary sensor entities."""
icon_off: str = "mdi:motion-sensor-off" icon_off: str = "mdi:motion-sensor-off"
icon: str = "mdi:motion-sensor" icon: str = "mdi:motion-sensor"
supported: Callable[[Host, int], bool] = lambda host, ch: True
value: Callable[[Host, int], bool] value: Callable[[Host, int], bool]
@ -128,8 +130,8 @@ class ReolinkBinarySensorEntity(ReolinkChannelCoordinatorEntity, BinarySensorEnt
entity_description: ReolinkBinarySensorEntityDescription, entity_description: ReolinkBinarySensorEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink binary sensor.""" """Initialize Reolink binary sensor."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
if self._host.api.model in DUAL_LENS_DUAL_MOTION_MODELS: if self._host.api.model in DUAL_LENS_DUAL_MOTION_MODELS:
if entity_description.translation_key is not None: if entity_description.translation_key is not None:
@ -138,10 +140,6 @@ class ReolinkBinarySensorEntity(ReolinkChannelCoordinatorEntity, BinarySensorEnt
key = entity_description.key key = entity_description.key
self._attr_translation_key = f"{key}_lens_{self._channel}" self._attr_translation_key = f"{key}_lens_{self._channel}"
self._attr_unique_id = (
f"{self._host.unique_id}_{self._channel}_{entity_description.key}"
)
@property @property
def icon(self) -> str | None: def icon(self) -> str | None:
"""Icon of the sensor.""" """Icon of the sensor."""

View File

@ -27,7 +27,12 @@ from homeassistant.helpers.entity_platform import (
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity from .entity import (
ReolinkChannelCoordinatorEntity,
ReolinkChannelEntityDescription,
ReolinkHostCoordinatorEntity,
ReolinkHostEntityDescription,
)
ATTR_SPEED = "speed" ATTR_SPEED = "speed"
SUPPORT_PTZ_SPEED = CameraEntityFeature.STREAM SUPPORT_PTZ_SPEED = CameraEntityFeature.STREAM
@ -36,21 +41,23 @@ SUPPORT_PTZ_SPEED = CameraEntityFeature.STREAM
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkButtonEntityDescription( class ReolinkButtonEntityDescription(
ButtonEntityDescription, ButtonEntityDescription,
ReolinkChannelEntityDescription,
): ):
"""A class that describes button entities for a camera channel.""" """A class that describes button entities for a camera channel."""
enabled_default: Callable[[Host, int], bool] | None = None enabled_default: Callable[[Host, int], bool] | None = None
method: Callable[[Host, int], Any] method: Callable[[Host, int], Any]
supported: Callable[[Host, int], bool] = lambda api, ch: True
ptz_cmd: str | None = None ptz_cmd: str | None = None
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkHostButtonEntityDescription(ButtonEntityDescription): class ReolinkHostButtonEntityDescription(
ButtonEntityDescription,
ReolinkHostEntityDescription,
):
"""A class that describes button entities for the host.""" """A class that describes button entities for the host."""
method: Callable[[Host], Any] method: Callable[[Host], Any]
supported: Callable[[Host], bool] = lambda api: True
BUTTON_ENTITIES = ( BUTTON_ENTITIES = (
@ -195,12 +202,9 @@ class ReolinkButtonEntity(ReolinkChannelCoordinatorEntity, ButtonEntity):
entity_description: ReolinkButtonEntityDescription, entity_description: ReolinkButtonEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink button entity.""" """Initialize Reolink button entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
if entity_description.enabled_default is not None: if entity_description.enabled_default is not None:
self._attr_entity_registry_enabled_default = ( self._attr_entity_registry_enabled_default = (
entity_description.enabled_default(self._host.api, self._channel) entity_description.enabled_default(self._host.api, self._channel)
@ -241,10 +245,8 @@ class ReolinkHostButtonEntity(ReolinkHostCoordinatorEntity, ButtonEntity):
entity_description: ReolinkHostButtonEntityDescription, entity_description: ReolinkHostButtonEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink button entity.""" """Initialize Reolink button entity."""
super().__init__(reolink_data)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data)
self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}"
async def async_press(self) -> None: async def async_press(self) -> None:
"""Execute the button action.""" """Execute the button action."""

View File

@ -1,11 +1,10 @@
"""Component providing support for Reolink IP cameras.""" """Component providing support for Reolink IP cameras."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
import logging import logging
from reolink_aio.api import DUAL_LENS_MODELS, Host from reolink_aio.api import DUAL_LENS_MODELS
from reolink_aio.exceptions import ReolinkError from reolink_aio.exceptions import ReolinkError
from homeassistant.components.camera import ( from homeassistant.components.camera import (
@ -20,7 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -28,11 +27,11 @@ _LOGGER = logging.getLogger(__name__)
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkCameraEntityDescription( class ReolinkCameraEntityDescription(
CameraEntityDescription, CameraEntityDescription,
ReolinkChannelEntityDescription,
): ):
"""A class that describes camera entities for a camera channel.""" """A class that describes camera entities for a camera channel."""
stream: str stream: str
supported: Callable[[Host, int], bool] = lambda api, ch: True
CAMERA_ENTITIES = ( CAMERA_ENTITIES = (
@ -135,10 +134,6 @@ class ReolinkCamera(ReolinkChannelCoordinatorEntity, Camera):
f"{entity_description.translation_key}_lens_{self._channel}" f"{entity_description.translation_key}_lens_{self._channel}"
) )
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
async def stream_source(self) -> str | None: async def stream_source(self) -> str | None:
"""Return the source of the stream.""" """Return the source of the stream."""
return await self._host.api.get_stream_source( return await self._host.api.get_stream_source(

View File

@ -1,11 +1,14 @@
"""Reolink parent entity class.""" """Reolink parent entity class."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import TypeVar from typing import TypeVar
from reolink_aio.api import DUAL_LENS_MODELS from reolink_aio.api import DUAL_LENS_MODELS, Host
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
DataUpdateCoordinator, DataUpdateCoordinator,
@ -17,8 +20,22 @@ from .const import DOMAIN
_T = TypeVar("_T") _T = TypeVar("_T")
@dataclass(kw_only=True)
class ReolinkChannelEntityDescription(EntityDescription):
"""A class that describes entities for a camera channel."""
supported: Callable[[Host, int], bool] = lambda api, ch: True
@dataclass(kw_only=True)
class ReolinkHostEntityDescription(EntityDescription):
"""A class that describes host entities."""
supported: Callable[[Host], bool] = lambda api: True
class ReolinkBaseCoordinatorEntity(CoordinatorEntity[DataUpdateCoordinator[_T]]): class ReolinkBaseCoordinatorEntity(CoordinatorEntity[DataUpdateCoordinator[_T]]):
"""Parent class fo Reolink entities.""" """Parent class for Reolink entities."""
_attr_has_entity_name = True _attr_has_entity_name = True
@ -59,14 +76,20 @@ class ReolinkHostCoordinatorEntity(ReolinkBaseCoordinatorEntity[None]):
basically a NVR with a single channel that has the camera connected to that channel. basically a NVR with a single channel that has the camera connected to that channel.
""" """
entity_description: ReolinkHostEntityDescription | ReolinkChannelEntityDescription
def __init__(self, reolink_data: ReolinkData) -> None: def __init__(self, reolink_data: ReolinkData) -> None:
"""Initialize ReolinkHostCoordinatorEntity.""" """Initialize ReolinkHostCoordinatorEntity."""
super().__init__(reolink_data, reolink_data.device_coordinator) super().__init__(reolink_data, reolink_data.device_coordinator)
self._attr_unique_id = f"{self._host.unique_id}_{self.entity_description.key}"
class ReolinkChannelCoordinatorEntity(ReolinkHostCoordinatorEntity): class ReolinkChannelCoordinatorEntity(ReolinkHostCoordinatorEntity):
"""Parent class for Reolink hardware camera entities connected to a channel of the NVR.""" """Parent class for Reolink hardware camera entities connected to a channel of the NVR."""
entity_description: ReolinkChannelEntityDescription
def __init__( def __init__(
self, self,
reolink_data: ReolinkData, reolink_data: ReolinkData,
@ -76,6 +99,9 @@ class ReolinkChannelCoordinatorEntity(ReolinkHostCoordinatorEntity):
super().__init__(reolink_data) super().__init__(reolink_data)
self._channel = channel self._channel = channel
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{self.entity_description.key}"
)
dev_ch = channel dev_ch = channel
if self._host.api.model in DUAL_LENS_MODELS: if self._host.api.model in DUAL_LENS_MODELS:

View File

@ -22,17 +22,19 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkLightEntityDescription(LightEntityDescription): class ReolinkLightEntityDescription(
LightEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes light entities.""" """A class that describes light entities."""
get_brightness_fn: Callable[[Host, int], int | None] | None = None get_brightness_fn: Callable[[Host, int], int | None] | None = None
is_on_fn: Callable[[Host, int], bool] is_on_fn: Callable[[Host, int], bool]
set_brightness_fn: Callable[[Host, int, int], Any] | None = None set_brightness_fn: Callable[[Host, int, int], Any] | None = None
supported_fn: Callable[[Host, int], bool] = lambda api, ch: True
turn_on_off_fn: Callable[[Host, int, bool], Any] turn_on_off_fn: Callable[[Host, int, bool], Any]
@ -41,7 +43,7 @@ LIGHT_ENTITIES = (
key="floodlight", key="floodlight",
translation_key="floodlight", translation_key="floodlight",
icon="mdi:spotlight-beam", icon="mdi:spotlight-beam",
supported_fn=lambda api, ch: api.supported(ch, "floodLight"), supported=lambda api, ch: api.supported(ch, "floodLight"),
is_on_fn=lambda api, ch: api.whiteled_state(ch), is_on_fn=lambda api, ch: api.whiteled_state(ch),
turn_on_off_fn=lambda api, ch, value: api.set_whiteled(ch, state=value), turn_on_off_fn=lambda api, ch, value: api.set_whiteled(ch, state=value),
get_brightness_fn=lambda api, ch: api.whiteled_brightness(ch), get_brightness_fn=lambda api, ch: api.whiteled_brightness(ch),
@ -52,7 +54,7 @@ LIGHT_ENTITIES = (
translation_key="ir_lights", translation_key="ir_lights",
icon="mdi:led-off", icon="mdi:led-off",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
supported_fn=lambda api, ch: api.supported(ch, "ir_lights"), supported=lambda api, ch: api.supported(ch, "ir_lights"),
is_on_fn=lambda api, ch: api.ir_enabled(ch), is_on_fn=lambda api, ch: api.ir_enabled(ch),
turn_on_off_fn=lambda api, ch, value: api.set_ir_lights(ch, value), turn_on_off_fn=lambda api, ch, value: api.set_ir_lights(ch, value),
), ),
@ -61,7 +63,7 @@ LIGHT_ENTITIES = (
translation_key="status_led", translation_key="status_led",
icon="mdi:lightning-bolt-circle", icon="mdi:lightning-bolt-circle",
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
supported_fn=lambda api, ch: api.supported(ch, "power_led"), supported=lambda api, ch: api.supported(ch, "power_led"),
is_on_fn=lambda api, ch: api.status_led_enabled(ch), is_on_fn=lambda api, ch: api.status_led_enabled(ch),
turn_on_off_fn=lambda api, ch, value: api.set_status_led(ch, value), turn_on_off_fn=lambda api, ch, value: api.set_status_led(ch, value),
), ),
@ -80,7 +82,7 @@ async def async_setup_entry(
ReolinkLightEntity(reolink_data, channel, entity_description) ReolinkLightEntity(reolink_data, channel, entity_description)
for entity_description in LIGHT_ENTITIES for entity_description in LIGHT_ENTITIES
for channel in reolink_data.host.api.channels for channel in reolink_data.host.api.channels
if entity_description.supported_fn(reolink_data.host.api, channel) if entity_description.supported(reolink_data.host.api, channel)
) )
@ -96,12 +98,8 @@ class ReolinkLightEntity(ReolinkChannelCoordinatorEntity, LightEntity):
entity_description: ReolinkLightEntityDescription, entity_description: ReolinkLightEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink light entity.""" """Initialize Reolink light entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
if entity_description.set_brightness_fn is None: if entity_description.set_brightness_fn is None:
self._attr_supported_color_modes = {ColorMode.ONOFF} self._attr_supported_color_modes = {ColorMode.ONOFF}

View File

@ -21,18 +21,20 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkNumberEntityDescription(NumberEntityDescription): class ReolinkNumberEntityDescription(
NumberEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes number entities.""" """A class that describes number entities."""
get_max_value: Callable[[Host, int], float] | None = None get_max_value: Callable[[Host, int], float] | None = None
get_min_value: Callable[[Host, int], float] | None = None get_min_value: Callable[[Host, int], float] | None = None
method: Callable[[Host, int, float], Any] method: Callable[[Host, int, float], Any]
mode: NumberMode = NumberMode.AUTO mode: NumberMode = NumberMode.AUTO
supported: Callable[[Host, int], bool] = lambda api, ch: True
value: Callable[[Host, int], float | None] value: Callable[[Host, int], float | None]
@ -378,8 +380,8 @@ class ReolinkNumberEntity(ReolinkChannelCoordinatorEntity, NumberEntity):
entity_description: ReolinkNumberEntityDescription, entity_description: ReolinkNumberEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink number entity.""" """Initialize Reolink number entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
if entity_description.get_min_value is not None: if entity_description.get_min_value is not None:
self._attr_native_min_value = entity_description.get_min_value( self._attr_native_min_value = entity_description.get_min_value(
@ -390,9 +392,6 @@ class ReolinkNumberEntity(ReolinkChannelCoordinatorEntity, NumberEntity):
self._host.api, channel self._host.api, channel
) )
self._attr_mode = entity_description.mode self._attr_mode = entity_description.mode
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
@property @property
def native_value(self) -> float | None: def native_value(self) -> float | None:

View File

@ -24,18 +24,20 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkSelectEntityDescription(SelectEntityDescription): class ReolinkSelectEntityDescription(
SelectEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes select entities.""" """A class that describes select entities."""
get_options: list[str] | Callable[[Host, int], list[str]] get_options: list[str] | Callable[[Host, int], list[str]]
method: Callable[[Host, int, str], Any] method: Callable[[Host, int, str], Any]
supported: Callable[[Host, int], bool] = lambda api, ch: True
value: Callable[[Host, int], str] | None = None value: Callable[[Host, int], str] | None = None
@ -131,14 +133,10 @@ class ReolinkSelectEntity(ReolinkChannelCoordinatorEntity, SelectEntity):
entity_description: ReolinkSelectEntityDescription, entity_description: ReolinkSelectEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink select entity.""" """Initialize Reolink select entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._log_error = True self._log_error = True
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
if callable(entity_description.get_options): if callable(entity_description.get_options):
self._attr_options = entity_description.get_options(self._host.api, channel) self._attr_options = entity_description.get_options(self._host.api, channel)
else: else:

View File

@ -21,31 +21,32 @@ from homeassistant.helpers.typing import StateType
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity from .entity import (
ReolinkChannelCoordinatorEntity,
ReolinkChannelEntityDescription,
ReolinkHostCoordinatorEntity,
ReolinkHostEntityDescription,
)
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkSensorEntityDescription(SensorEntityDescription): class ReolinkSensorEntityDescription(
SensorEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes sensor entities for a camera channel.""" """A class that describes sensor entities for a camera channel."""
supported: Callable[[Host, int], bool] = lambda api, ch: True
value: Callable[[Host, int], int] value: Callable[[Host, int], int]
@dataclass @dataclass(kw_only=True)
class ReolinkHostSensorEntityDescriptionMixin:
"""Mixin values for Reolink host sensor entities."""
value: Callable[[Host], int | None]
@dataclass
class ReolinkHostSensorEntityDescription( class ReolinkHostSensorEntityDescription(
SensorEntityDescription, ReolinkHostSensorEntityDescriptionMixin SensorEntityDescription,
ReolinkHostEntityDescription,
): ):
"""A class that describes host sensor entities.""" """A class that describes host sensor entities."""
supported: Callable[[Host], bool] = lambda api: True value: Callable[[Host], int | None]
SENSORS = ( SENSORS = (
@ -110,12 +111,8 @@ class ReolinkSensorEntity(ReolinkChannelCoordinatorEntity, SensorEntity):
entity_description: ReolinkSensorEntityDescription, entity_description: ReolinkSensorEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink sensor.""" """Initialize Reolink sensor."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
@property @property
def native_value(self) -> StateType | date | datetime | Decimal: def native_value(self) -> StateType | date | datetime | Decimal:
@ -134,10 +131,8 @@ class ReolinkHostSensorEntity(ReolinkHostCoordinatorEntity, SensorEntity):
entity_description: ReolinkHostSensorEntityDescription, entity_description: ReolinkHostSensorEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink host sensor.""" """Initialize Reolink host sensor."""
super().__init__(reolink_data)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data)
self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}"
@property @property
def native_value(self) -> StateType | date | datetime | Decimal: def native_value(self) -> StateType | date | datetime | Decimal:

View File

@ -1,11 +1,9 @@
"""Component providing support for Reolink siren entities.""" """Component providing support for Reolink siren entities."""
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from reolink_aio.api import Host
from reolink_aio.exceptions import InvalidParameterError, ReolinkError from reolink_aio.exceptions import InvalidParameterError, ReolinkError
from homeassistant.components.siren import ( from homeassistant.components.siren import (
@ -22,15 +20,15 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity from .entity import ReolinkChannelCoordinatorEntity, ReolinkChannelEntityDescription
@dataclass @dataclass
class ReolinkSirenEntityDescription(SirenEntityDescription): class ReolinkSirenEntityDescription(
SirenEntityDescription, ReolinkChannelEntityDescription
):
"""A class that describes siren entities.""" """A class that describes siren entities."""
supported: Callable[[Host, int], bool] = lambda api, ch: True
SIREN_ENTITIES = ( SIREN_ENTITIES = (
ReolinkSirenEntityDescription( ReolinkSirenEntityDescription(
@ -76,12 +74,8 @@ class ReolinkSirenEntity(ReolinkChannelCoordinatorEntity, SirenEntity):
entity_description: ReolinkSirenEntityDescription, entity_description: ReolinkSirenEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink siren entity.""" """Initialize Reolink siren entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the siren.""" """Turn on the siren."""

View File

@ -17,24 +17,33 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ReolinkData from . import ReolinkData
from .const import DOMAIN from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity from .entity import (
ReolinkChannelCoordinatorEntity,
ReolinkChannelEntityDescription,
ReolinkHostCoordinatorEntity,
ReolinkHostEntityDescription,
)
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkSwitchEntityDescription(SwitchEntityDescription): class ReolinkSwitchEntityDescription(
SwitchEntityDescription,
ReolinkChannelEntityDescription,
):
"""A class that describes switch entities.""" """A class that describes switch entities."""
method: Callable[[Host, int, bool], Any] method: Callable[[Host, int, bool], Any]
supported: Callable[[Host, int], bool] = lambda api, ch: True
value: Callable[[Host, int], bool] value: Callable[[Host, int], bool]
@dataclass(kw_only=True) @dataclass(kw_only=True)
class ReolinkNVRSwitchEntityDescription(SwitchEntityDescription): class ReolinkNVRSwitchEntityDescription(
SwitchEntityDescription,
ReolinkHostEntityDescription,
):
"""A class that describes NVR switch entities.""" """A class that describes NVR switch entities."""
method: Callable[[Host, bool], Any] method: Callable[[Host, bool], Any]
supported: Callable[[Host], bool] = lambda api: True
value: Callable[[Host], bool] value: Callable[[Host], bool]
@ -235,12 +244,8 @@ class ReolinkSwitchEntity(ReolinkChannelCoordinatorEntity, SwitchEntity):
entity_description: ReolinkSwitchEntityDescription, entity_description: ReolinkSwitchEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink switch entity.""" """Initialize Reolink switch entity."""
super().__init__(reolink_data, channel)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data, channel)
self._attr_unique_id = (
f"{self._host.unique_id}_{channel}_{entity_description.key}"
)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -275,8 +280,8 @@ class ReolinkNVRSwitchEntity(ReolinkHostCoordinatorEntity, SwitchEntity):
entity_description: ReolinkNVRSwitchEntityDescription, entity_description: ReolinkNVRSwitchEntityDescription,
) -> None: ) -> None:
"""Initialize Reolink switch entity.""" """Initialize Reolink switch entity."""
super().__init__(reolink_data)
self.entity_description = entity_description self.entity_description = entity_description
super().__init__(reolink_data)
self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}" self._attr_unique_id = f"{self._host.unique_id}_{entity_description.key}"