mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Improve dimmer support (#62)
* discover dimmers properly * fix circular import, hopefully * add is_color to SmartDevice API * allow changing the dimming without implicitly turning the device on * Add tests for device type handling for discovery data, make sure new fixtures are added to categories inside conftest
This commit is contained in:
parent
e37244de0f
commit
012436c494
@ -8,6 +8,7 @@ from typing import Awaitable, Callable, Dict, Mapping, Type, Union, cast
|
||||
from kasa.protocol import TPLinkSmartHomeProtocol
|
||||
from kasa.smartbulb import SmartBulb
|
||||
from kasa.smartdevice import SmartDevice, SmartDeviceException
|
||||
from kasa.smartdimmer import SmartDimmer
|
||||
from kasa.smartplug import SmartPlug
|
||||
from kasa.smartstrip import SmartStrip
|
||||
|
||||
@ -195,7 +196,12 @@ class Discover:
|
||||
else:
|
||||
raise SmartDeviceException("No 'system' nor 'get_sysinfo' in response")
|
||||
|
||||
if "smartplug" in type_.lower() and "children" in sysinfo:
|
||||
if (
|
||||
"smartlife.iot.dimmer" in info
|
||||
and "get_dimmer_parameters" in info["smartlife.iot.dimmer"]
|
||||
):
|
||||
return SmartDimmer
|
||||
elif "smartplug" in type_.lower() and "children" in sysinfo:
|
||||
return SmartStrip
|
||||
elif "smartplug" in type_.lower():
|
||||
return SmartPlug
|
||||
|
@ -667,6 +667,11 @@ class SmartDevice:
|
||||
"""Return True if the device supports color temperature."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_color(self) -> bool:
|
||||
"""Return True if the device supports color changes."""
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return "<{} model {} at {} ({}), is_on: {} - dev specific: {}>".format(
|
||||
self.__class__.__name__,
|
||||
|
@ -1,8 +1,7 @@
|
||||
"""Module for dimmers (currently only HS220)."""
|
||||
from typing import Any, Dict
|
||||
|
||||
from kasa import DeviceType, SmartDeviceException
|
||||
from kasa.smartdevice import requires_update
|
||||
from kasa.smartdevice import DeviceType, SmartDeviceException, requires_update
|
||||
from kasa.smartplug import SmartPlug
|
||||
|
||||
|
||||
@ -61,7 +60,6 @@ class SmartDimmer(SmartPlug):
|
||||
if not isinstance(value, int):
|
||||
raise ValueError("Brightness must be integer, " "not of %s.", type(value))
|
||||
elif 0 <= value <= 100:
|
||||
await self.turn_on()
|
||||
await self._query_helper(
|
||||
"smartlife.iot.dimmer", "set_brightness", {"brightness": value}
|
||||
)
|
||||
|
@ -17,7 +17,7 @@ SUPPORTED_DEVICES = glob.glob(
|
||||
|
||||
BULBS = {"KL60", "LB100", "LB120", "LB130", "KL120", "KL130"}
|
||||
VARIABLE_TEMP = {"LB120", "LB130", "KL120", "KL130"}
|
||||
PLUGS = {"HS100", "HS103", "HS105", "HS110", "HS200", "HS210", "HS300"}
|
||||
PLUGS = {"HS100", "HS103", "HS105", "HS110", "HS200", "HS210"}
|
||||
STRIPS = {"HS107", "HS300", "KP303", "KP400"}
|
||||
DIMMERS = {"HS220"}
|
||||
COLOR_BULBS = {"LB130", "KL130"}
|
||||
@ -49,6 +49,18 @@ no_emeter = pytest.mark.parametrize(
|
||||
bulb = pytest.mark.parametrize("dev", filter_model("bulbs", BULBS), indirect=True)
|
||||
plug = pytest.mark.parametrize("dev", filter_model("plugs", PLUGS), indirect=True)
|
||||
strip = pytest.mark.parametrize("dev", filter_model("strips", STRIPS), indirect=True)
|
||||
dimmer = pytest.mark.parametrize("dev", filter_model("dimmers", DIMMERS), indirect=True)
|
||||
|
||||
# This ensures that every single file inside fixtures/ is being placed in some category
|
||||
categorized_fixtures = set(dimmer.args[1] + strip.args[1] + plug.args[1] + bulb.args[1])
|
||||
diff = set(SUPPORTED_DEVICES) - set(categorized_fixtures)
|
||||
if diff:
|
||||
for file in diff:
|
||||
print(
|
||||
"No category for file %s, add to the corresponding set (BULBS, PLUGS, ..)"
|
||||
% file
|
||||
)
|
||||
raise Exception("Missing category for %s" % diff)
|
||||
|
||||
dimmable = pytest.mark.parametrize(
|
||||
"dev", filter_model("dimmable", DIMMABLE), indirect=True
|
||||
|
@ -249,8 +249,8 @@ def success(target, cmd, res):
|
||||
|
||||
|
||||
class FakeTransportProtocol(TPLinkSmartHomeProtocol):
|
||||
def __init__(self, info, invalid=False):
|
||||
# TODO remove invalid when removing the old tests.
|
||||
def __init__(self, info):
|
||||
self.discovery_data = info
|
||||
proto = FakeTransportProtocol.baseproto
|
||||
for target in info:
|
||||
# print("target %s" % target)
|
||||
|
43
kasa/tests/test_discovery.py
Normal file
43
kasa/tests/test_discovery.py
Normal file
@ -0,0 +1,43 @@
|
||||
# type: ignore
|
||||
import pytest # type: ignore # https://github.com/pytest-dev/pytest/issues/3342
|
||||
|
||||
from kasa import DeviceType, Discover, SmartDevice, SmartDeviceException
|
||||
|
||||
from .conftest import bulb, dimmer, plug, strip
|
||||
|
||||
# to avoid adding this for each async function separately
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
|
||||
@plug
|
||||
async def test_type_detection_plug(dev: SmartDevice):
|
||||
d = Discover._get_device_class(dev.protocol.discovery_data)("localhost")
|
||||
assert d.is_plug
|
||||
assert d.device_type == DeviceType.Plug
|
||||
|
||||
|
||||
@bulb
|
||||
async def test_type_detection_bulb(dev: SmartDevice):
|
||||
d = Discover._get_device_class(dev.protocol.discovery_data)("localhost")
|
||||
assert d.is_bulb
|
||||
assert d.device_type == DeviceType.Bulb
|
||||
|
||||
|
||||
@strip
|
||||
async def test_type_detection_strip(dev: SmartDevice):
|
||||
d = Discover._get_device_class(dev.protocol.discovery_data)("localhost")
|
||||
assert d.is_strip
|
||||
assert d.device_type == DeviceType.Strip
|
||||
|
||||
|
||||
@dimmer
|
||||
async def test_type_detection_dimmer(dev: SmartDevice):
|
||||
d = Discover._get_device_class(dev.protocol.discovery_data)("localhost")
|
||||
assert d.is_dimmer
|
||||
assert d.device_type == DeviceType.Dimmer
|
||||
|
||||
|
||||
async def test_type_unknown():
|
||||
invalid_info = {"system": {"get_sysinfo": {"type": "nosuchtype"}}}
|
||||
with pytest.raises(SmartDeviceException):
|
||||
Discover._get_device_class(invalid_info)
|
@ -1,4 +1,3 @@
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from unittest.mock import patch
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user