mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Add fan module (#764)
Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
parent
da441bc697
commit
700643d3cf
@ -16,6 +16,7 @@ class DeviceType(Enum):
|
||||
LightStrip = "lightstrip"
|
||||
Sensor = "sensor"
|
||||
Hub = "hub"
|
||||
Fan = "fan"
|
||||
Unknown = "unknown"
|
||||
|
||||
@staticmethod
|
||||
|
@ -9,6 +9,7 @@ from .cloudmodule import CloudModule
|
||||
from .colortemp import ColorTemperatureModule
|
||||
from .devicemodule import DeviceModule
|
||||
from .energymodule import EnergyModule
|
||||
from .fanmodule import FanModule
|
||||
from .firmware import Firmware
|
||||
from .humidity import HumiditySensor
|
||||
from .ledmodule import LedModule
|
||||
@ -30,6 +31,7 @@ __all__ = [
|
||||
"AutoOffModule",
|
||||
"LedModule",
|
||||
"Brightness",
|
||||
"FanModule",
|
||||
"Firmware",
|
||||
"CloudModule",
|
||||
"LightTransitionModule",
|
||||
|
66
kasa/smart/modules/fanmodule.py
Normal file
66
kasa/smart/modules/fanmodule.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""Implementation of fan_control module."""
|
||||
from typing import TYPE_CHECKING, Dict
|
||||
|
||||
from ...feature import Feature, FeatureType
|
||||
from ..smartmodule import SmartModule
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..smartdevice import SmartDevice
|
||||
|
||||
|
||||
class FanModule(SmartModule):
|
||||
"""Implementation of fan_control module."""
|
||||
|
||||
REQUIRED_COMPONENT = "fan_control"
|
||||
|
||||
def __init__(self, device: "SmartDevice", module: str):
|
||||
super().__init__(device, module)
|
||||
|
||||
self._add_feature(
|
||||
Feature(
|
||||
device,
|
||||
"Fan speed level",
|
||||
container=self,
|
||||
attribute_getter="fan_speed_level",
|
||||
attribute_setter="set_fan_speed_level",
|
||||
icon="mdi:fan",
|
||||
type=FeatureType.Number,
|
||||
minimum_value=1,
|
||||
maximum_value=4,
|
||||
)
|
||||
)
|
||||
self._add_feature(
|
||||
Feature(
|
||||
device,
|
||||
"Fan sleep mode",
|
||||
container=self,
|
||||
attribute_getter="sleep_mode",
|
||||
attribute_setter="set_sleep_mode",
|
||||
icon="mdi:sleep",
|
||||
type=FeatureType.Switch
|
||||
)
|
||||
)
|
||||
|
||||
def query(self) -> Dict:
|
||||
"""Query to execute during the update cycle."""
|
||||
return {}
|
||||
|
||||
@property
|
||||
def fan_speed_level(self) -> int:
|
||||
"""Return fan speed level."""
|
||||
return self.data["fan_speed_level"]
|
||||
|
||||
async def set_fan_speed_level(self, level: int):
|
||||
"""Set fan speed level."""
|
||||
if level < 1 or level > 4:
|
||||
raise ValueError("Invalid level, should be in range 1-4.")
|
||||
return await self.call("set_device_info", {"fan_speed_level": level})
|
||||
|
||||
@property
|
||||
def sleep_mode(self) -> bool:
|
||||
"""Return sleep mode status."""
|
||||
return self.data["fan_sleep_mode_on"]
|
||||
|
||||
async def set_sleep_mode(self, on: bool):
|
||||
"""Set sleep mode."""
|
||||
return await self.call("set_device_info", {"fan_sleep_mode_on": on})
|
@ -49,6 +49,8 @@ class SmartChildDevice(SmartDevice):
|
||||
child_device_map = {
|
||||
"plug.powerstrip.sub-plug": DeviceType.Plug,
|
||||
"subg.trigger.temp-hmdt-sensor": DeviceType.Sensor,
|
||||
"kasa.switch.outlet.sub-fan": DeviceType.Fan,
|
||||
"kasa.switch.outlet.sub-dimmer": DeviceType.Dimmer,
|
||||
}
|
||||
dev_type = child_device_map.get(self.sys_info["category"])
|
||||
if dev_type is None:
|
||||
|
@ -314,12 +314,11 @@ class SmartDevice(Device):
|
||||
return self._last_update
|
||||
|
||||
def _update_internal_state(self, info):
|
||||
"""Update internal state.
|
||||
"""Update the internal info state.
|
||||
|
||||
This is used by the parent to push updates to its children
|
||||
This is used by the parent to push updates to its children.
|
||||
"""
|
||||
# TODO: cleanup the _last_update, _info mess.
|
||||
self._last_update = self._info = info
|
||||
self._info = info
|
||||
|
||||
async def _query_helper(
|
||||
self, method: str, params: Optional[Dict] = None, child_ids=None
|
||||
|
@ -62,7 +62,7 @@ class SmartModule(Module):
|
||||
q = self.query()
|
||||
|
||||
if not q:
|
||||
return dev.internal_state["get_device_info"]
|
||||
return dev.sys_info
|
||||
|
||||
q_keys = list(q.keys())
|
||||
query_key = q_keys[0]
|
||||
|
43
kasa/tests/smart/modules/test_fan.py
Normal file
43
kasa/tests/smart/modules/test_fan.py
Normal file
@ -0,0 +1,43 @@
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
from kasa import SmartDevice
|
||||
from kasa.smart.modules import FanModule
|
||||
from kasa.tests.device_fixtures import parametrize
|
||||
|
||||
fan = parametrize(
|
||||
"has fan", component_filter="fan_control", protocol_filter={"SMART.CHILD"}
|
||||
)
|
||||
|
||||
|
||||
@fan
|
||||
async def test_fan_speed(dev: SmartDevice, mocker: MockerFixture):
|
||||
"""Test fan speed feature."""
|
||||
fan: FanModule = dev.modules["FanModule"]
|
||||
level_feature = fan._module_features["fan_speed_level"]
|
||||
assert level_feature.minimum_value <= level_feature.value <= level_feature.maximum_value
|
||||
|
||||
call = mocker.spy(fan, "call")
|
||||
await fan.set_fan_speed_level(3)
|
||||
call.assert_called_with("set_device_info", {"fan_sleep_level": 3})
|
||||
|
||||
await dev.update()
|
||||
|
||||
assert fan.fan_speed_level == 3
|
||||
assert level_feature.value == 3
|
||||
|
||||
|
||||
@fan
|
||||
async def test_sleep_mode(dev: SmartDevice, mocker: MockerFixture):
|
||||
"""Test sleep mode feature."""
|
||||
fan: FanModule = dev.modules["FanModule"]
|
||||
sleep_feature = fan._module_features["fan_sleep_mode"]
|
||||
assert isinstance(sleep_feature.value, bool)
|
||||
|
||||
call = mocker.spy(fan, "call")
|
||||
await fan.set_sleep_mode(True)
|
||||
call.assert_called_with("set_device_info", {"fan_sleep_mode_on": True})
|
||||
|
||||
await dev.update()
|
||||
|
||||
assert fan.sleep_mode is True
|
||||
assert sleep_feature.value is True
|
@ -32,8 +32,8 @@ async def test_childdevice_update(dev, dummy_protocol, mocker):
|
||||
|
||||
await dev.update()
|
||||
|
||||
assert dev._last_update != first._last_update
|
||||
assert child_list[0] == first._last_update
|
||||
assert dev._info != first._info
|
||||
assert child_list[0] == first._info
|
||||
|
||||
|
||||
@strip_smart
|
||||
|
Loading…
Reference in New Issue
Block a user