Auto auto-off module for smartdevice (#760)

Adds auto-off implementation. The feature stays enabled after the timer runs out, and it will start the countdown if the device is turned on again without explicitly disabling it.

New features:
* Switch to select if enabled: `Auto off enabled (auto_off_enabled): False`
* Setting to change the delay: `Auto off minutes (auto_off_minutes): 222`
* If timer is active, datetime object when the device gets turned off: `Auto off at (auto_off_at): None`
This commit is contained in:
Teemu R 2024-02-19 21:11:11 +01:00 committed by GitHub
parent 44b59efbb2
commit efb4a0f31f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 90 additions and 1 deletions

View File

@ -47,4 +47,5 @@ class Feature:
"""Set the value.""" """Set the value."""
if self.attribute_setter is None: if self.attribute_setter is None:
raise ValueError("Tried to set read-only feature.") raise ValueError("Tried to set read-only feature.")
return await getattr(self.device, self.attribute_setter)(value) container = self.container if self.container is not None else self.device
return await getattr(container, self.attribute_setter)(value)

View File

@ -1,4 +1,5 @@
"""Modules for SMART devices.""" """Modules for SMART devices."""
from .autooffmodule import AutoOffModule
from .childdevicemodule import ChildDeviceModule from .childdevicemodule import ChildDeviceModule
from .cloudmodule import CloudModule from .cloudmodule import CloudModule
from .devicemodule import DeviceModule from .devicemodule import DeviceModule
@ -12,6 +13,7 @@ __all__ = [
"EnergyModule", "EnergyModule",
"DeviceModule", "DeviceModule",
"ChildDeviceModule", "ChildDeviceModule",
"AutoOffModule",
"LedModule", "LedModule",
"CloudModule", "CloudModule",
"LightTransitionModule", "LightTransitionModule",

View File

@ -0,0 +1,84 @@
"""Implementation of auto off module."""
from datetime import datetime, timedelta
from typing import TYPE_CHECKING, Dict, Optional
from ...feature import Feature
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class AutoOffModule(SmartModule):
"""Implementation of auto off module."""
REQUIRED_COMPONENT = "auto_off"
QUERY_GETTER_NAME = "get_auto_off_config"
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Auto off enabled",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
)
)
self._add_feature(
Feature(
device,
"Auto off minutes",
container=self,
attribute_getter="delay",
attribute_setter="set_delay",
)
)
self._add_feature(
Feature(
device, "Auto off at", container=self, attribute_getter="auto_off_at"
)
)
def query(self) -> Dict:
"""Query to execute during the update cycle."""
return {self.QUERY_GETTER_NAME: {"start_index": 0}}
@property
def enabled(self) -> bool:
"""Return True if enabled."""
return self.data["enable"]
def set_enabled(self, enable: bool):
"""Enable/disable auto off."""
return self.call(
"set_auto_off_config",
{"enable": enable, "delay_min": self.data["delay_min"]},
)
@property
def delay(self) -> int:
"""Return time until auto off."""
return self.data["delay_min"]
def set_delay(self, delay: int):
"""Set time until auto off."""
return self.call(
"set_auto_off_config", {"delay_min": delay, "enable": self.data["enable"]}
)
@property
def is_timer_active(self) -> bool:
"""Return True is auto-off timer is active."""
return self._device.sys_info["auto_off_status"] == "on"
@property
def auto_off_at(self) -> Optional[datetime]:
"""Return when the device will be turned off automatically."""
if not self.is_timer_active:
return None
sysinfo = self._device.sys_info
return self._device.time + timedelta(seconds=sysinfo["auto_off_remain_time"])

View File

@ -13,6 +13,7 @@ from ..exceptions import AuthenticationException, SmartDeviceException, SmartErr
from ..feature import Feature, FeatureType from ..feature import Feature, FeatureType
from ..smartprotocol import SmartProtocol from ..smartprotocol import SmartProtocol
from .modules import ( # noqa: F401 from .modules import ( # noqa: F401
AutoOffModule,
ChildDeviceModule, ChildDeviceModule,
CloudModule, CloudModule,
DeviceModule, DeviceModule,

View File

@ -46,6 +46,7 @@ class FakeSmartTransport(BaseTransport):
FIXTURE_MISSING_MAP = { FIXTURE_MISSING_MAP = {
"get_wireless_scan_info": ("wireless", {"ap_list": [], "wep_supported": False}), "get_wireless_scan_info": ("wireless", {"ap_list": [], "wep_supported": False}),
"get_auto_off_config": ("auto_off", {'delay_min': 10, 'enable': False}),
"get_led_info": ( "get_led_info": (
"led", "led",
{ {