diff --git a/kasa/iot/iotbulb.py b/kasa/iot/iotbulb.py index 6819d94b..92bf9814 100644 --- a/kasa/iot/iotbulb.py +++ b/kasa/iot/iotbulb.py @@ -13,6 +13,7 @@ from ..bulb import HSV, Bulb, BulbPreset, ColorTempRange from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..feature import Feature +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import IotDevice, KasaException, requires_update from .modules import Antitheft, Cloud, Countdown, Emeter, Schedule, Time, Usage @@ -198,13 +199,17 @@ class IotBulb(IotDevice, Bulb): ) -> None: super().__init__(host=host, config=config, protocol=protocol) self._device_type = DeviceType.Bulb - self.add_module("schedule", Schedule(self, "smartlife.iot.common.schedule")) - self.add_module("usage", Usage(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("emeter", Emeter(self, self.emeter_type)) - self.add_module("countdown", Countdown(self, "countdown")) - self.add_module("cloud", Cloud(self, "smartlife.iot.common.cloud")) + self.add_module( + Module.IotSchedule, Schedule(self, "smartlife.iot.common.schedule") + ) + self.add_module(Module.IotUsage, Usage(self, "smartlife.iot.common.schedule")) + self.add_module( + Module.IotAntitheft, Antitheft(self, "smartlife.iot.common.anti_theft") + ) + 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): await super()._initialize_features() diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 762fc06c..e4c1bb13 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -30,7 +30,7 @@ from ..module import Module from ..modulemapping import ModuleMapping, ModuleName from ..protocol import BaseProtocol from .iotmodule import IotModule -from .modules import Emeter, Time +from .modules import Emeter _LOGGER = logging.getLogger(__name__) @@ -347,7 +347,7 @@ class IotDevice(Device): _LOGGER.debug( "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, # making separate handling for this unnecessary @@ -440,27 +440,27 @@ class IotDevice(Device): @requires_update def time(self) -> datetime: """Return current time from the device.""" - return cast(Time, self.modules["time"]).time + return self.modules[Module.IotTime].time @property @requires_update def timezone(self) -> dict: """Return the current timezone.""" - return cast(Time, self.modules["time"]).timezone + return self.modules[Module.IotTime].timezone async def get_time(self) -> datetime | None: """Return current time from the device, if available.""" _LOGGER.warning( "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: """Return timezone information.""" _LOGGER.warning( "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 @requires_update @@ -541,26 +541,26 @@ class IotDevice(Device): def emeter_realtime(self) -> EmeterStatus: """Return current energy readings.""" 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: """Retrieve current energy readings.""" self._verify_emeter() - return EmeterStatus(await cast(Emeter, self.modules["emeter"]).get_realtime()) + return EmeterStatus(await self.modules[Module.IotEmeter].get_realtime()) @property @requires_update def emeter_today(self) -> float | None: """Return today's energy consumption in kWh.""" self._verify_emeter() - return cast(Emeter, self.modules["emeter"]).emeter_today + return self.modules[Module.IotEmeter].emeter_today @property @requires_update def emeter_this_month(self) -> float | None: """Return this month's energy consumption in kWh.""" 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( 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 """ 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 ) @@ -589,15 +589,13 @@ class IotDevice(Device): :return: dict: mapping of month to value """ self._verify_emeter() - return await cast(Emeter, self.modules["emeter"]).get_monthstat( - year=year, kwh=kwh - ) + return await self.modules[Module.IotEmeter].get_monthstat(year=year, kwh=kwh) @requires_update async def erase_emeter_stats(self) -> dict: """Erase energy meter statistics.""" self._verify_emeter() - return await cast(Emeter, self.modules["emeter"]).erase_stats() + return await self.modules[Module.IotEmeter].erase_stats() @requires_update async def current_consumption(self) -> float: diff --git a/kasa/iot/iotdimmer.py b/kasa/iot/iotdimmer.py index cfe937b8..fed9e7e7 100644 --- a/kasa/iot/iotdimmer.py +++ b/kasa/iot/iotdimmer.py @@ -8,6 +8,7 @@ from typing import Any from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..feature import Feature +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import KasaException, requires_update from .iotplug import IotPlug @@ -81,8 +82,8 @@ class IotDimmer(IotPlug): 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 - self.add_module("motion", Motion(self, "smartlife.iot.PIR")) - self.add_module("ambient", AmbientLight(self, "smartlife.iot.LAS")) + self.add_module(Module.IotMotion, Motion(self, "smartlife.iot.PIR")) + self.add_module(Module.IotAmbientLight, AmbientLight(self, "smartlife.iot.LAS")) async def _initialize_features(self): await super()._initialize_features() diff --git a/kasa/iot/iotlightstrip.py b/kasa/iot/iotlightstrip.py index a120be7a..7cdbe43b 100644 --- a/kasa/iot/iotlightstrip.py +++ b/kasa/iot/iotlightstrip.py @@ -9,7 +9,7 @@ from ..protocol import BaseProtocol from .effects import EFFECT_NAMES_V1 from .iotbulb import IotBulb from .iotdevice import KasaException, requires_update -from .modules.lighteffectmodule import LightEffectModule +from .modules.lighteffect import LightEffect class IotLightStrip(IotBulb): @@ -58,7 +58,7 @@ class IotLightStrip(IotBulb): self._device_type = DeviceType.LightStrip self.add_module( Module.LightEffect, - LightEffectModule(self, "smartlife.iot.lighting_effect"), + LightEffect(self, "smartlife.iot.lighting_effect"), ) @property # type: ignore diff --git a/kasa/iot/iotplug.py b/kasa/iot/iotplug.py index 22238c7a..6aace4f8 100644 --- a/kasa/iot/iotplug.py +++ b/kasa/iot/iotplug.py @@ -9,7 +9,7 @@ from ..deviceconfig import DeviceConfig from ..module import Module from ..protocol import BaseProtocol 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__) @@ -53,12 +53,12 @@ class IotPlug(IotDevice): ) -> None: super().__init__(host=host, config=config, protocol=protocol) self._device_type = DeviceType.Plug - self.add_module("schedule", Schedule(self, "schedule")) - self.add_module("usage", Usage(self, "schedule")) - self.add_module("antitheft", Antitheft(self, "anti_theft")) - self.add_module("time", Time(self, "time")) - self.add_module("cloud", Cloud(self, "cnCloud")) - self.add_module(Module.Led, LedModule(self, "system")) + self.add_module(Module.IotSchedule, Schedule(self, "schedule")) + self.add_module(Module.IotUsage, Usage(self, "schedule")) + self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft")) + self.add_module(Module.IotTime, Time(self, "time")) + self.add_module(Module.IotCloud, Cloud(self, "cnCloud")) + self.add_module(Module.Led, Led(self, "system")) @property # type: ignore @requires_update diff --git a/kasa/iot/iotstrip.py b/kasa/iot/iotstrip.py index ab14abb0..4aa966e1 100755 --- a/kasa/iot/iotstrip.py +++ b/kasa/iot/iotstrip.py @@ -10,6 +10,7 @@ from typing import Any from ..device_type import DeviceType from ..deviceconfig import DeviceConfig from ..exceptions import KasaException +from ..module import Module from ..protocol import BaseProtocol from .iotdevice import ( EmeterStatus, @@ -95,11 +96,11 @@ class IotStrip(IotDevice): super().__init__(host=host, config=config, protocol=protocol) self.emeter_type = "emeter" self._device_type = DeviceType.Strip - self.add_module("antitheft", Antitheft(self, "anti_theft")) - self.add_module("schedule", Schedule(self, "schedule")) - self.add_module("usage", Usage(self, "schedule")) - self.add_module("time", Time(self, "time")) - self.add_module("countdown", Countdown(self, "countdown")) + self.add_module(Module.IotAntitheft, Antitheft(self, "anti_theft")) + self.add_module(Module.IotSchedule, Schedule(self, "schedule")) + self.add_module(Module.IotUsage, Usage(self, "schedule")) + self.add_module(Module.IotTime, Time(self, "time")) + self.add_module(Module.IotCountdown, Countdown(self, "countdown")) @property # type: ignore @requires_update diff --git a/kasa/iot/modules/__init__.py b/kasa/iot/modules/__init__.py index f061e607..e0febfd4 100644 --- a/kasa/iot/modules/__init__.py +++ b/kasa/iot/modules/__init__.py @@ -5,7 +5,8 @@ from .antitheft import Antitheft from .cloud import Cloud from .countdown import Countdown from .emeter import Emeter -from .ledmodule import LedModule +from .led import Led +from .lighteffect import LightEffect from .motion import Motion from .rulemodule import Rule, RuleModule from .schedule import Schedule @@ -18,7 +19,8 @@ __all__ = [ "Cloud", "Countdown", "Emeter", - "LedModule", + "Led", + "LightEffect", "Motion", "Rule", "RuleModule", diff --git a/kasa/iot/modules/ledmodule.py b/kasa/iot/modules/led.py similarity index 89% rename from kasa/iot/modules/ledmodule.py rename to kasa/iot/modules/led.py index 6b3c6194..6c4ca02a 100644 --- a/kasa/iot/modules/ledmodule.py +++ b/kasa/iot/modules/led.py @@ -2,11 +2,11 @@ from __future__ import annotations -from ...interfaces.led import Led +from ...interfaces.led import Led as LedInterface from ..iotmodule import IotModule -class LedModule(IotModule, Led): +class Led(IotModule, LedInterface): """Implementation of led controls.""" def query(self) -> dict: diff --git a/kasa/iot/modules/lighteffectmodule.py b/kasa/iot/modules/lighteffect.py similarity index 95% rename from kasa/iot/modules/lighteffectmodule.py rename to kasa/iot/modules/lighteffect.py index c53de192..2d40fb54 100644 --- a/kasa/iot/modules/lighteffectmodule.py +++ b/kasa/iot/modules/lighteffect.py @@ -2,12 +2,12 @@ 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 ..iotmodule import IotModule -class LightEffectModule(IotModule, LightEffect): +class LightEffect(IotModule, LightEffectInterface): """Implementation of dynamic light effects.""" @property diff --git a/kasa/module.py b/kasa/module.py index b65f0499..55eeea18 100644 --- a/kasa/module.py +++ b/kasa/module.py @@ -15,7 +15,7 @@ from .feature import Feature from .modulemapping import ModuleName 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.lighteffect import LightEffect from .iot import modules as iot @@ -34,8 +34,8 @@ class Module(ABC): """ # Common Modules - LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffectModule") - Led: Final[ModuleName[Led]] = ModuleName("LedModule") + LightEffect: Final[ModuleName[LightEffect]] = ModuleName("LightEffect") + Led: Final[ModuleName[Led]] = ModuleName("Led") # IOT only Modules IotAmbientLight: Final[ModuleName[iot.AmbientLight]] = ModuleName("ambient") @@ -49,43 +49,43 @@ class Module(ABC): IotTime: Final[ModuleName[iot.Time]] = ModuleName("time") # SMART only Modules - Alarm: Final[ModuleName[smart.AlarmModule]] = ModuleName("AlarmModule") - AutoOff: Final[ModuleName[smart.AutoOffModule]] = ModuleName("AutoOffModule") + Alarm: Final[ModuleName[smart.Alarm]] = ModuleName("Alarm") + AutoOff: Final[ModuleName[smart.AutoOff]] = ModuleName("AutoOff") BatterySensor: Final[ModuleName[smart.BatterySensor]] = ModuleName("BatterySensor") Brightness: Final[ModuleName[smart.Brightness]] = ModuleName("Brightness") - ChildDevice: Final[ModuleName[smart.ChildDeviceModule]] = ModuleName( - "ChildDeviceModule" - ) - Cloud: Final[ModuleName[smart.CloudModule]] = ModuleName("CloudModule") - Color: Final[ModuleName[smart.ColorModule]] = ModuleName("ColorModule") - ColorTemp: Final[ModuleName[smart.ColorTemperatureModule]] = ModuleName( - "ColorTemperatureModule" + ChildDevice: Final[ModuleName[smart.ChildDevice]] = ModuleName("ChildDevice") + Cloud: Final[ModuleName[smart.Cloud]] = ModuleName("Cloud") + Color: Final[ModuleName[smart.Color]] = ModuleName("Color") + ColorTemperature: Final[ModuleName[smart.ColorTemperature]] = ModuleName( + "ColorTemperature" ) ContactSensor: Final[ModuleName[smart.ContactSensor]] = ModuleName("ContactSensor") - Device: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule") - Energy: Final[ModuleName[smart.EnergyModule]] = ModuleName("EnergyModule") - Fan: Final[ModuleName[smart.FanModule]] = ModuleName("FanModule") + DeviceModule: Final[ModuleName[smart.DeviceModule]] = ModuleName("DeviceModule") + Energy: Final[ModuleName[smart.Energy]] = ModuleName("Energy") + Fan: Final[ModuleName[smart.Fan]] = ModuleName("Fan") Firmware: Final[ModuleName[smart.Firmware]] = ModuleName("Firmware") - FrostProtection: Final[ModuleName[smart.FrostProtectionModule]] = ModuleName( - "FrostProtectionModule" + FrostProtection: Final[ModuleName[smart.FrostProtection]] = ModuleName( + "FrostProtection" ) - Humidity: Final[ModuleName[smart.HumiditySensor]] = ModuleName("HumiditySensor") - LightTransition: Final[ModuleName[smart.LightTransitionModule]] = ModuleName( - "LightTransitionModule" + HumiditySensor: Final[ModuleName[smart.HumiditySensor]] = ModuleName( + "HumiditySensor" ) - Report: Final[ModuleName[smart.ReportModule]] = ModuleName("ReportModule") - Temperature: Final[ModuleName[smart.TemperatureSensor]] = ModuleName( + LightTransition: Final[ModuleName[smart.LightTransition]] = ModuleName( + "LightTransition" + ) + ReportMode: Final[ModuleName[smart.ReportMode]] = ModuleName("ReportMode") + TemperatureSensor: Final[ModuleName[smart.TemperatureSensor]] = ModuleName( "TemperatureSensor" ) - TemperatureSensor: Final[ModuleName[smart.TemperatureControl]] = ModuleName( + TemperatureControl: Final[ModuleName[smart.TemperatureControl]] = ModuleName( "TemperatureControl" ) - Time: Final[ModuleName[smart.TimeModule]] = ModuleName("TimeModule") + Time: Final[ModuleName[smart.Time]] = ModuleName("Time") WaterleakSensor: Final[ModuleName[smart.WaterleakSensor]] = ModuleName( "WaterleakSensor" ) - def __init__(self, device: DeviceType, module: str): + def __init__(self, device: Device, module: str): self._device = device self._module = module self._module_features: dict[str, Feature] = {} diff --git a/kasa/smart/modules/__init__.py b/kasa/smart/modules/__init__.py index b0956b80..e119e067 100644 --- a/kasa/smart/modules/__init__.py +++ b/kasa/smart/modules/__init__.py @@ -1,51 +1,51 @@ """Modules for SMART devices.""" -from .alarmmodule import AlarmModule -from .autooffmodule import AutoOffModule -from .battery import BatterySensor +from .alarm import Alarm +from .autooff import AutoOff +from .batterysensor import BatterySensor from .brightness import Brightness -from .childdevicemodule import ChildDeviceModule -from .cloudmodule import CloudModule -from .colormodule import ColorModule -from .colortemp import ColorTemperatureModule -from .contact import ContactSensor +from .childdevice import ChildDevice +from .cloud import Cloud +from .color import Color +from .colortemperature import ColorTemperature +from .contactsensor import ContactSensor from .devicemodule import DeviceModule -from .energymodule import EnergyModule -from .fanmodule import FanModule +from .energy import Energy +from .fan import Fan from .firmware import Firmware -from .frostprotection import FrostProtectionModule -from .humidity import HumiditySensor -from .ledmodule import LedModule -from .lighteffectmodule import LightEffectModule -from .lighttransitionmodule import LightTransitionModule -from .reportmodule import ReportModule -from .temperature import TemperatureSensor +from .frostprotection import FrostProtection +from .humiditysensor import HumiditySensor +from .led import Led +from .lighteffect import LightEffect +from .lighttransition import LightTransition +from .reportmode import ReportMode from .temperaturecontrol import TemperatureControl -from .timemodule import TimeModule -from .waterleak import WaterleakSensor +from .temperaturesensor import TemperatureSensor +from .time import Time +from .waterleaksensor import WaterleakSensor __all__ = [ - "AlarmModule", - "TimeModule", - "EnergyModule", + "Alarm", + "Time", + "Energy", "DeviceModule", - "ChildDeviceModule", + "ChildDevice", "BatterySensor", "HumiditySensor", "TemperatureSensor", "TemperatureControl", - "ReportModule", - "AutoOffModule", - "LedModule", + "ReportMode", + "AutoOff", + "Led", "Brightness", - "FanModule", + "Fan", "Firmware", - "CloudModule", - "LightEffectModule", - "LightTransitionModule", - "ColorTemperatureModule", - "ColorModule", + "Cloud", + "LightEffect", + "LightTransition", + "ColorTemperature", + "Color", "WaterleakSensor", "ContactSensor", - "FrostProtectionModule", + "FrostProtection", ] diff --git a/kasa/smart/modules/alarmmodule.py b/kasa/smart/modules/alarm.py similarity index 99% rename from kasa/smart/modules/alarmmodule.py rename to kasa/smart/modules/alarm.py index 845eb65a..f033496a 100644 --- a/kasa/smart/modules/alarmmodule.py +++ b/kasa/smart/modules/alarm.py @@ -6,7 +6,7 @@ from ...feature import Feature from ..smartmodule import SmartModule -class AlarmModule(SmartModule): +class Alarm(SmartModule): """Implementation of alarm module.""" REQUIRED_COMPONENT = "alarm" diff --git a/kasa/smart/modules/autooffmodule.py b/kasa/smart/modules/autooff.py similarity index 98% rename from kasa/smart/modules/autooffmodule.py rename to kasa/smart/modules/autooff.py index cb8d5e57..385364fa 100644 --- a/kasa/smart/modules/autooffmodule.py +++ b/kasa/smart/modules/autooff.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class AutoOffModule(SmartModule): +class AutoOff(SmartModule): """Implementation of auto off module.""" REQUIRED_COMPONENT = "auto_off" diff --git a/kasa/smart/modules/battery.py b/kasa/smart/modules/batterysensor.py similarity index 100% rename from kasa/smart/modules/battery.py rename to kasa/smart/modules/batterysensor.py diff --git a/kasa/smart/modules/childdevicemodule.py b/kasa/smart/modules/childdevice.py similarity index 84% rename from kasa/smart/modules/childdevicemodule.py rename to kasa/smart/modules/childdevice.py index 9f4710b2..5713eff4 100644 --- a/kasa/smart/modules/childdevicemodule.py +++ b/kasa/smart/modules/childdevice.py @@ -3,7 +3,7 @@ from ..smartmodule import SmartModule -class ChildDeviceModule(SmartModule): +class ChildDevice(SmartModule): """Implementation for child devices.""" REQUIRED_COMPONENT = "child_device" diff --git a/kasa/smart/modules/cloudmodule.py b/kasa/smart/modules/cloud.py similarity index 97% rename from kasa/smart/modules/cloudmodule.py rename to kasa/smart/modules/cloud.py index 8b9d8f41..1b64f090 100644 --- a/kasa/smart/modules/cloudmodule.py +++ b/kasa/smart/modules/cloud.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class CloudModule(SmartModule): +class Cloud(SmartModule): """Implementation of cloud module.""" QUERY_GETTER_NAME = "get_connect_cloud_state" diff --git a/kasa/smart/modules/colormodule.py b/kasa/smart/modules/color.py similarity index 98% rename from kasa/smart/modules/colormodule.py rename to kasa/smart/modules/color.py index 716d4c44..979d4fec 100644 --- a/kasa/smart/modules/colormodule.py +++ b/kasa/smart/modules/color.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class ColorModule(SmartModule): +class Color(SmartModule): """Implementation of color module.""" REQUIRED_COMPONENT = "color" diff --git a/kasa/smart/modules/colortemp.py b/kasa/smart/modules/colortemperature.py similarity index 98% rename from kasa/smart/modules/colortemp.py rename to kasa/smart/modules/colortemperature.py index d6b43d02..88d5ea21 100644 --- a/kasa/smart/modules/colortemp.py +++ b/kasa/smart/modules/colortemperature.py @@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__) DEFAULT_TEMP_RANGE = [2500, 6500] -class ColorTemperatureModule(SmartModule): +class ColorTemperature(SmartModule): """Implementation of color temp module.""" REQUIRED_COMPONENT = "color_temperature" diff --git a/kasa/smart/modules/contact.py b/kasa/smart/modules/contactsensor.py similarity index 100% rename from kasa/smart/modules/contact.py rename to kasa/smart/modules/contactsensor.py diff --git a/kasa/smart/modules/energymodule.py b/kasa/smart/modules/energy.py similarity index 98% rename from kasa/smart/modules/energymodule.py rename to kasa/smart/modules/energy.py index 9cfe8cfb..55b5088e 100644 --- a/kasa/smart/modules/energymodule.py +++ b/kasa/smart/modules/energy.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class EnergyModule(SmartModule): +class Energy(SmartModule): """Implementation of energy monitoring module.""" REQUIRED_COMPONENT = "energy_monitoring" diff --git a/kasa/smart/modules/fanmodule.py b/kasa/smart/modules/fan.py similarity index 98% rename from kasa/smart/modules/fanmodule.py rename to kasa/smart/modules/fan.py index 6eeaa4d4..3d8cc7eb 100644 --- a/kasa/smart/modules/fanmodule.py +++ b/kasa/smart/modules/fan.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class FanModule(SmartModule): +class Fan(SmartModule): """Implementation of fan_control module.""" REQUIRED_COMPONENT = "fan_control" diff --git a/kasa/smart/modules/frostprotection.py b/kasa/smart/modules/frostprotection.py index cedaf78b..ee93d299 100644 --- a/kasa/smart/modules/frostprotection.py +++ b/kasa/smart/modules/frostprotection.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class FrostProtectionModule(SmartModule): +class FrostProtection(SmartModule): """Implementation for frost protection module. This basically turns the thermostat on and off. diff --git a/kasa/smart/modules/humidity.py b/kasa/smart/modules/humiditysensor.py similarity index 100% rename from kasa/smart/modules/humidity.py rename to kasa/smart/modules/humiditysensor.py diff --git a/kasa/smart/modules/ledmodule.py b/kasa/smart/modules/led.py similarity index 93% rename from kasa/smart/modules/ledmodule.py rename to kasa/smart/modules/led.py index 587be51c..230b83d9 100644 --- a/kasa/smart/modules/ledmodule.py +++ b/kasa/smart/modules/led.py @@ -2,11 +2,11 @@ from __future__ import annotations -from ...interfaces.led import Led +from ...interfaces.led import Led as LedInterface from ..smartmodule import SmartModule -class LedModule(SmartModule, Led): +class Led(SmartModule, LedInterface): """Implementation of led controls.""" REQUIRED_COMPONENT = "led" diff --git a/kasa/smart/modules/lighteffectmodule.py b/kasa/smart/modules/lighteffect.py similarity index 96% rename from kasa/smart/modules/lighteffectmodule.py rename to kasa/smart/modules/lighteffect.py index a06e979a..4f049576 100644 --- a/kasa/smart/modules/lighteffectmodule.py +++ b/kasa/smart/modules/lighteffect.py @@ -6,14 +6,14 @@ import base64 import copy from typing import TYPE_CHECKING, Any -from ...interfaces.lighteffect import LightEffect +from ...interfaces.lighteffect import LightEffect as LightEffectInterface from ..smartmodule import SmartModule if TYPE_CHECKING: from ..smartdevice import SmartDevice -class LightEffectModule(SmartModule, LightEffect): +class LightEffect(SmartModule, LightEffectInterface): """Implementation of dynamic light effects.""" REQUIRED_COMPONENT = "light_effect" diff --git a/kasa/smart/modules/lighttransitionmodule.py b/kasa/smart/modules/lighttransition.py similarity index 99% rename from kasa/smart/modules/lighttransitionmodule.py rename to kasa/smart/modules/lighttransition.py index f213d9ac..a11c7d95 100644 --- a/kasa/smart/modules/lighttransitionmodule.py +++ b/kasa/smart/modules/lighttransition.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class LightTransitionModule(SmartModule): +class LightTransition(SmartModule): """Implementation of gradual on/off.""" REQUIRED_COMPONENT = "on_off_gradually" diff --git a/kasa/smart/modules/reportmodule.py b/kasa/smart/modules/reportmode.py similarity index 96% rename from kasa/smart/modules/reportmodule.py rename to kasa/smart/modules/reportmode.py index 16827a8c..f0af4c1c 100644 --- a/kasa/smart/modules/reportmodule.py +++ b/kasa/smart/modules/reportmode.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class ReportModule(SmartModule): +class ReportMode(SmartModule): """Implementation of report module.""" REQUIRED_COMPONENT = "report_mode" diff --git a/kasa/smart/modules/temperature.py b/kasa/smart/modules/temperaturesensor.py similarity index 100% rename from kasa/smart/modules/temperature.py rename to kasa/smart/modules/temperaturesensor.py diff --git a/kasa/smart/modules/timemodule.py b/kasa/smart/modules/time.py similarity index 98% rename from kasa/smart/modules/timemodule.py rename to kasa/smart/modules/time.py index 23814f57..958cf9e2 100644 --- a/kasa/smart/modules/timemodule.py +++ b/kasa/smart/modules/time.py @@ -13,7 +13,7 @@ if TYPE_CHECKING: from ..smartdevice import SmartDevice -class TimeModule(SmartModule): +class Time(SmartModule): """Implementation of device_local_time.""" REQUIRED_COMPONENT = "time" diff --git a/kasa/smart/modules/waterleak.py b/kasa/smart/modules/waterleaksensor.py similarity index 100% rename from kasa/smart/modules/waterleak.py rename to kasa/smart/modules/waterleaksensor.py diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 194e7c17..122c943b 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -20,15 +20,10 @@ from ..module import Module from ..modulemapping import ModuleMapping, ModuleName from ..smartprotocol import SmartProtocol from .modules import ( - Brightness, - CloudModule, - ColorModule, - ColorTemperatureModule, + Cloud, DeviceModule, - EnergyModule, - FanModule, Firmware, - TimeModule, + Time, ) 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. # This list should be updated when creating new modules that could have the # 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 @@ -329,11 +324,11 @@ class SmartDevice(Bulb, Fan, Device): self._add_feature(feat) @property - def is_cloud_connected(self): + def is_cloud_connected(self) -> bool: """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 self.modules["CloudModule"].is_connected + return self.modules[Module.Cloud].is_connected @property def sys_info(self) -> dict[str, Any]: @@ -357,10 +352,10 @@ class SmartDevice(Bulb, Fan, Device): def time(self) -> datetime: """Return the time.""" # TODO: Default to parent's time module for child devices - if self._parent and "TimeModule" in self.modules: - _timemod = cast(TimeModule, self._parent.modules["TimeModule"]) # noqa: F405 + if self._parent and Module.Time in self.modules: + _timemod = self._parent.modules[Module.Time] else: - _timemod = cast(TimeModule, self.modules["TimeModule"]) # noqa: F405 + _timemod = self.modules[Module.Time] return _timemod.time @@ -437,7 +432,7 @@ class SmartDevice(Bulb, Fan, Device): @property def has_emeter(self) -> bool: """Return if the device has emeter.""" - return "EnergyModule" in self.modules + return Module.Energy in self.modules @property def is_dimmer(self) -> bool: @@ -479,19 +474,19 @@ class SmartDevice(Bulb, Fan, Device): @property def emeter_realtime(self) -> EmeterStatus: """Get the emeter status.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_realtime @property def emeter_this_month(self) -> float | None: """Get the emeter value for this month.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_this_month @property def emeter_today(self) -> float | None: """Get the emeter value for today.""" - energy = cast(EnergyModule, self.modules["EnergyModule"]) + energy = self.modules[Module.Energy] return energy.emeter_today @property @@ -503,8 +498,7 @@ class SmartDevice(Bulb, Fan, Device): ): return None on_time = cast(float, on_time) - if (timemod := self.modules.get("TimeModule")) is not None: - timemod = cast(TimeModule, timemod) # noqa: F405 + if (timemod := self.modules.get(Module.Time)) is not None: return timemod.time - timedelta(seconds=on_time) else: # We have no device time, use current local time. return datetime.now().replace(microsecond=0) - timedelta(seconds=on_time) @@ -650,37 +644,37 @@ class SmartDevice(Bulb, Fan, Device): @property def is_fan(self) -> bool: """Return True if the device is a fan.""" - return "FanModule" in self.modules + return Module.Fan in self.modules @property def fan_speed_level(self) -> int: """Return fan speed level.""" if not self.is_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): """Set fan speed level.""" if not self.is_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 @property def is_color(self) -> bool: """Whether the bulb supports color changes.""" - return "ColorModule" in self.modules + return Module.Color in self.modules @property def is_dimmable(self) -> bool: """Whether the bulb supports brightness changes.""" - return "Brightness" in self.modules + return Module.Brightness in self.modules @property def is_variable_color_temp(self) -> bool: """Whether the bulb supports color temperature changes.""" - return "ColorTemperatureModule" in self.modules + return Module.ColorTemperature in self.modules @property def valid_temperature_range(self) -> ColorTempRange: @@ -691,9 +685,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_variable_color_temp: raise KasaException("Color temperature not supported") - return cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).valid_temperature_range + return self.modules[Module.ColorTemperature].valid_temperature_range @property def hsv(self) -> HSV: @@ -704,7 +696,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_color: raise KasaException("Bulb does not support color.") - return cast(ColorModule, self.modules["ColorModule"]).hsv + return self.modules[Module.Color].hsv @property def color_temp(self) -> int: @@ -712,9 +704,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_variable_color_temp: raise KasaException("Bulb does not support colortemp.") - return cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).color_temp + return self.modules[Module.ColorTemperature].color_temp @property def brightness(self) -> int: @@ -722,7 +712,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_dimmable: # pragma: no cover raise KasaException("Bulb is not dimmable.") - return cast(Brightness, self.modules["Brightness"]).brightness + return self.modules[Module.Brightness].brightness async def set_hsv( self, @@ -744,9 +734,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_color: raise KasaException("Bulb does not support color.") - return await cast(ColorModule, self.modules["ColorModule"]).set_hsv( - hue, saturation, value - ) + return await self.modules[Module.Color].set_hsv(hue, saturation, value) async def set_color_temp( 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: raise KasaException("Bulb does not support colortemp.") - return await cast( - ColorTemperatureModule, self.modules["ColorTemperatureModule"] - ).set_color_temp(temp) + return await self.modules[Module.ColorTemperature].set_color_temp(temp) async def set_brightness( self, brightness: int, *, transition: int | None = None @@ -777,9 +763,7 @@ class SmartDevice(Bulb, Fan, Device): if not self.is_dimmable: # pragma: no cover raise KasaException("Bulb is not dimmable.") - return await cast(Brightness, self.modules["Brightness"]).set_brightness( - brightness - ) + return await self.modules[Module.Brightness].set_brightness(brightness) @property def presets(self) -> list[BulbPreset]: @@ -789,4 +773,4 @@ class SmartDevice(Bulb, Fan, Device): @property def has_effects(self) -> bool: """Return True if the device supports effects.""" - return "LightEffectModule" in self.modules + return Module.LightEffect in self.modules diff --git a/kasa/tests/smart/modules/test_light_effect.py b/kasa/tests/smart/modules/test_light_effect.py index cc0eee8a..56c3f096 100644 --- a/kasa/tests/smart/modules/test_light_effect.py +++ b/kasa/tests/smart/modules/test_light_effect.py @@ -6,7 +6,7 @@ import pytest from pytest_mock import MockerFixture 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 light_effect = parametrize( @@ -18,7 +18,7 @@ light_effect = parametrize( async def test_light_effect(dev: Device, mocker: MockerFixture): """Test light effect.""" light_effect = dev.modules.get(Module.LightEffect) - assert isinstance(light_effect, LightEffectModule) + assert isinstance(light_effect, LightEffect) feature = light_effect._module_features["light_effect"] assert feature.type == Feature.Type.Choice @@ -28,7 +28,7 @@ async def test_light_effect(dev: Device, mocker: MockerFixture): assert feature.choices for effect in chain(reversed(feature.choices), feature.choices): 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} if enable: params["id"] = light_effect._scenes_names_to_id[effect] diff --git a/kasa/tests/test_cli.py b/kasa/tests/test_cli.py index 7addd434..a438aa97 100644 --- a/kasa/tests/test_cli.py +++ b/kasa/tests/test_cli.py @@ -737,7 +737,7 @@ async def test_feature_set(mocker, runner): dummy_device = await get_device_for_fixture_protocol( "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) res = await runner.invoke( diff --git a/kasa/tests/test_smartdevice.py b/kasa/tests/test_smartdevice.py index a0af2cb1..ed9e5721 100644 --- a/kasa/tests/test_smartdevice.py +++ b/kasa/tests/test_smartdevice.py @@ -127,21 +127,21 @@ async def test_get_modules(): dummy_device = await get_device_for_fixture_protocol( "KS240(US)_1.0_1.0.5.json", "SMART" ) - from kasa.smart.modules import CloudModule + from kasa.smart.modules import Cloud # Modules on device - module = dummy_device.modules.get("CloudModule") + module = dummy_device.modules.get("Cloud") assert module assert module._device == dummy_device - assert isinstance(module, CloudModule) + assert isinstance(module, Cloud) module = dummy_device.modules.get(Module.Cloud) assert module assert module._device == dummy_device - assert isinstance(module, CloudModule) + assert isinstance(module, Cloud) # Modules on child - module = dummy_device.modules.get("FanModule") + module = dummy_device.modules.get("Fan") assert module assert module._device != dummy_device assert module._device._parent == dummy_device