python-kasa/kasa/iot/modules/motion.py
2024-11-10 18:55:13 +00:00

103 lines
3.1 KiB
Python

"""Implementation of the motion detection (PIR) module found in some dimmers."""
from __future__ import annotations
import logging
from enum import Enum
from ...exceptions import KasaException
from ...feature import Feature
from ..iotmodule import IotModule
_LOGGER = logging.getLogger(__name__)
class Range(Enum):
"""Range for motion detection."""
Far = 0
Mid = 1
Near = 2
Custom = 3
class Motion(IotModule):
"""Implements the motion detection (PIR) module."""
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
# Only add features if the device supports the module
if "get_config" not in self.data:
return
if "enable" not in self.config:
_LOGGER.warning("%r initialized, but no enable in response")
return
self._add_feature(
Feature(
device=self._device,
container=self,
id="pir_enabled",
name="PIR enabled",
icon="mdi:motion-sensor",
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
def query(self) -> dict:
"""Request PIR configuration."""
return self.query_for_command("get_config")
@property
def config(self) -> dict:
"""Return current configuration."""
return self.data["get_config"]
@property
def range(self) -> Range:
"""Return motion detection range."""
return Range(self.config["trigger_index"])
@property
def enabled(self) -> bool:
"""Return True if module is enabled."""
return bool(self.config["enable"])
async def set_enabled(self, state: bool) -> dict:
"""Enable/disable PIR."""
return await self.call("set_enable", {"enable": int(state)})
async def set_range(
self, *, range: Range | None = None, custom_range: int | None = None
) -> dict:
"""Set the range for the sensor.
:param range: for using standard ranges
:param custom_range: range in decimeters, overrides the range parameter
"""
if custom_range is not None:
payload = {"index": Range.Custom.value, "value": custom_range}
elif range is not None:
payload = {"index": range.value}
else:
raise KasaException("Either range or custom_range need to be defined")
return await self.call("set_trigger_sens", payload)
@property
def inactivity_timeout(self) -> int:
"""Return inactivity timeout in milliseconds."""
return self.config["cold_time"]
async def set_inactivity_timeout(self, timeout: int) -> dict:
"""Set inactivity timeout in milliseconds.
Note, that you need to delete the default "Smart Control" rule in the app
to avoid reverting this back to 60 seconds after a period of time.
"""
return await self.call("set_cold_time", {"cold_time": timeout})