diff --git a/kasa/cli.py b/kasa/cli.py index 78553ebf..20372be4 100755 --- a/kasa/cli.py +++ b/kasa/cli.py @@ -609,16 +609,7 @@ async def state(ctx, dev: Device): echo(f"\tMAC (rssi): {dev.mac} ({dev.rssi})") echo(f"\tLocation: {dev.location}") - echo("\n\t[bold]== Device specific information ==[/bold]") - for info_name, info_data in dev.state_information.items(): - if isinstance(info_data, list): - echo(f"\t{info_name}:") - for item in info_data: - echo(f"\t\t{item}") - else: - echo(f"\t{info_name}: {info_data}") - - echo("\n\t[bold]== Features == [/bold]") + echo("\n\t[bold]== Device-specific information == [/bold]") for id_, feature in dev.features.items(): echo(f"\t{feature.name} ({id_}): {feature.value}") diff --git a/kasa/device.py b/kasa/device.py index 63eafa5b..fd0fe59c 100644 --- a/kasa/device.py +++ b/kasa/device.py @@ -304,9 +304,9 @@ class Device(ABC): """Return all the internal state data.""" @property - @abstractmethod def state_information(self) -> Dict[str, Any]: - """Return the key state information.""" + """Return available features and their values.""" + return {feat.name: feat.value for feat in self._features.values()} @property def features(self) -> Dict[str, Feature]: diff --git a/kasa/iot/iotbulb.py b/kasa/iot/iotbulb.py index d80a24ea..7652a1fb 100644 --- a/kasa/iot/iotbulb.py +++ b/kasa/iot/iotbulb.py @@ -2,7 +2,7 @@ import logging import re from enum import Enum -from typing import Any, Dict, List, Optional, cast +from typing import Dict, List, Optional, cast try: from pydantic.v1 import BaseModel, Field, root_validator @@ -462,23 +462,6 @@ class IotBulb(IotDevice, Bulb): light_state = {"brightness": brightness} return await self.set_light_state(light_state, transition=transition) - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return bulb-specific state information.""" - info: Dict[str, Any] = { - "Brightness": self.brightness, - "Is dimmable": self.is_dimmable, - } - if self.is_variable_color_temp: - info["Color temperature"] = self.color_temp - info["Valid temperature range"] = self.valid_temperature_range - if self.is_color: - info["HSV"] = self.hsv - info["Presets"] = self.presets - - return info - @property # type: ignore @requires_update def is_on(self) -> bool: diff --git a/kasa/iot/iotdevice.py b/kasa/iot/iotdevice.py index 5bbb9505..0f34d8fb 100755 --- a/kasa/iot/iotdevice.py +++ b/kasa/iot/iotdevice.py @@ -615,12 +615,6 @@ class IotDevice(Device): return datetime.now().replace(microsecond=0) - timedelta(seconds=on_time) - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return device-type specific, end-user friendly state information.""" - raise NotImplementedError("Device subclass needs to implement this.") - @property # type: ignore @requires_update def device_id(self) -> str: diff --git a/kasa/iot/iotdimmer.py b/kasa/iot/iotdimmer.py index 8882ae81..cbcafd12 100644 --- a/kasa/iot/iotdimmer.py +++ b/kasa/iot/iotdimmer.py @@ -232,12 +232,3 @@ class IotDimmer(IotPlug): """Whether the switch supports brightness changes.""" sys_info = self.sys_info return "brightness" in sys_info - - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return switch-specific state information.""" - info = super().state_information - info["Brightness"] = self.brightness - - return info diff --git a/kasa/iot/iotlightstrip.py b/kasa/iot/iotlightstrip.py index fa341a2c..1e657a98 100644 --- a/kasa/iot/iotlightstrip.py +++ b/kasa/iot/iotlightstrip.py @@ -1,5 +1,5 @@ """Module for light strips (KL430).""" -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional from ..device_type import DeviceType from ..deviceconfig import DeviceConfig @@ -84,18 +84,6 @@ class IotLightStrip(IotBulb): """ return EFFECT_NAMES_V1 if self.has_effects else None - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return strip specific state information.""" - info = super().state_information - - info["Length"] = self.length - if self.has_effects: - info["Effect"] = self.effect["name"] - - return info - @requires_update async def set_effect( self, diff --git a/kasa/iot/iotplug.py b/kasa/iot/iotplug.py index 2d509e05..2296b1e6 100644 --- a/kasa/iot/iotplug.py +++ b/kasa/iot/iotplug.py @@ -1,6 +1,6 @@ """Module for smart plugs (HS100, HS110, ..).""" import logging -from typing import Any, Dict, Optional +from typing import Optional from ..device_type import DeviceType from ..deviceconfig import DeviceConfig @@ -99,12 +99,6 @@ class IotPlug(IotDevice): "system", "set_led_off", {"off": int(not state)} ) - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return switch-specific state information.""" - return {} - class IotWallSwitch(IotPlug): """Representation of a TP-Link Smart Wall Switch.""" diff --git a/kasa/iot/iotstrip.py b/kasa/iot/iotstrip.py index 4bf31cc7..2e5af0d0 100755 --- a/kasa/iot/iotstrip.py +++ b/kasa/iot/iotstrip.py @@ -154,19 +154,6 @@ class IotStrip(IotDevice): """Set the state of the led (night mode).""" await self._query_helper("system", "set_led_off", {"off": int(not state)}) - @property # type: ignore - @requires_update - def state_information(self) -> Dict[str, Any]: - """Return strip-specific state information. - - :return: Strip information dict, keys in user-presentable form. - """ - return { - "LED state": self.led, - "Childs count": len(self.children), - "On since": self.on_since, - } - async def current_consumption(self) -> float: """Get the current power consumption in watts.""" return sum([await plug.current_consumption() for plug in self.children]) diff --git a/kasa/smart/smartbulb.py b/kasa/smart/smartbulb.py index eb3310e8..b92edecd 100644 --- a/kasa/smart/smartbulb.py +++ b/kasa/smart/smartbulb.py @@ -1,5 +1,5 @@ """Module for tapo-branded smart bulbs (L5**).""" -from typing import Any, Dict, List, Optional +from typing import Dict, List, Optional from ..bulb import Bulb from ..exceptions import KasaException @@ -238,25 +238,6 @@ class SmartBulb(SmartDevice, Bulb): } ) - @property # type: ignore - def state_information(self) -> Dict[str, Any]: - """Return bulb-specific state information.""" - info: Dict[str, Any] = { - # TODO: re-enable after we don't inherit from smartbulb - # **super().state_information - "Is dimmable": self.is_dimmable, - } - if self.is_dimmable: - info["Brightness"] = self.brightness - if self.is_variable_color_temp: - info["Color temperature"] = self.color_temp - info["Valid temperature range"] = self.valid_temperature_range - if self.is_color: - info["HSV"] = self.hsv - info["Presets"] = self.presets - - return info - @property def presets(self) -> List[BulbPreset]: """Return a list of available bulb setting presets.""" diff --git a/kasa/smart/smartdevice.py b/kasa/smart/smartdevice.py index 3cbd12f9..f6e7f734 100644 --- a/kasa/smart/smartdevice.py +++ b/kasa/smart/smartdevice.py @@ -334,15 +334,6 @@ class SmartDevice(Device): ssid = base64.b64decode(ssid).decode() if ssid else "No SSID" return ssid - @property - def state_information(self) -> Dict[str, Any]: - """Return the key state information.""" - return { - "overheated": self._info.get("overheated"), - "signal_level": self._info.get("signal_level"), - "SSID": self.ssid, - } - @property def has_emeter(self) -> bool: """Return if the device has emeter.""" diff --git a/kasa/tests/fakeprotocol_iot.py b/kasa/tests/fakeprotocol_iot.py index 86457654..6b22db0b 100644 --- a/kasa/tests/fakeprotocol_iot.py +++ b/kasa/tests/fakeprotocol_iot.py @@ -121,6 +121,61 @@ TIME_MODULE = { "set_timezone": None, } +CLOUD_MODULE = { + "get_info": { + "username": "", + "server": "devs.tplinkcloud.com", + "binded": 0, + "cld_connection": 0, + "illegalType": -1, + "stopConnect": -1, + "tcspStatus": -1, + "fwDlPage": "", + "tcspInfo": "", + "fwNotifyType": 0, + } +} + + +AMBIENT_MODULE = { + "get_current_brt": {"value": 26, "err_code": 0}, + "get_config": { + "devs": [ + { + "hw_id": 0, + "enable": 0, + "dark_index": 1, + "min_adc": 0, + "max_adc": 2450, + "level_array": [ + {"name": "cloudy", "adc": 490, "value": 20}, + {"name": "overcast", "adc": 294, "value": 12}, + {"name": "dawn", "adc": 222, "value": 9}, + {"name": "twilight", "adc": 222, "value": 9}, + {"name": "total darkness", "adc": 111, "value": 4}, + {"name": "custom", "adc": 2400, "value": 97}, + ], + } + ], + "ver": "1.0", + "err_code": 0, + }, +} + + +MOTION_MODULE = { + "get_config": { + "enable": 0, + "version": "1.0", + "trigger_index": 2, + "cold_time": 60000, + "min_adc": 0, + "max_adc": 4095, + "array": [80, 50, 20, 0], + "err_code": 0, + } +} + class FakeIotProtocol(IotProtocol): def __init__(self, info): @@ -306,8 +361,10 @@ class FakeIotProtocol(IotProtocol): "set_brightness": set_hs220_brightness, "set_dimmer_transition": set_hs220_dimmer_transition, }, - "smartlife.iot.LAS": {}, - "smartlife.iot.PIR": {}, + "smartlife.iot.LAS": AMBIENT_MODULE, + "smartlife.iot.PIR": MOTION_MODULE, + "cnCloud": CLOUD_MODULE, + "smartlife.iot.common.cloud": CLOUD_MODULE, } async def query(self, request, port=9999): diff --git a/kasa/tests/test_bulb.py b/kasa/tests/test_bulb.py index 48b5976e..2ef52fec 100644 --- a/kasa/tests/test_bulb.py +++ b/kasa/tests/test_bulb.py @@ -42,11 +42,8 @@ async def test_bulb_sysinfo(dev: Bulb): @bulb async def test_state_attributes(dev: Bulb): - assert "Brightness" in dev.state_information - assert dev.state_information["Brightness"] == dev.brightness - - assert "Is dimmable" in dev.state_information - assert dev.state_information["Is dimmable"] == dev.is_dimmable + assert "Cloud connection" in dev.state_information + assert isinstance(dev.state_information["Cloud connection"], bool) @bulb_iot @@ -114,6 +111,7 @@ async def test_invalid_hsv(dev: Bulb, turn_on): @color_bulb +@pytest.mark.skip("requires color feature") async def test_color_state_information(dev: Bulb): assert "HSV" in dev.state_information assert dev.state_information["HSV"] == dev.hsv @@ -130,6 +128,7 @@ async def test_hsv_on_non_color(dev: Bulb): @variable_temp +@pytest.mark.skip("requires colortemp module") async def test_variable_temp_state_information(dev: Bulb): assert "Color temperature" in dev.state_information assert dev.state_information["Color temperature"] == dev.color_temp diff --git a/kasa/tests/test_lightstrip.py b/kasa/tests/test_lightstrip.py index fcc48dfa..ac80c52a 100644 --- a/kasa/tests/test_lightstrip.py +++ b/kasa/tests/test_lightstrip.py @@ -28,7 +28,6 @@ async def test_effects_lightstrip_set_effect(dev: IotLightStrip): await dev.set_effect("Candy Cane") assert dev.effect["name"] == "Candy Cane" - assert dev.state_information["Effect"] == "Candy Cane" @lightstrip