mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-26 16:46:23 +00:00
Make module names consistent and remove redundant module casting (#909)
Address the inconsistent naming of smart modules by removing all "Module" suffixes and aligning filenames with class names. Removes the casting of modules to the correct module type now that is is redundant. Update the adding of iot modules to use the ModuleName class rather than a free string.
This commit is contained in:
parent
9473d97ad2
commit
f259a8f162
@ -13,6 +13,7 @@ from ..bulb import HSV, Bulb, BulbPreset, ColorTempRange
|
|||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..deviceconfig import DeviceConfig
|
from ..deviceconfig import DeviceConfig
|
||||||
from ..feature import Feature
|
from ..feature import Feature
|
||||||
|
from ..module import Module
|
||||||
from ..protocol import BaseProtocol
|
from ..protocol import BaseProtocol
|
||||||
from .iotdevice import IotDevice, KasaException, requires_update
|
from .iotdevice import IotDevice, KasaException, requires_update
|
||||||
from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage
|
from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage
|
||||||
@ -198,13 +199,17 @@ class IotBulb(IotDevice, Bulb):
|
|||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(host=host, config=config, protocol=protocol)
|
super().__init__(host=host, config=config, protocol=protocol)
|
||||||
self._device_type = DeviceType.Bulb
|
self._device_type = DeviceType.Bulb
|
||||||
self.add_module("schedule", Schedule(self, "smartlife.iot.common.schedule"))
|
self.add_module(
|
||||||
self.add_module("usage", Usage(self, "smartlife.iot.common.schedule"))
|
Module.IotSchedule, Schedule(self, "smartlife.iot.common.schedule")
|
||||||
self.add_module("antitheft", Antitheft(self, "smartlife.iot.common.anti_theft"))
|
)
|
||||||
self.add_module("time", Time(self, "smartlife.iot.common.timesetting"))
|
self.add_module(Module.IotUsage, Usage(self, "smartlife.iot.common.schedule"))
|
||||||
self.add_module("emeter", Emeter(self, self.emeter_type))
|
self.add_module(
|
||||||
self.add_module("countdown", Countdown(self, "countdown"))
|
Module.IotAntitheft, Antitheft(self, "smartlife.iot.common.anti_theft")
|
||||||
self.add_module("cloud", Cloud(self, "smartlife.iot.common.cloud"))
|
)
|
||||||
|
self.add_module(Module.IotTime, Time(self, "smartlife.iot.common.timesetting"))
|
||||||
|
self.add_module(Module.IotEmeter, Emeter(self, self.emeter_type))
|
||||||
|
self.add_module(Module.IotCountdown, Countdown(self, "countdown"))
|
||||||
|
self.add_module(Module.IotCloud, Cloud(self, "smartlife.iot.common.cloud"))
|
||||||
|
|
||||||
async def _initialize_features(self):
|
async def _initialize_features(self):
|
||||||
await super()._initialize_features()
|
await super()._initialize_features()
|
||||||
|
@ -30,7 +30,7 @@ from ..module import Module
|
|||||||
from ..modulemapping import ModuleMapping, ModuleName
|
from ..modulemapping import ModuleMapping, ModuleName
|
||||||
from ..protocol import BaseProtocol
|
from ..protocol import BaseProtocol
|
||||||
from .iotmodule import IotModule
|
from .iotmodule import IotModule
|
||||||
from .modules import Emeter, Time
|
from .modules import Emeter
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ class IotDevice(Device):
|
|||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"The device has emeter, querying its information along sysinfo"
|
"The device has emeter, querying its information along sysinfo"
|
||||||
)
|
)
|
||||||
self.add_module("emeter", Emeter(self, self.emeter_type))
|
self.add_module(Module.IotEmeter, Emeter(self, self.emeter_type))
|
||||||
|
|
||||||
# TODO: perhaps modules should not have unsupported modules,
|
# TODO: perhaps modules should not have unsupported modules,
|
||||||
# making separate handling for this unnecessary
|
# making separate handling for this unnecessary
|
||||||
@ -440,27 +440,27 @@ class IotDevice(Device):
|
|||||||
@requires_update
|
@requires_update
|
||||||
def time(self) -> datetime:
|
def time(self) -> datetime:
|
||||||
"""Return current time from the device."""
|
"""Return current time from the device."""
|
||||||
return cast(Time, self.modules["time"]).time
|
return self.modules[Module.IotTime].time
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@requires_update
|
@requires_update
|
||||||
def timezone(self) -> dict:
|
def timezone(self) -> dict:
|
||||||
"""Return the current timezone."""
|
"""Return the current timezone."""
|
||||||
return cast(Time, self.modules["time"]).timezone
|
return self.modules[Module.IotTime].timezone
|
||||||
|
|
||||||
async def get_time(self) -> datetime | None:
|
async def get_time(self) -> datetime | None:
|
||||||
"""Return current time from the device, if available."""
|
"""Return current time from the device, if available."""
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Use `time` property instead, this call will be removed in the future."
|
"Use `time` property instead, this call will be removed in the future."
|
||||||
)
|
)
|
||||||
return await cast(Time, self.modules["time"]).get_time()
|
return await self.modules[Module.IotTime].get_time()
|
||||||
|
|
||||||
async def get_timezone(self) -> dict:
|
async def get_timezone(self) -> dict:
|
||||||
"""Return timezone information."""
|
"""Return timezone information."""
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Use `timezone` property instead, this call will be removed in the future."
|
"Use `timezone` property instead, this call will be removed in the future."
|
||||||
)
|
)
|
||||||
return await cast(Time, self.modules["time"]).get_timezone()
|
return await self.modules[Module.IotTime].get_timezone()
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@requires_update
|
@requires_update
|
||||||
@ -541,26 +541,26 @@ class IotDevice(Device):
|
|||||||
def emeter_realtime(self) -> EmeterStatus:
|
def emeter_realtime(self) -> EmeterStatus:
|
||||||
"""Return current energy readings."""
|
"""Return current energy readings."""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return EmeterStatus(cast(Emeter, self.modules["emeter"]).realtime)
|
return EmeterStatus(self.modules[Module.IotEmeter].realtime)
|
||||||
|
|
||||||
async def get_emeter_realtime(self) -> EmeterStatus:
|
async def get_emeter_realtime(self) -> EmeterStatus:
|
||||||
"""Retrieve current energy readings."""
|
"""Retrieve current energy readings."""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return EmeterStatus(await cast(Emeter, self.modules["emeter"]).get_realtime())
|
return EmeterStatus(await self.modules[Module.IotEmeter].get_realtime())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@requires_update
|
@requires_update
|
||||||
def emeter_today(self) -> float | None:
|
def emeter_today(self) -> float | None:
|
||||||
"""Return today's energy consumption in kWh."""
|
"""Return today's energy consumption in kWh."""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return cast(Emeter, self.modules["emeter"]).emeter_today
|
return self.modules[Module.IotEmeter].emeter_today
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@requires_update
|
@requires_update
|
||||||
def emeter_this_month(self) -> float | None:
|
def emeter_this_month(self) -> float | None:
|
||||||
"""Return this month's energy consumption in kWh."""
|
"""Return this month's energy consumption in kWh."""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return cast(Emeter, self.modules["emeter"]).emeter_this_month
|
return self.modules[Module.IotEmeter].emeter_this_month
|
||||||
|
|
||||||
async def get_emeter_daily(
|
async def get_emeter_daily(
|
||||||
self, year: int | None = None, month: int | None = None, kwh: bool = True
|
self, year: int | None = None, month: int | None = None, kwh: bool = True
|
||||||
@ -574,7 +574,7 @@ class IotDevice(Device):
|
|||||||
:return: mapping of day of month to value
|
:return: mapping of day of month to value
|
||||||
"""
|
"""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return await cast(Emeter, self.modules["emeter"]).get_daystat(
|
return await self.modules[Module.IotEmeter].get_daystat(
|
||||||
year=year, month=month, kwh=kwh
|
year=year, month=month, kwh=kwh
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -589,15 +589,13 @@ class IotDevice(Device):
|
|||||||
:return: dict: mapping of month to value
|
:return: dict: mapping of month to value
|
||||||
"""
|
"""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return await cast(Emeter, self.modules["emeter"]).get_monthstat(
|
return await self.modules[Module.IotEmeter].get_monthstat(year=year, kwh=kwh)
|
||||||
year=year, kwh=kwh
|
|
||||||
)
|
|
||||||
|
|
||||||
@requires_update
|
@requires_update
|
||||||
async def erase_emeter_stats(self) -> dict:
|
async def erase_emeter_stats(self) -> dict:
|
||||||
"""Erase energy meter statistics."""
|
"""Erase energy meter statistics."""
|
||||||
self._verify_emeter()
|
self._verify_emeter()
|
||||||
return await cast(Emeter, self.modules["emeter"]).erase_stats()
|
return await self.modules[Module.IotEmeter].erase_stats()
|
||||||
|
|
||||||
@requires_update
|
@requires_update
|
||||||
async def current_consumption(self) -> float:
|
async def current_consumption(self) -> float:
|
||||||
|
@ -8,6 +8,7 @@ from typing import Any
|
|||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..deviceconfig import DeviceConfig
|
from ..deviceconfig import DeviceConfig
|
||||||
from ..feature import Feature
|
from ..feature import Feature
|
||||||
|
from ..module import Module
|
||||||
from ..protocol import BaseProtocol
|
from ..protocol import BaseProtocol
|
||||||
from .iotdevice import KasaException, requires_update
|
from .iotdevice import KasaException, requires_update
|
||||||
from .iotplug import IotPlug
|
from .iotplug import IotPlug
|
||||||
@ -81,8 +82,8 @@ class IotDimmer(IotPlug):
|
|||||||
self._device_type = DeviceType.Dimmer
|
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 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
|
# TODO: need to be figured out what's the best approach to detect support
|
||||||
self.add_module("motion", Motion(self, "smartlife.iot.PIR"))
|
self.add_module(Module.IotMotion, Motion(self, "smartlife.iot.PIR"))
|
||||||
self.add_module("ambient", AmbientLight(self, "smartlife.iot.LAS"))
|
self.add_module(Module.IotAmbientLight, AmbientLight(self, "smartlife.iot.LAS"))
|
||||||
|
|
||||||
async def _initialize_features(self):
|
async def _initialize_features(self):
|
||||||
await super()._initialize_features()
|
await super()._initialize_features()
|
||||||
|
@ -9,7 +9,7 @@ from ..protocol import BaseProtocol
|
|||||||
from .effects import EFFECT_NAMES_V1
|
from .effects import EFFECT_NAMES_V1
|
||||||
from .iotbulb import IotBulb
|
from .iotbulb import IotBulb
|
||||||
from .iotdevice import KasaException, requires_update
|
from .iotdevice import KasaException, requires_update
|
||||||
from .modules.lighteffectmodule import LightEffectModule
|
from .modules.lighteffect import LightEffect
|
||||||
|
|
||||||
|
|
||||||
class IotLightStrip(IotBulb):
|
class IotLightStrip(IotBulb):
|
||||||
@ -58,7 +58,7 @@ class IotLightStrip(IotBulb):
|
|||||||
self._device_type = DeviceType.LightStrip
|
self._device_type = DeviceType.LightStrip
|
||||||
self.add_module(
|
self.add_module(
|
||||||
Module.LightEffect,
|
Module.LightEffect,
|
||||||
LightEffectModule(self, "smartlife.iot.lighting_effect"),
|
LightEffect(self, "smartlife.iot.lighting_effect"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
|
@ -9,7 +9,7 @@ from ..deviceconfig import DeviceConfig
|
|||||||
from ..module import Module
|
from ..module import Module
|
||||||
from ..protocol import BaseProtocol
|
from ..protocol import BaseProtocol
|
||||||
from .iotdevice import IotDevice, requires_update
|
from .iotdevice import IotDevice, requires_update
|
||||||
from .modules import Antitheft, Cloud, LedModule, Schedule, Time, Usage
|
from .modules import Antitheft, Cloud, Led, Schedule, Time, Usage
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -53,12 +53,12 @@ class IotPlug(IotDevice):
|
|||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(host=host, config=config, protocol=protocol)
|
super().__init__(host=host, config=config, protocol=protocol)
|
||||||
self._device_type = DeviceType.Plug
|
self._device_type = DeviceType.Plug
|
||||||
self.add_module("schedule", Schedule(self, "schedule"))
|
self.add_module(Module.IotSchedule, Schedule(self, "schedule"))
|
||||||
self.add_module("usage", Usage(self, "schedule"))
|
self.add_module(Module.IotUsage, Usage(self, "schedule"))
|
||||||
self.add_module("antitheft", Antitheft(self, "anti_theft"))
|
self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft"))
|
||||||
self.add_module("time", Time(self, "time"))
|
self.add_module(Module.IotTime, Time(self, "time"))
|
||||||
self.add_module("cloud", Cloud(self, "cnCloud"))
|
self.add_module(Module.IotCloud, Cloud(self, "cnCloud"))
|
||||||
self.add_module(Module.Led, LedModule(self, "system"))
|
self.add_module(Module.Led, Led(self, "system"))
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@requires_update
|
@requires_update
|
||||||
|
@ -10,6 +10,7 @@ from typing import Any
|
|||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..deviceconfig import DeviceConfig
|
from ..deviceconfig import DeviceConfig
|
||||||
from ..exceptions import KasaException
|
from ..exceptions import KasaException
|
||||||
|
from ..module import Module
|
||||||
from ..protocol import BaseProtocol
|
from ..protocol import BaseProtocol
|
||||||
from .iotdevice import (
|
from .iotdevice import (
|
||||||
EmeterStatus,
|
EmeterStatus,
|
||||||
@ -95,11 +96,11 @@ class IotStrip(IotDevice):
|
|||||||
super().__init__(host=host, config=config, protocol=protocol)
|
super().__init__(host=host, config=config, protocol=protocol)
|
||||||
self.emeter_type = "emeter"
|
self.emeter_type = "emeter"
|
||||||
self._device_type = DeviceType.Strip
|
self._device_type = DeviceType.Strip
|
||||||
self.add_module("antitheft", Antitheft(self, "anti_theft"))
|
self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft"))
|
||||||
self.add_module("schedule", Schedule(self, "schedule"))
|
self.add_module(Module.IotSchedule, Schedule(self, "schedule"))
|
||||||
self.add_module("usage", Usage(self, "schedule"))
|
self.add_module(Module.IotUsage, Usage(self, "schedule"))
|
||||||
self.add_module("time", Time(self, "time"))
|
self.add_module(Module.IotTime, Time(self, "time"))
|
||||||
self.add_module("countdown", Countdown(self, "countdown"))
|
self.add_module(Module.IotCountdown, Countdown(self, "countdown"))
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@requires_update
|
@requires_update
|
||||||
|
@ -5,7 +5,8 @@ from .antitheft import Antitheft
|
|||||||
from .cloud import Cloud
|
from .cloud import Cloud
|
||||||
from .countdown import Countdown
|
from .countdown import Countdown
|
||||||
from .emeter import Emeter
|
from .emeter import Emeter
|
||||||
from .ledmodule import LedModule
|
from .led import Led
|
||||||
|
from .lighteffect import LightEffect
|
||||||
from .motion import Motion
|
from .motion import Motion
|
||||||
from .rulemodule import Rule, RuleModule
|
from .rulemodule import Rule, RuleModule
|
||||||
from .schedule import Schedule
|
from .schedule import Schedule
|
||||||
@ -18,7 +19,8 @@ __all__ = [
|
|||||||
"Cloud",
|
"Cloud",
|
||||||
"Countdown",
|
"Countdown",
|
||||||
"Emeter",
|
"Emeter",
|
||||||
"LedModule",
|
"Led",
|
||||||
|
"LightEffect",
|
||||||
"Motion",
|
"Motion",
|
||||||
"Rule",
|
"Rule",
|
||||||
"RuleModule",
|
"RuleModule",
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from ...interfaces.led import Led
|
from ...interfaces.led import Led as LedInterface
|
||||||
from ..iotmodule import IotModule
|
from ..iotmodule import IotModule
|
||||||
|
|
||||||
|
|
||||||
class LedModule(IotModule, Led):
|
class Led(IotModule, LedInterface):
|
||||||
"""Implementation of led controls."""
|
"""Implementation of led controls."""
|
||||||
|
|
||||||
def query(self) -> dict:
|
def query(self) -> dict:
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from ...interfaces.lighteffect import LightEffect
|
from ...interfaces.lighteffect import LightEffect as LightEffectInterface
|
||||||
from ..effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1
|
from ..effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1
|
||||||
from ..iotmodule import IotModule
|
from ..iotmodule import IotModule
|
||||||
|
|
||||||
|
|
||||||
class LightEffectModule(IotModule, LightEffect):
|
class LightEffect(IotModule, LightEffectInterface):
|
||||||
"""Implementation of dynamic light effects."""
|
"""Implementation of dynamic light effects."""
|
||||||
|
|
||||||
@property
|
@property
|
@ -15,7 +15,7 @@ from .feature import Feature
|
|||||||
from .modulemapping import ModuleName
|
from .modulemapping import ModuleName
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .device import Device as DeviceType # avoid name clash with Device module
|
from .device import Device
|
||||||
from .interfaces.led import Led
|
from .interfaces.led import Led
|
||||||
from .interfaces.lighteffect import LightEffect
|
from .interfaces.lighteffect import LightEffect
|
||||||
from .iot import modules as iot
|
from .iot import modules as iot
|
||||||
@ -34,8 +34,8 @@ class Module(ABC):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Common Modules
|
# Common Modules
|
||||||
LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffectModule")
|
LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffect")
|
||||||
Led: Final[ModuleName[Led]] = ModuleName("LedModule")
|
Led: Final[ModuleName[Led]] = ModuleName("Led")
|
||||||
|
|
||||||
# IOT only Modules
|
# IOT only Modules
|
||||||
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient")
|
IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient")
|
||||||
@ -49,43 +49,43 @@ class Module(ABC):
|
|||||||
IotTime: Final[ModuleName[iot.Time]] = ModuleName("time")
|
IotTime: Final[ModuleName[iot.Time]] = ModuleName("time")
|
||||||
|
|
||||||
# SMART only Modules
|
# SMART only Modules
|
||||||
Alarm: Final[ModuleName[smart.AlarmModule]] = ModuleName("AlarmModule")
|
Alarm: Final[ModuleName[smart.Alarm]] = ModuleName("Alarm")
|
||||||
AutoOff: Final[ModuleName[smart.AutoOffModule]] = ModuleName("AutoOffModule")
|
AutoOff: Final[ModuleName[smart.AutoOff]] = ModuleName("AutoOff")
|
||||||
BatterySensor: Final[ModuleName[smart.BatterySensor]] = ModuleName("BatterySensor")
|
BatterySensor: Final[ModuleName[smart.BatterySensor]] = ModuleName("BatterySensor")
|
||||||
Brightness: Final[ModuleName[smart.Brightness]] = ModuleName("Brightness")
|
Brightness: Final[ModuleName[smart.Brightness]] = ModuleName("Brightness")
|
||||||
ChildDevice: Final[ModuleName[smart.ChildDeviceModule]] = ModuleName(
|
ChildDevice: Final[ModuleName[smart.ChildDevice]] = ModuleName("ChildDevice")
|
||||||
"ChildDeviceModule"
|
Cloud: Final[ModuleName[smart.Cloud]] = ModuleName("Cloud")
|
||||||
)
|
Color: Final[ModuleName[smart.Color]] = ModuleName("Color")
|
||||||
Cloud: Final[ModuleName[smart.CloudModule]] = ModuleName("CloudModule")
|
ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = ModuleName(
|
||||||
Color: Final[ModuleName[smart.ColorModule]] = ModuleName("ColorModule")
|
"ColorTemperature"
|
||||||
ColorTemp: Final[ModuleName[smart.ColorTemperatureModule]] = ModuleName(
|
|
||||||
"ColorTemperatureModule"
|
|
||||||
)
|
)
|
||||||
ContactSensor: Final[ModuleName[smart.ContactSensor]] = ModuleName("ContactSensor")
|
ContactSensor: Final[ModuleName[smart.ContactSensor]] = ModuleName("ContactSensor")
|
||||||
Device: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule")
|
DeviceModule: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule")
|
||||||
Energy: Final[ModuleName[smart.EnergyModule]] = ModuleName("EnergyModule")
|
Energy: Final[ModuleName[smart.Energy]] = ModuleName("Energy")
|
||||||
Fan: Final[ModuleName[smart.FanModule]] = ModuleName("FanModule")
|
Fan: Final[ModuleName[smart.Fan]] = ModuleName("Fan")
|
||||||
Firmware: Final[ModuleName[smart.Firmware]] = ModuleName("Firmware")
|
Firmware: Final[ModuleName[smart.Firmware]] = ModuleName("Firmware")
|
||||||
FrostProtection: Final[ModuleName[smart.FrostProtectionModule]] = ModuleName(
|
FrostProtection: Final[ModuleName[smart.FrostProtection]] = ModuleName(
|
||||||
"FrostProtectionModule"
|
"FrostProtection"
|
||||||
)
|
)
|
||||||
Humidity: Final[ModuleName[smart.HumiditySensor]] = ModuleName("HumiditySensor")
|
HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = ModuleName(
|
||||||
LightTransition: Final[ModuleName[smart.LightTransitionModule]] = ModuleName(
|
"HumiditySensor"
|
||||||
"LightTransitionModule"
|
|
||||||
)
|
)
|
||||||
Report: Final[ModuleName[smart.ReportModule]] = ModuleName("ReportModule")
|
LightTransition: Final[ModuleName[smart.LightTransition]] = ModuleName(
|
||||||
Temperature: Final[ModuleName[smart.TemperatureSensor]] = ModuleName(
|
"LightTransition"
|
||||||
|
)
|
||||||
|
ReportMode: Final[ModuleName[smart.ReportMode]] = ModuleName("ReportMode")
|
||||||
|
TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = ModuleName(
|
||||||
"TemperatureSensor"
|
"TemperatureSensor"
|
||||||
)
|
)
|
||||||
TemperatureSensor: Final[ModuleName[smart.TemperatureControl]] = ModuleName(
|
TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = ModuleName(
|
||||||
"TemperatureControl"
|
"TemperatureControl"
|
||||||
)
|
)
|
||||||
Time: Final[ModuleName[smart.TimeModule]] = ModuleName("TimeModule")
|
Time: Final[ModuleName[smart.Time]] = ModuleName("Time")
|
||||||
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = ModuleName(
|
WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = ModuleName(
|
||||||
"WaterleakSensor"
|
"WaterleakSensor"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, device: DeviceType, module: str):
|
def __init__(self, device: Device, module: str):
|
||||||
self._device = device
|
self._device = device
|
||||||
self._module = module
|
self._module = module
|
||||||
self._module_features: dict[str, Feature] = {}
|
self._module_features: dict[str, Feature] = {}
|
||||||
|
@ -1,51 +1,51 @@
|
|||||||
"""Modules for SMART devices."""
|
"""Modules for SMART devices."""
|
||||||
|
|
||||||
from .alarmmodule import AlarmModule
|
from .alarm import Alarm
|
||||||
from .autooffmodule import AutoOffModule
|
from .autooff import AutoOff
|
||||||
from .battery import BatterySensor
|
from .batterysensor import BatterySensor
|
||||||
from .brightness import Brightness
|
from .brightness import Brightness
|
||||||
from .childdevicemodule import ChildDeviceModule
|
from .childdevice import ChildDevice
|
||||||
from .cloudmodule import CloudModule
|
from .cloud import Cloud
|
||||||
from .colormodule import ColorModule
|
from .color import Color
|
||||||
from .colortemp import ColorTemperatureModule
|
from .colortemperature import ColorTemperature
|
||||||
from .contact import ContactSensor
|
from .contactsensor import ContactSensor
|
||||||
from .devicemodule import DeviceModule
|
from .devicemodule import DeviceModule
|
||||||
from .energymodule import EnergyModule
|
from .energy import Energy
|
||||||
from .fanmodule import FanModule
|
from .fan import Fan
|
||||||
from .firmware import Firmware
|
from .firmware import Firmware
|
||||||
from .frostprotection import FrostProtectionModule
|
from .frostprotection import FrostProtection
|
||||||
from .humidity import HumiditySensor
|
from .humiditysensor import HumiditySensor
|
||||||
from .ledmodule import LedModule
|
from .led import Led
|
||||||
from .lighteffectmodule import LightEffectModule
|
from .lighteffect import LightEffect
|
||||||
from .lighttransitionmodule import LightTransitionModule
|
from .lighttransition import LightTransition
|
||||||
from .reportmodule import ReportModule
|
from .reportmode import ReportMode
|
||||||
from .temperature import TemperatureSensor
|
|
||||||
from .temperaturecontrol import TemperatureControl
|
from .temperaturecontrol import TemperatureControl
|
||||||
from .timemodule import TimeModule
|
from .temperaturesensor import TemperatureSensor
|
||||||
from .waterleak import WaterleakSensor
|
from .time import Time
|
||||||
|
from .waterleaksensor import WaterleakSensor
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AlarmModule",
|
"Alarm",
|
||||||
"TimeModule",
|
"Time",
|
||||||
"EnergyModule",
|
"Energy",
|
||||||
"DeviceModule",
|
"DeviceModule",
|
||||||
"ChildDeviceModule",
|
"ChildDevice",
|
||||||
"BatterySensor",
|
"BatterySensor",
|
||||||
"HumiditySensor",
|
"HumiditySensor",
|
||||||
"TemperatureSensor",
|
"TemperatureSensor",
|
||||||
"TemperatureControl",
|
"TemperatureControl",
|
||||||
"ReportModule",
|
"ReportMode",
|
||||||
"AutoOffModule",
|
"AutoOff",
|
||||||
"LedModule",
|
"Led",
|
||||||
"Brightness",
|
"Brightness",
|
||||||
"FanModule",
|
"Fan",
|
||||||
"Firmware",
|
"Firmware",
|
||||||
"CloudModule",
|
"Cloud",
|
||||||
"LightEffectModule",
|
"LightEffect",
|
||||||
"LightTransitionModule",
|
"LightTransition",
|
||||||
"ColorTemperatureModule",
|
"ColorTemperature",
|
||||||
"ColorModule",
|
"Color",
|
||||||
"WaterleakSensor",
|
"WaterleakSensor",
|
||||||
"ContactSensor",
|
"ContactSensor",
|
||||||
"FrostProtectionModule",
|
"FrostProtection",
|
||||||
]
|
]
|
||||||
|
@ -6,7 +6,7 @@ from ...feature import Feature
|
|||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
|
|
||||||
class AlarmModule(SmartModule):
|
class Alarm(SmartModule):
|
||||||
"""Implementation of alarm module."""
|
"""Implementation of alarm module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "alarm"
|
REQUIRED_COMPONENT = "alarm"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class AutoOffModule(SmartModule):
|
class AutoOff(SmartModule):
|
||||||
"""Implementation of auto off module."""
|
"""Implementation of auto off module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "auto_off"
|
REQUIRED_COMPONENT = "auto_off"
|
@ -3,7 +3,7 @@
|
|||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
|
|
||||||
class ChildDeviceModule(SmartModule):
|
class ChildDevice(SmartModule):
|
||||||
"""Implementation for child devices."""
|
"""Implementation for child devices."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "child_device"
|
REQUIRED_COMPONENT = "child_device"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class CloudModule(SmartModule):
|
class Cloud(SmartModule):
|
||||||
"""Implementation of cloud module."""
|
"""Implementation of cloud module."""
|
||||||
|
|
||||||
QUERY_GETTER_NAME = "get_connect_cloud_state"
|
QUERY_GETTER_NAME = "get_connect_cloud_state"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class ColorModule(SmartModule):
|
class Color(SmartModule):
|
||||||
"""Implementation of color module."""
|
"""Implementation of color module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "color"
|
REQUIRED_COMPONENT = "color"
|
@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
DEFAULT_TEMP_RANGE = [2500, 6500]
|
DEFAULT_TEMP_RANGE = [2500, 6500]
|
||||||
|
|
||||||
|
|
||||||
class ColorTemperatureModule(SmartModule):
|
class ColorTemperature(SmartModule):
|
||||||
"""Implementation of color temp module."""
|
"""Implementation of color temp module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "color_temperature"
|
REQUIRED_COMPONENT = "color_temperature"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class EnergyModule(SmartModule):
|
class Energy(SmartModule):
|
||||||
"""Implementation of energy monitoring module."""
|
"""Implementation of energy monitoring module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "energy_monitoring"
|
REQUIRED_COMPONENT = "energy_monitoring"
|
@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class FanModule(SmartModule):
|
class Fan(SmartModule):
|
||||||
"""Implementation of fan_control module."""
|
"""Implementation of fan_control module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "fan_control"
|
REQUIRED_COMPONENT = "fan_control"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class FrostProtectionModule(SmartModule):
|
class FrostProtection(SmartModule):
|
||||||
"""Implementation for frost protection module.
|
"""Implementation for frost protection module.
|
||||||
|
|
||||||
This basically turns the thermostat on and off.
|
This basically turns the thermostat on and off.
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from ...interfaces.led import Led
|
from ...interfaces.led import Led as LedInterface
|
||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
|
|
||||||
class LedModule(SmartModule, Led):
|
class Led(SmartModule, LedInterface):
|
||||||
"""Implementation of led controls."""
|
"""Implementation of led controls."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "led"
|
REQUIRED_COMPONENT = "led"
|
@ -6,14 +6,14 @@ import base64
|
|||||||
import copy
|
import copy
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from ...interfaces.lighteffect import LightEffect
|
from ...interfaces.lighteffect import LightEffect as LightEffectInterface
|
||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class LightEffectModule(SmartModule, LightEffect):
|
class LightEffect(SmartModule, LightEffectInterface):
|
||||||
"""Implementation of dynamic light effects."""
|
"""Implementation of dynamic light effects."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "light_effect"
|
REQUIRED_COMPONENT = "light_effect"
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class LightTransitionModule(SmartModule):
|
class LightTransition(SmartModule):
|
||||||
"""Implementation of gradual on/off."""
|
"""Implementation of gradual on/off."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "on_off_gradually"
|
REQUIRED_COMPONENT = "on_off_gradually"
|
@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class ReportModule(SmartModule):
|
class ReportMode(SmartModule):
|
||||||
"""Implementation of report module."""
|
"""Implementation of report module."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "report_mode"
|
REQUIRED_COMPONENT = "report_mode"
|
@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|||||||
from ..smartdevice import SmartDevice
|
from ..smartdevice import SmartDevice
|
||||||
|
|
||||||
|
|
||||||
class TimeModule(SmartModule):
|
class Time(SmartModule):
|
||||||
"""Implementation of device_local_time."""
|
"""Implementation of device_local_time."""
|
||||||
|
|
||||||
REQUIRED_COMPONENT = "time"
|
REQUIRED_COMPONENT = "time"
|
@ -20,15 +20,10 @@ from ..module import Module
|
|||||||
from ..modulemapping import ModuleMapping, ModuleName
|
from ..modulemapping import ModuleMapping, ModuleName
|
||||||
from ..smartprotocol import SmartProtocol
|
from ..smartprotocol import SmartProtocol
|
||||||
from .modules import (
|
from .modules import (
|
||||||
Brightness,
|
Cloud,
|
||||||
CloudModule,
|
|
||||||
ColorModule,
|
|
||||||
ColorTemperatureModule,
|
|
||||||
DeviceModule,
|
DeviceModule,
|
||||||
EnergyModule,
|
|
||||||
FanModule,
|
|
||||||
Firmware,
|
Firmware,
|
||||||
TimeModule,
|
Time,
|
||||||
)
|
)
|
||||||
from .smartmodule import SmartModule
|
from .smartmodule import SmartModule
|
||||||
|
|
||||||
@ -39,7 +34,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
# the child but only work on the parent. See longer note below in _initialize_modules.
|
# the child but only work on the parent. See longer note below in _initialize_modules.
|
||||||
# This list should be updated when creating new modules that could have the
|
# This list should be updated when creating new modules that could have the
|
||||||
# same issue, homekit perhaps?
|
# same issue, homekit perhaps?
|
||||||
WALL_SWITCH_PARENT_ONLY_MODULES = [DeviceModule, TimeModule, Firmware, CloudModule]
|
WALL_SWITCH_PARENT_ONLY_MODULES = [DeviceModule, Time, Firmware, Cloud]
|
||||||
|
|
||||||
|
|
||||||
# Device must go last as the other interfaces also inherit Device
|
# Device must go last as the other interfaces also inherit Device
|
||||||
@ -329,11 +324,11 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
self._add_feature(feat)
|
self._add_feature(feat)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_cloud_connected(self):
|
def is_cloud_connected(self) -> bool:
|
||||||
"""Returns if the device is connected to the cloud."""
|
"""Returns if the device is connected to the cloud."""
|
||||||
if "CloudModule" not in self.modules:
|
if Module.Cloud not in self.modules:
|
||||||
return False
|
return False
|
||||||
return self.modules["CloudModule"].is_connected
|
return self.modules[Module.Cloud].is_connected
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sys_info(self) -> dict[str, Any]:
|
def sys_info(self) -> dict[str, Any]:
|
||||||
@ -357,10 +352,10 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
def time(self) -> datetime:
|
def time(self) -> datetime:
|
||||||
"""Return the time."""
|
"""Return the time."""
|
||||||
# TODO: Default to parent's time module for child devices
|
# TODO: Default to parent's time module for child devices
|
||||||
if self._parent and "TimeModule" in self.modules:
|
if self._parent and Module.Time in self.modules:
|
||||||
_timemod = cast(TimeModule, self._parent.modules["TimeModule"]) # noqa: F405
|
_timemod = self._parent.modules[Module.Time]
|
||||||
else:
|
else:
|
||||||
_timemod = cast(TimeModule, self.modules["TimeModule"]) # noqa: F405
|
_timemod = self.modules[Module.Time]
|
||||||
|
|
||||||
return _timemod.time
|
return _timemod.time
|
||||||
|
|
||||||
@ -437,7 +432,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
@property
|
@property
|
||||||
def has_emeter(self) -> bool:
|
def has_emeter(self) -> bool:
|
||||||
"""Return if the device has emeter."""
|
"""Return if the device has emeter."""
|
||||||
return "EnergyModule" in self.modules
|
return Module.Energy in self.modules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_dimmer(self) -> bool:
|
def is_dimmer(self) -> bool:
|
||||||
@ -479,19 +474,19 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
@property
|
@property
|
||||||
def emeter_realtime(self) -> EmeterStatus:
|
def emeter_realtime(self) -> EmeterStatus:
|
||||||
"""Get the emeter status."""
|
"""Get the emeter status."""
|
||||||
energy = cast(EnergyModule, self.modules["EnergyModule"])
|
energy = self.modules[Module.Energy]
|
||||||
return energy.emeter_realtime
|
return energy.emeter_realtime
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def emeter_this_month(self) -> float | None:
|
def emeter_this_month(self) -> float | None:
|
||||||
"""Get the emeter value for this month."""
|
"""Get the emeter value for this month."""
|
||||||
energy = cast(EnergyModule, self.modules["EnergyModule"])
|
energy = self.modules[Module.Energy]
|
||||||
return energy.emeter_this_month
|
return energy.emeter_this_month
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def emeter_today(self) -> float | None:
|
def emeter_today(self) -> float | None:
|
||||||
"""Get the emeter value for today."""
|
"""Get the emeter value for today."""
|
||||||
energy = cast(EnergyModule, self.modules["EnergyModule"])
|
energy = self.modules[Module.Energy]
|
||||||
return energy.emeter_today
|
return energy.emeter_today
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -503,8 +498,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
):
|
):
|
||||||
return None
|
return None
|
||||||
on_time = cast(float, on_time)
|
on_time = cast(float, on_time)
|
||||||
if (timemod := self.modules.get("TimeModule")) is not None:
|
if (timemod := self.modules.get(Module.Time)) is not None:
|
||||||
timemod = cast(TimeModule, timemod) # noqa: F405
|
|
||||||
return timemod.time - timedelta(seconds=on_time)
|
return timemod.time - timedelta(seconds=on_time)
|
||||||
else: # We have no device time, use current local time.
|
else: # We have no device time, use current local time.
|
||||||
return datetime.now().replace(microsecond=0) - timedelta(seconds=on_time)
|
return datetime.now().replace(microsecond=0) - timedelta(seconds=on_time)
|
||||||
@ -650,37 +644,37 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
@property
|
@property
|
||||||
def is_fan(self) -> bool:
|
def is_fan(self) -> bool:
|
||||||
"""Return True if the device is a fan."""
|
"""Return True if the device is a fan."""
|
||||||
return "FanModule" in self.modules
|
return Module.Fan in self.modules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_speed_level(self) -> int:
|
def fan_speed_level(self) -> int:
|
||||||
"""Return fan speed level."""
|
"""Return fan speed level."""
|
||||||
if not self.is_fan:
|
if not self.is_fan:
|
||||||
raise KasaException("Device is not a Fan")
|
raise KasaException("Device is not a Fan")
|
||||||
return cast(FanModule, self.modules["FanModule"]).fan_speed_level
|
return self.modules[Module.Fan].fan_speed_level
|
||||||
|
|
||||||
async def set_fan_speed_level(self, level: int):
|
async def set_fan_speed_level(self, level: int):
|
||||||
"""Set fan speed level."""
|
"""Set fan speed level."""
|
||||||
if not self.is_fan:
|
if not self.is_fan:
|
||||||
raise KasaException("Device is not a Fan")
|
raise KasaException("Device is not a Fan")
|
||||||
await cast(FanModule, self.modules["FanModule"]).set_fan_speed_level(level)
|
await self.modules[Module.Fan].set_fan_speed_level(level)
|
||||||
|
|
||||||
# Bulb interface methods
|
# Bulb interface methods
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_color(self) -> bool:
|
def is_color(self) -> bool:
|
||||||
"""Whether the bulb supports color changes."""
|
"""Whether the bulb supports color changes."""
|
||||||
return "ColorModule" in self.modules
|
return Module.Color in self.modules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_dimmable(self) -> bool:
|
def is_dimmable(self) -> bool:
|
||||||
"""Whether the bulb supports brightness changes."""
|
"""Whether the bulb supports brightness changes."""
|
||||||
return "Brightness" in self.modules
|
return Module.Brightness in self.modules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_variable_color_temp(self) -> bool:
|
def is_variable_color_temp(self) -> bool:
|
||||||
"""Whether the bulb supports color temperature changes."""
|
"""Whether the bulb supports color temperature changes."""
|
||||||
return "ColorTemperatureModule" in self.modules
|
return Module.ColorTemperature in self.modules
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def valid_temperature_range(self) -> ColorTempRange:
|
def valid_temperature_range(self) -> ColorTempRange:
|
||||||
@ -691,9 +685,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_variable_color_temp:
|
if not self.is_variable_color_temp:
|
||||||
raise KasaException("Color temperature not supported")
|
raise KasaException("Color temperature not supported")
|
||||||
|
|
||||||
return cast(
|
return self.modules[Module.ColorTemperature].valid_temperature_range
|
||||||
ColorTemperatureModule, self.modules["ColorTemperatureModule"]
|
|
||||||
).valid_temperature_range
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hsv(self) -> HSV:
|
def hsv(self) -> HSV:
|
||||||
@ -704,7 +696,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_color:
|
if not self.is_color:
|
||||||
raise KasaException("Bulb does not support color.")
|
raise KasaException("Bulb does not support color.")
|
||||||
|
|
||||||
return cast(ColorModule, self.modules["ColorModule"]).hsv
|
return self.modules[Module.Color].hsv
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def color_temp(self) -> int:
|
def color_temp(self) -> int:
|
||||||
@ -712,9 +704,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_variable_color_temp:
|
if not self.is_variable_color_temp:
|
||||||
raise KasaException("Bulb does not support colortemp.")
|
raise KasaException("Bulb does not support colortemp.")
|
||||||
|
|
||||||
return cast(
|
return self.modules[Module.ColorTemperature].color_temp
|
||||||
ColorTemperatureModule, self.modules["ColorTemperatureModule"]
|
|
||||||
).color_temp
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self) -> int:
|
def brightness(self) -> int:
|
||||||
@ -722,7 +712,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_dimmable: # pragma: no cover
|
if not self.is_dimmable: # pragma: no cover
|
||||||
raise KasaException("Bulb is not dimmable.")
|
raise KasaException("Bulb is not dimmable.")
|
||||||
|
|
||||||
return cast(Brightness, self.modules["Brightness"]).brightness
|
return self.modules[Module.Brightness].brightness
|
||||||
|
|
||||||
async def set_hsv(
|
async def set_hsv(
|
||||||
self,
|
self,
|
||||||
@ -744,9 +734,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_color:
|
if not self.is_color:
|
||||||
raise KasaException("Bulb does not support color.")
|
raise KasaException("Bulb does not support color.")
|
||||||
|
|
||||||
return await cast(ColorModule, self.modules["ColorModule"]).set_hsv(
|
return await self.modules[Module.Color].set_hsv(hue, saturation, value)
|
||||||
hue, saturation, value
|
|
||||||
)
|
|
||||||
|
|
||||||
async def set_color_temp(
|
async def set_color_temp(
|
||||||
self, temp: int, *, brightness=None, transition: int | None = None
|
self, temp: int, *, brightness=None, transition: int | None = None
|
||||||
@ -760,9 +748,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
"""
|
"""
|
||||||
if not self.is_variable_color_temp:
|
if not self.is_variable_color_temp:
|
||||||
raise KasaException("Bulb does not support colortemp.")
|
raise KasaException("Bulb does not support colortemp.")
|
||||||
return await cast(
|
return await self.modules[Module.ColorTemperature].set_color_temp(temp)
|
||||||
ColorTemperatureModule, self.modules["ColorTemperatureModule"]
|
|
||||||
).set_color_temp(temp)
|
|
||||||
|
|
||||||
async def set_brightness(
|
async def set_brightness(
|
||||||
self, brightness: int, *, transition: int | None = None
|
self, brightness: int, *, transition: int | None = None
|
||||||
@ -777,9 +763,7 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
if not self.is_dimmable: # pragma: no cover
|
if not self.is_dimmable: # pragma: no cover
|
||||||
raise KasaException("Bulb is not dimmable.")
|
raise KasaException("Bulb is not dimmable.")
|
||||||
|
|
||||||
return await cast(Brightness, self.modules["Brightness"]).set_brightness(
|
return await self.modules[Module.Brightness].set_brightness(brightness)
|
||||||
brightness
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def presets(self) -> list[BulbPreset]:
|
def presets(self) -> list[BulbPreset]:
|
||||||
@ -789,4 +773,4 @@ class SmartDevice(Bulb, Fan, Device):
|
|||||||
@property
|
@property
|
||||||
def has_effects(self) -> bool:
|
def has_effects(self) -> bool:
|
||||||
"""Return True if the device supports effects."""
|
"""Return True if the device supports effects."""
|
||||||
return "LightEffectModule" in self.modules
|
return Module.LightEffect in self.modules
|
||||||
|
@ -6,7 +6,7 @@ import pytest
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from kasa import Device, Feature, Module
|
from kasa import Device, Feature, Module
|
||||||
from kasa.smart.modules import LightEffectModule
|
from kasa.smart.modules import LightEffect
|
||||||
from kasa.tests.device_fixtures import parametrize
|
from kasa.tests.device_fixtures import parametrize
|
||||||
|
|
||||||
light_effect = parametrize(
|
light_effect = parametrize(
|
||||||
@ -18,7 +18,7 @@ light_effect = parametrize(
|
|||||||
async def test_light_effect(dev: Device, mocker: MockerFixture):
|
async def test_light_effect(dev: Device, mocker: MockerFixture):
|
||||||
"""Test light effect."""
|
"""Test light effect."""
|
||||||
light_effect = dev.modules.get(Module.LightEffect)
|
light_effect = dev.modules.get(Module.LightEffect)
|
||||||
assert isinstance(light_effect, LightEffectModule)
|
assert isinstance(light_effect, LightEffect)
|
||||||
|
|
||||||
feature = light_effect._module_features["light_effect"]
|
feature = light_effect._module_features["light_effect"]
|
||||||
assert feature.type == Feature.Type.Choice
|
assert feature.type == Feature.Type.Choice
|
||||||
@ -28,7 +28,7 @@ async def test_light_effect(dev: Device, mocker: MockerFixture):
|
|||||||
assert feature.choices
|
assert feature.choices
|
||||||
for effect in chain(reversed(feature.choices), feature.choices):
|
for effect in chain(reversed(feature.choices), feature.choices):
|
||||||
await light_effect.set_effect(effect)
|
await light_effect.set_effect(effect)
|
||||||
enable = effect != LightEffectModule.LIGHT_EFFECTS_OFF
|
enable = effect != LightEffect.LIGHT_EFFECTS_OFF
|
||||||
params: dict[str, bool | str] = {"enable": enable}
|
params: dict[str, bool | str] = {"enable": enable}
|
||||||
if enable:
|
if enable:
|
||||||
params["id"] = light_effect._scenes_names_to_id[effect]
|
params["id"] = light_effect._scenes_names_to_id[effect]
|
||||||
|
@ -737,7 +737,7 @@ async def test_feature_set(mocker, runner):
|
|||||||
dummy_device = await get_device_for_fixture_protocol(
|
dummy_device = await get_device_for_fixture_protocol(
|
||||||
"P300(EU)_1.0_1.0.13.json", "SMART"
|
"P300(EU)_1.0_1.0.13.json", "SMART"
|
||||||
)
|
)
|
||||||
led_setter = mocker.patch("kasa.smart.modules.ledmodule.LedModule.set_led")
|
led_setter = mocker.patch("kasa.smart.modules.led.Led.set_led")
|
||||||
mocker.patch("kasa.discover.Discover.discover_single", return_value=dummy_device)
|
mocker.patch("kasa.discover.Discover.discover_single", return_value=dummy_device)
|
||||||
|
|
||||||
res = await runner.invoke(
|
res = await runner.invoke(
|
||||||
|
@ -127,21 +127,21 @@ async def test_get_modules():
|
|||||||
dummy_device = await get_device_for_fixture_protocol(
|
dummy_device = await get_device_for_fixture_protocol(
|
||||||
"KS240(US)_1.0_1.0.5.json", "SMART"
|
"KS240(US)_1.0_1.0.5.json", "SMART"
|
||||||
)
|
)
|
||||||
from kasa.smart.modules import CloudModule
|
from kasa.smart.modules import Cloud
|
||||||
|
|
||||||
# Modules on device
|
# Modules on device
|
||||||
module = dummy_device.modules.get("CloudModule")
|
module = dummy_device.modules.get("Cloud")
|
||||||
assert module
|
assert module
|
||||||
assert module._device == dummy_device
|
assert module._device == dummy_device
|
||||||
assert isinstance(module, CloudModule)
|
assert isinstance(module, Cloud)
|
||||||
|
|
||||||
module = dummy_device.modules.get(Module.Cloud)
|
module = dummy_device.modules.get(Module.Cloud)
|
||||||
assert module
|
assert module
|
||||||
assert module._device == dummy_device
|
assert module._device == dummy_device
|
||||||
assert isinstance(module, CloudModule)
|
assert isinstance(module, Cloud)
|
||||||
|
|
||||||
# Modules on child
|
# Modules on child
|
||||||
module = dummy_device.modules.get("FanModule")
|
module = dummy_device.modules.get("Fan")
|
||||||
assert module
|
assert module
|
||||||
assert module._device != dummy_device
|
assert module._device != dummy_device
|
||||||
assert module._device._parent == dummy_device
|
assert module._device._parent == dummy_device
|
||||||
|
Loading…
x
Reference in New Issue
Block a user