mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-26 16:46:23 +00:00
Remove SmartPlug in favor of SmartDevice (#781)
With the move towards autodetecting available features, there is no reason to keep SmartPlug around. kasa.smart.SmartPlug is removed in favor of kasa.smart.SmartDevice which offers the same functionality. Information about auto_off can be accessed using Features of the AutoOffModule on supported devices. Co-authored-by: Steven B. <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
parent
8c39e81a40
commit
d9d2f1a430
@ -134,7 +134,6 @@ if TYPE_CHECKING:
|
||||
from . import smart
|
||||
|
||||
smart.SmartDevice("127.0.0.1")
|
||||
smart.SmartPlug("127.0.0.1")
|
||||
smart.SmartBulb("127.0.0.1")
|
||||
iot.IotDevice("127.0.0.1")
|
||||
iot.IotPlug("127.0.0.1")
|
||||
|
@ -27,7 +27,7 @@ from kasa import (
|
||||
)
|
||||
from kasa.discover import DiscoveryResult
|
||||
from kasa.iot import IotBulb, IotDevice, IotDimmer, IotLightStrip, IotPlug, IotStrip
|
||||
from kasa.smart import SmartBulb, SmartDevice, SmartPlug
|
||||
from kasa.smart import SmartBulb, SmartDevice
|
||||
|
||||
try:
|
||||
from pydantic.v1 import ValidationError
|
||||
@ -72,7 +72,7 @@ TYPE_TO_CLASS = {
|
||||
"iot.dimmer": IotDimmer,
|
||||
"iot.strip": IotStrip,
|
||||
"iot.lightstrip": IotLightStrip,
|
||||
"smart.plug": SmartPlug,
|
||||
"smart.plug": SmartDevice,
|
||||
"smart.bulb": SmartBulb,
|
||||
}
|
||||
|
||||
|
@ -194,32 +194,32 @@ class Device(ABC):
|
||||
@property
|
||||
def is_bulb(self) -> bool:
|
||||
"""Return True if the device is a bulb."""
|
||||
return self._device_type == DeviceType.Bulb
|
||||
return self.device_type == DeviceType.Bulb
|
||||
|
||||
@property
|
||||
def is_light_strip(self) -> bool:
|
||||
"""Return True if the device is a led strip."""
|
||||
return self._device_type == DeviceType.LightStrip
|
||||
return self.device_type == DeviceType.LightStrip
|
||||
|
||||
@property
|
||||
def is_plug(self) -> bool:
|
||||
"""Return True if the device is a plug."""
|
||||
return self._device_type == DeviceType.Plug
|
||||
return self.device_type == DeviceType.Plug
|
||||
|
||||
@property
|
||||
def is_strip(self) -> bool:
|
||||
"""Return True if the device is a strip."""
|
||||
return self._device_type == DeviceType.Strip
|
||||
return self.device_type == DeviceType.Strip
|
||||
|
||||
@property
|
||||
def is_strip_socket(self) -> bool:
|
||||
"""Return True if the device is a strip socket."""
|
||||
return self._device_type == DeviceType.StripSocket
|
||||
return self.device_type == DeviceType.StripSocket
|
||||
|
||||
@property
|
||||
def is_dimmer(self) -> bool:
|
||||
"""Return True if the device is a dimmer."""
|
||||
return self._device_type == DeviceType.Dimmer
|
||||
return self.device_type == DeviceType.Dimmer
|
||||
|
||||
@property
|
||||
def is_dimmable(self) -> bool:
|
||||
@ -354,9 +354,9 @@ class Device(ABC):
|
||||
|
||||
def __repr__(self):
|
||||
if self._last_update is None:
|
||||
return f"<{self._device_type} at {self.host} - update() needed>"
|
||||
return f"<{self.device_type} at {self.host} - update() needed>"
|
||||
return (
|
||||
f"<{self._device_type} model {self.model} at {self.host}"
|
||||
f"<{self.device_type} model {self.model} at {self.host}"
|
||||
f" ({self.alias}), is_on: {self.is_on}"
|
||||
f" - dev specific: {self.state_information}>"
|
||||
)
|
||||
|
@ -14,7 +14,7 @@ from .protocol import (
|
||||
BaseProtocol,
|
||||
BaseTransport,
|
||||
)
|
||||
from .smart import SmartBulb, SmartPlug
|
||||
from .smart import SmartBulb, SmartDevice
|
||||
from .smartprotocol import SmartProtocol
|
||||
from .xortransport import XorTransport
|
||||
|
||||
@ -135,10 +135,10 @@ def get_device_class_from_sys_info(info: Dict[str, Any]) -> Type[IotDevice]:
|
||||
def get_device_class_from_family(device_type: str) -> Optional[Type[Device]]:
|
||||
"""Return the device class from the type name."""
|
||||
supported_device_types: Dict[str, Type[Device]] = {
|
||||
"SMART.TAPOPLUG": SmartPlug,
|
||||
"SMART.TAPOPLUG": SmartDevice,
|
||||
"SMART.TAPOBULB": SmartBulb,
|
||||
"SMART.TAPOSWITCH": SmartBulb,
|
||||
"SMART.KASAPLUG": SmartPlug,
|
||||
"SMART.KASAPLUG": SmartDevice,
|
||||
"SMART.KASASWITCH": SmartBulb,
|
||||
"IOT.SMARTPLUGSWITCH": IotPlug,
|
||||
"IOT.SMARTBULB": IotBulb,
|
||||
|
@ -2,6 +2,5 @@
|
||||
from .smartbulb import SmartBulb
|
||||
from .smartchilddevice import SmartChildDevice
|
||||
from .smartdevice import SmartDevice
|
||||
from .smartplug import SmartPlug
|
||||
|
||||
__all__ = ["SmartDevice", "SmartPlug", "SmartBulb", "SmartChildDevice"]
|
||||
__all__ = ["SmartDevice", "SmartBulb", "SmartChildDevice"]
|
||||
|
@ -485,3 +485,28 @@ class SmartDevice(Device):
|
||||
Note, this does not downgrade the firmware.
|
||||
"""
|
||||
await self.protocol.query("device_reset")
|
||||
|
||||
@property
|
||||
def device_type(self) -> DeviceType:
|
||||
"""Return the device type."""
|
||||
if self._device_type is not DeviceType.Unknown:
|
||||
return self._device_type
|
||||
|
||||
if self.children:
|
||||
if "SMART.TAPOHUB" in self.sys_info["type"]:
|
||||
pass # TODO: placeholder for future hub PR
|
||||
else:
|
||||
self._device_type = DeviceType.Strip
|
||||
elif "light_strip" in self._components:
|
||||
self._device_type = DeviceType.LightStrip
|
||||
elif "dimmer_calibration" in self._components:
|
||||
self._device_type = DeviceType.Dimmer
|
||||
elif "brightness" in self._components:
|
||||
self._device_type = DeviceType.Bulb
|
||||
elif "PLUG" in self.sys_info["type"]:
|
||||
self._device_type = DeviceType.Plug
|
||||
else:
|
||||
_LOGGER.warning("Unknown device type, falling back to plug")
|
||||
self._device_type = DeviceType.Plug
|
||||
|
||||
return self._device_type
|
||||
|
@ -1,37 +0,0 @@
|
||||
"""Module for a TAPO Plug."""
|
||||
import logging
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from ..device_type import DeviceType
|
||||
from ..deviceconfig import DeviceConfig
|
||||
from ..plug import Plug
|
||||
from ..smartprotocol import SmartProtocol
|
||||
from .smartdevice import SmartDevice
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SmartPlug(SmartDevice, Plug):
|
||||
"""Class to represent a TAPO Plug."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
host: str,
|
||||
*,
|
||||
config: Optional[DeviceConfig] = None,
|
||||
protocol: Optional[SmartProtocol] = None,
|
||||
) -> None:
|
||||
super().__init__(host=host, config=config, protocol=protocol)
|
||||
self._device_type = DeviceType.Plug
|
||||
|
||||
@property
|
||||
def state_information(self) -> Dict[str, Any]:
|
||||
"""Return the key state information."""
|
||||
return {
|
||||
**super().state_information,
|
||||
**{
|
||||
"On since": self.on_since,
|
||||
"auto_off_status": self._info.get("auto_off_status"),
|
||||
"auto_off_remain_time": self._info.get("auto_off_remain_time"),
|
||||
},
|
||||
}
|
@ -20,7 +20,7 @@ from kasa import (
|
||||
)
|
||||
from kasa.iot import IotBulb, IotDimmer, IotLightStrip, IotPlug, IotStrip
|
||||
from kasa.protocol import BaseTransport
|
||||
from kasa.smart import SmartBulb, SmartPlug
|
||||
from kasa.smart import SmartBulb, SmartDevice
|
||||
from kasa.xortransport import XorEncryption
|
||||
|
||||
from .fakeprotocol_iot import FakeIotProtocol
|
||||
@ -108,7 +108,6 @@ PLUGS_SMART = {
|
||||
"EP25",
|
||||
"KS205",
|
||||
"P125M",
|
||||
"P135",
|
||||
"S505",
|
||||
"TP15",
|
||||
}
|
||||
@ -121,7 +120,7 @@ STRIPS_SMART = {"P300", "TP25"}
|
||||
STRIPS = {*STRIPS_IOT, *STRIPS_SMART}
|
||||
|
||||
DIMMERS_IOT = {"ES20M", "HS220", "KS220M", "KS230", "KP405"}
|
||||
DIMMERS_SMART = {"S500D"}
|
||||
DIMMERS_SMART = {"S500D", "P135"}
|
||||
DIMMERS = {
|
||||
*DIMMERS_IOT,
|
||||
*DIMMERS_SMART,
|
||||
@ -346,7 +345,7 @@ def device_for_file(model, protocol):
|
||||
if protocol == "SMART":
|
||||
for d in PLUGS_SMART:
|
||||
if d in model:
|
||||
return SmartPlug
|
||||
return SmartDevice
|
||||
for d in BULBS_SMART:
|
||||
if d in model:
|
||||
return SmartBulb
|
||||
@ -355,7 +354,7 @@ def device_for_file(model, protocol):
|
||||
return SmartBulb
|
||||
for d in STRIPS_SMART:
|
||||
if d in model:
|
||||
return SmartPlug
|
||||
return SmartDevice
|
||||
else:
|
||||
for d in STRIPS_IOT:
|
||||
if d in model:
|
||||
|
@ -37,9 +37,6 @@ async def test_led(dev):
|
||||
@plug_smart
|
||||
async def test_plug_device_info(dev):
|
||||
assert dev._info is not None
|
||||
# PLUG_SCHEMA(dev.sys_info)
|
||||
|
||||
assert dev.model is not None
|
||||
|
||||
assert dev.device_type == DeviceType.Plug or dev.device_type == DeviceType.Strip
|
||||
# assert dev.is_plug or dev.is_strip
|
||||
|
@ -22,16 +22,21 @@ from voluptuous import (
|
||||
|
||||
import kasa
|
||||
from kasa import Credentials, Device, DeviceConfig, KasaException
|
||||
from kasa.device_type import DeviceType
|
||||
from kasa.exceptions import SmartErrorCode
|
||||
from kasa.iot import IotDevice
|
||||
from kasa.smart import SmartChildDevice, SmartDevice
|
||||
|
||||
from .conftest import (
|
||||
bulb,
|
||||
device_iot,
|
||||
device_smart,
|
||||
dimmer,
|
||||
handle_turn_on,
|
||||
has_emeter_iot,
|
||||
lightstrip,
|
||||
no_emeter_iot,
|
||||
plug,
|
||||
turn_on,
|
||||
)
|
||||
from .fakeprotocol_iot import FakeIotProtocol
|
||||
@ -416,3 +421,25 @@ SYSINFO_SCHEMA = Schema(
|
||||
},
|
||||
extra=REMOVE_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
@dimmer
|
||||
def test_device_type_dimmer(dev):
|
||||
assert dev.device_type == DeviceType.Dimmer
|
||||
|
||||
|
||||
@bulb
|
||||
def test_device_type_bulb(dev):
|
||||
if dev.is_light_strip:
|
||||
pytest.skip("bulb has also lightstrips to test the api")
|
||||
assert dev.device_type == DeviceType.Bulb
|
||||
|
||||
|
||||
@plug
|
||||
def test_device_type_plug(dev):
|
||||
assert dev.device_type == DeviceType.Plug
|
||||
|
||||
|
||||
@lightstrip
|
||||
def test_device_type_lightstrip(dev):
|
||||
assert dev.device_type == DeviceType.LightStrip
|
||||
|
Loading…
x
Reference in New Issue
Block a user