mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Add pan tilt camera module (#1261)
Add ptz controls for smartcameras. --------- Co-authored-by: Teemu R. <tpr@iki.fi>
This commit is contained in:
parent
a01247d48f
commit
5b5a148f9a
@ -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",
|
||||
]
|
||||
|
107
kasa/smartcamera/modules/pantilt.py
Normal file
107
kasa/smartcamera/modules/pantilt.py
Normal 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)}}}}
|
||||
)
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user