mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-26 16:46:23 +00:00
Implement motion & ambient light sensor modules for dimmers (#278)
This commit is contained in:
parent
e3588047fc
commit
8c7b1b4a68
@ -1,9 +1,11 @@
|
||||
# flake8: noqa
|
||||
from .ambientlight import AmbientLight
|
||||
from .antitheft import Antitheft
|
||||
from .cloud import Cloud
|
||||
from .countdown import Countdown
|
||||
from .emeter import Emeter
|
||||
from .module import Module
|
||||
from .motion import Motion
|
||||
from .rulemodule import Rule, RuleModule
|
||||
from .schedule import Schedule
|
||||
from .time import Time
|
||||
|
47
kasa/modules/ambientlight.py
Normal file
47
kasa/modules/ambientlight.py
Normal file
@ -0,0 +1,47 @@
|
||||
"""Implementation of the ambient light (LAS) module found in some dimmers."""
|
||||
from .module import Module
|
||||
|
||||
# TODO create tests and use the config reply there
|
||||
# [{"hw_id":0,"enable":0,"dark_index":1,"min_adc":0,"max_adc":2450,
|
||||
# "level_array":[{"name":"cloudy","adc":490,"value":20},
|
||||
# {"name":"overcast","adc":294,"value":12},
|
||||
# {"name":"dawn","adc":222,"value":9},
|
||||
# {"name":"twilight","adc":222,"value":9},
|
||||
# {"name":"total darkness","adc":111,"value":4},
|
||||
# {"name":"custom","adc":2400,"value":97}]}]
|
||||
|
||||
|
||||
class AmbientLight(Module):
|
||||
"""Implements ambient light controls for the motion sensor."""
|
||||
|
||||
def query(self):
|
||||
"""Request configuration."""
|
||||
return self.query_for_command("get_config")
|
||||
|
||||
@property
|
||||
def presets(self) -> dict:
|
||||
"""Return device-defined presets for brightness setting."""
|
||||
return self.data["level_array"]
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
"""Return True if the module is enabled."""
|
||||
return bool(self.data["enable"])
|
||||
|
||||
async def set_enabled(self, state: bool):
|
||||
"""Enable/disable LAS."""
|
||||
return await self.call("set_enable", {"enable": int(state)})
|
||||
|
||||
async def current_brightness(self) -> int:
|
||||
"""Return current brightness.
|
||||
|
||||
Return value units.
|
||||
"""
|
||||
return await self.call("get_current_brt")
|
||||
|
||||
async def set_brightness_limit(self, value: int):
|
||||
"""Set the limit when the motion sensor is inactive.
|
||||
|
||||
See `presets` for preset values. Custom values are also likely allowed.
|
||||
"""
|
||||
return await self.call("set_brt_level", {"index": 0, "value": value})
|
62
kasa/modules/motion.py
Normal file
62
kasa/modules/motion.py
Normal file
@ -0,0 +1,62 @@
|
||||
"""Implementation of the motion detection (PIR) module found in some dimmers."""
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from kasa.smartdevice import SmartDeviceException
|
||||
|
||||
from .module import Module
|
||||
|
||||
|
||||
class Range(Enum):
|
||||
"""Range for motion detection."""
|
||||
|
||||
Far = 0
|
||||
Mid = 1
|
||||
Near = 2
|
||||
Custom = 3
|
||||
|
||||
|
||||
# TODO: use the config reply in tests
|
||||
# {"enable":0,"version":"1.0","trigger_index":2,"cold_time":60000,
|
||||
# "min_adc":0,"max_adc":4095,"array":[80,50,20,0],"err_code":0}}}
|
||||
|
||||
|
||||
class Motion(Module):
|
||||
"""Implements the motion detection (PIR) module."""
|
||||
|
||||
def query(self):
|
||||
"""Request PIR configuration."""
|
||||
return self.query_for_command("get_config")
|
||||
|
||||
@property
|
||||
def range(self) -> Range:
|
||||
"""Return motion detection range."""
|
||||
return Range(self.data["trigger_index"])
|
||||
|
||||
@property
|
||||
def enabled(self) -> bool:
|
||||
"""Return True if module is enabled."""
|
||||
return bool(self.data["enable"])
|
||||
|
||||
async def set_enabled(self, state: bool):
|
||||
"""Enable/disable PIR."""
|
||||
return await self.call("set_enable", {"enable": int(state)})
|
||||
|
||||
async def set_range(
|
||||
self, *, range: Optional[Range] = None, custom_range: Optional[int] = None
|
||||
):
|
||||
"""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 SmartDeviceException(
|
||||
"Either range or custom_range need to be defined"
|
||||
)
|
||||
|
||||
return await self.call("set_trigger_sens", payload)
|
@ -1,6 +1,7 @@
|
||||
"""Module for dimmers (currently only HS220)."""
|
||||
from typing import Any, Dict
|
||||
|
||||
from kasa.modules import AmbientLight, Motion
|
||||
from kasa.smartdevice import DeviceType, SmartDeviceException, requires_update
|
||||
from kasa.smartplug import SmartPlug
|
||||
|
||||
@ -40,6 +41,10 @@ class SmartDimmer(SmartPlug):
|
||||
def __init__(self, host: str) -> None:
|
||||
super().__init__(host)
|
||||
self._device_type = DeviceType.Dimmer
|
||||
# TODO: need to be verified if it's okay to call these on HS220 w/o these
|
||||
# TODO: need to be figured out what's the best approach to detect support for these
|
||||
self.add_module("motion", Motion(self, "smartlife.iot.PIR"))
|
||||
self.add_module("ambient", AmbientLight(self, "smartlife.iot.LAS"))
|
||||
|
||||
@property # type: ignore
|
||||
@requires_update
|
||||
|
Loading…
x
Reference in New Issue
Block a user