mirror of
				https://github.com/python-kasa/python-kasa.git
				synced 2025-10-31 04:31:54 +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:
		| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Steven B.
					Steven B.