Reolink ptz service to specify move speed (#104350)

This commit is contained in:
starkillerOG 2023-11-24 11:50:16 +01:00 committed by GitHub
parent 9ed745638d
commit e9dd158a8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 1 deletions

View file

@ -7,22 +7,31 @@ from typing import Any
from reolink_aio.api import GuardEnum, Host, PtzEnum
from reolink_aio.exceptions import ReolinkError
import voluptuous as vol
from homeassistant.components.button import (
ButtonDeviceClass,
ButtonEntity,
ButtonEntityDescription,
)
from homeassistant.components.camera import CameraEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import (
AddEntitiesCallback,
async_get_current_platform,
)
from . import ReolinkData
from .const import DOMAIN
from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity
ATTR_SPEED = "speed"
SUPPORT_PTZ_SPEED = CameraEntityFeature.STREAM
@dataclass(kw_only=True)
class ReolinkButtonEntityDescription(
@ -33,6 +42,7 @@ class ReolinkButtonEntityDescription(
enabled_default: Callable[[Host, int], bool] | None = None
method: Callable[[Host, int], Any]
supported: Callable[[Host, int], bool] = lambda api, ch: True
ptz_cmd: str | None = None
@dataclass(kw_only=True)
@ -60,6 +70,7 @@ BUTTON_ENTITIES = (
icon="mdi:pan",
supported=lambda api, ch: api.supported(ch, "pan"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.left.value),
ptz_cmd=PtzEnum.left.value,
),
ReolinkButtonEntityDescription(
key="ptz_right",
@ -67,6 +78,7 @@ BUTTON_ENTITIES = (
icon="mdi:pan",
supported=lambda api, ch: api.supported(ch, "pan"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.right.value),
ptz_cmd=PtzEnum.right.value,
),
ReolinkButtonEntityDescription(
key="ptz_up",
@ -74,6 +86,7 @@ BUTTON_ENTITIES = (
icon="mdi:pan",
supported=lambda api, ch: api.supported(ch, "tilt"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.up.value),
ptz_cmd=PtzEnum.up.value,
),
ReolinkButtonEntityDescription(
key="ptz_down",
@ -81,6 +94,7 @@ BUTTON_ENTITIES = (
icon="mdi:pan",
supported=lambda api, ch: api.supported(ch, "tilt"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.down.value),
ptz_cmd=PtzEnum.down.value,
),
ReolinkButtonEntityDescription(
key="ptz_zoom_in",
@ -89,6 +103,7 @@ BUTTON_ENTITIES = (
entity_registry_enabled_default=False,
supported=lambda api, ch: api.supported(ch, "zoom_basic"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.zoomin.value),
ptz_cmd=PtzEnum.zoomin.value,
),
ReolinkButtonEntityDescription(
key="ptz_zoom_out",
@ -97,6 +112,7 @@ BUTTON_ENTITIES = (
entity_registry_enabled_default=False,
supported=lambda api, ch: api.supported(ch, "zoom_basic"),
method=lambda api, ch: api.set_ptz_command(ch, command=PtzEnum.zoomout.value),
ptz_cmd=PtzEnum.zoomout.value,
),
ReolinkButtonEntityDescription(
key="ptz_calibrate",
@ -158,6 +174,14 @@ async def async_setup_entry(
)
async_add_entities(entities)
platform = async_get_current_platform()
platform.async_register_entity_service(
"ptz_move",
{vol.Required(ATTR_SPEED): cv.positive_int},
"async_ptz_move",
[SUPPORT_PTZ_SPEED],
)
class ReolinkButtonEntity(ReolinkChannelCoordinatorEntity, ButtonEntity):
"""Base button entity class for Reolink IP cameras."""
@ -182,6 +206,12 @@ class ReolinkButtonEntity(ReolinkChannelCoordinatorEntity, ButtonEntity):
entity_description.enabled_default(self._host.api, self._channel)
)
if (
self._host.api.supported(channel, "ptz_speed")
and entity_description.ptz_cmd is not None
):
self._attr_supported_features = SUPPORT_PTZ_SPEED
async def async_press(self) -> None:
"""Execute the button action."""
try:
@ -189,6 +219,16 @@ class ReolinkButtonEntity(ReolinkChannelCoordinatorEntity, ButtonEntity):
except ReolinkError as err:
raise HomeAssistantError(err) from err
async def async_ptz_move(self, **kwargs) -> None:
"""PTZ move with speed."""
speed = kwargs[ATTR_SPEED]
try:
await self._host.api.set_ptz_command(
self._channel, command=self.entity_description.ptz_cmd, speed=speed
)
except ReolinkError as err:
raise HomeAssistantError(err) from err
class ReolinkHostButtonEntity(ReolinkHostCoordinatorEntity, ButtonEntity):
"""Base button entity class for Reolink IP cameras."""