Add pan tilt camera module (#1261)

Add ptz controls for smartcameras.

---------

Co-authored-by: Teemu R. <tpr@iki.fi>
This commit is contained in:
Steven B. 2024-11-19 10:11:51 +00:00 committed by GitHub
parent a01247d48f
commit 5b5a148f9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 112 additions and 1 deletions

View File

@ -5,6 +5,7 @@ from .camera import Camera
from .childdevice import ChildDevice
from .device import DeviceModule
from .led import Led
from .pantilt import PanTilt
from .time import Time
__all__ = [
@ -13,5 +14,6 @@ __all__ = [
"ChildDevice",
"DeviceModule",
"Led",
"PanTilt",
"Time",
]

View File

@ -0,0 +1,107 @@
"""Implementation of time module."""
from __future__ import annotations
from ...feature import Feature
from ..smartcameramodule import SmartCameraModule
DEFAULT_PAN_STEP = 30
DEFAULT_TILT_STEP = 10
class PanTilt(SmartCameraModule):
"""Implementation of device_local_time."""
REQUIRED_COMPONENT = "ptz"
_pan_step = DEFAULT_PAN_STEP
_tilt_step = DEFAULT_TILT_STEP
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
async def set_pan_step(value: int) -> None:
self._pan_step = value
async def set_tilt_step(value: int) -> None:
self._tilt_step = value
self._add_feature(
Feature(
self._device,
"pan_right",
"Pan right",
container=self,
attribute_setter=lambda: self.pan(self._pan_step * -1),
type=Feature.Type.Action,
)
)
self._add_feature(
Feature(
self._device,
"pan_left",
"Pan left",
container=self,
attribute_setter=lambda: self.pan(self._pan_step),
type=Feature.Type.Action,
)
)
self._add_feature(
Feature(
self._device,
"pan_step",
"Pan step",
container=self,
attribute_getter="_pan_step",
attribute_setter=set_pan_step,
type=Feature.Type.Number,
)
)
self._add_feature(
Feature(
self._device,
"tilt_up",
"Tilt up",
container=self,
attribute_setter=lambda: self.tilt(self._tilt_step),
type=Feature.Type.Action,
)
)
self._add_feature(
Feature(
self._device,
"tilt_down",
"Tilt down",
container=self,
attribute_setter=lambda: self.tilt(self._tilt_step * -1),
type=Feature.Type.Action,
)
)
self._add_feature(
Feature(
self._device,
"tilt_step",
"Tilt step",
container=self,
attribute_getter="_tilt_step",
attribute_setter=set_tilt_step,
type=Feature.Type.Number,
)
)
def query(self) -> dict:
"""Query to execute during the update cycle."""
return {}
async def pan(self, pan: int) -> dict:
"""Pan horizontally."""
return await self.move(pan=pan, tilt=0)
async def tilt(self, tilt: int) -> dict:
"""Tilt vertically."""
return await self.move(pan=0, tilt=tilt)
async def move(self, *, pan: int, tilt: int) -> dict:
"""Pan and tilt camera."""
return await self._device._raw_query(
{"do": {"motor": {"move": {"x_coord": str(pan), "y_coord": str(tilt)}}}}
)

View File

@ -160,12 +160,14 @@ async def test_precision_hint(dummy_feature, precision_hint):
async def test_feature_setters(dev: Device, mocker: MockerFixture):
"""Test that all feature setters query something."""
# setters that do not call set on the device itself.
internal_setters = {"pan_step", "tilt_step"}
async def _test_feature(feat, query_mock):
if feat.attribute_setter is None:
return
expecting_call = True
expecting_call = feat.id not in internal_setters
if feat.type == Feature.Type.Number:
await feat.set_value(feat.minimum_value)