mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 03:33:35 +00:00
Parse features only during updates (#527)
Every time emeter functions were called features had to be re-parsed. For power strips, thats a lot of re-parses. Only parse them when we update.
This commit is contained in:
parent
0ec0826cc7
commit
9930311b54
@ -92,6 +92,12 @@ def requires_update(f):
|
|||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache
|
||||||
|
def _parse_features(features: str) -> Set[str]:
|
||||||
|
"""Parse features string."""
|
||||||
|
return set(features.split(":"))
|
||||||
|
|
||||||
|
|
||||||
class SmartDevice:
|
class SmartDevice:
|
||||||
"""Base class for all supported device types.
|
"""Base class for all supported device types.
|
||||||
|
|
||||||
@ -213,6 +219,7 @@ class SmartDevice:
|
|||||||
# are not accessed incorrectly.
|
# are not accessed incorrectly.
|
||||||
self._last_update: Any = None
|
self._last_update: Any = None
|
||||||
self._sys_info: Any = None # TODO: this is here to avoid changing tests
|
self._sys_info: Any = None # TODO: this is here to avoid changing tests
|
||||||
|
self._features: Set[str] = set()
|
||||||
self.modules: Dict[str, Any] = {}
|
self.modules: Dict[str, Any] = {}
|
||||||
|
|
||||||
self.children: List["SmartDevice"] = []
|
self.children: List["SmartDevice"] = []
|
||||||
@ -284,11 +291,7 @@ class SmartDevice:
|
|||||||
@requires_update
|
@requires_update
|
||||||
def features(self) -> Set[str]:
|
def features(self) -> Set[str]:
|
||||||
"""Return a set of features that the device supports."""
|
"""Return a set of features that the device supports."""
|
||||||
try:
|
return self._features
|
||||||
return set(self.sys_info["feature"].split(":"))
|
|
||||||
except KeyError:
|
|
||||||
_LOGGER.debug("Device does not have feature information")
|
|
||||||
return set()
|
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@requires_update
|
@requires_update
|
||||||
@ -321,11 +324,12 @@ class SmartDevice:
|
|||||||
# See #105, #120, #161
|
# See #105, #120, #161
|
||||||
if self._last_update is None:
|
if self._last_update is None:
|
||||||
_LOGGER.debug("Performing the initial update to obtain sysinfo")
|
_LOGGER.debug("Performing the initial update to obtain sysinfo")
|
||||||
self._last_update = await self.protocol.query(req)
|
response = await self.protocol.query(req)
|
||||||
self._sys_info = self._last_update["system"]["get_sysinfo"]
|
self._last_update = response
|
||||||
|
self._set_sys_info(response["system"]["get_sysinfo"])
|
||||||
|
|
||||||
await self._modular_update(req)
|
await self._modular_update(req)
|
||||||
self._sys_info = self._last_update["system"]["get_sysinfo"]
|
self._set_sys_info(self._last_update["system"]["get_sysinfo"])
|
||||||
|
|
||||||
async def _modular_update(self, req: dict) -> None:
|
async def _modular_update(self, req: dict) -> None:
|
||||||
"""Execute an update query."""
|
"""Execute an update query."""
|
||||||
@ -366,10 +370,18 @@ class SmartDevice:
|
|||||||
update = {**update, **response}
|
update = {**update, **response}
|
||||||
self._last_update = update
|
self._last_update = update
|
||||||
|
|
||||||
def update_from_discover_info(self, info):
|
def update_from_discover_info(self, info: Dict[str, Any]) -> None:
|
||||||
"""Update state from info from the discover call."""
|
"""Update state from info from the discover call."""
|
||||||
self._last_update = info
|
self._last_update = info
|
||||||
self._sys_info = info["system"]["get_sysinfo"]
|
self._set_sys_info(info["system"]["get_sysinfo"])
|
||||||
|
|
||||||
|
def _set_sys_info(self, sys_info: Dict[str, Any]) -> None:
|
||||||
|
"""Set sys_info."""
|
||||||
|
self._sys_info = sys_info
|
||||||
|
if features := sys_info.get("feature"):
|
||||||
|
self._features = _parse_features(features)
|
||||||
|
else:
|
||||||
|
self._features = set()
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@requires_update
|
@requires_update
|
||||||
|
@ -259,7 +259,7 @@ class SmartStripPlug(SmartPlug):
|
|||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.child_id = child_id
|
self.child_id = child_id
|
||||||
self._last_update = parent._last_update
|
self._last_update = parent._last_update
|
||||||
self._sys_info = parent._sys_info
|
self._set_sys_info(parent.sys_info)
|
||||||
self._device_type = DeviceType.StripSocket
|
self._device_type = DeviceType.StripSocket
|
||||||
self.modules = {}
|
self.modules = {}
|
||||||
self.protocol = parent.protocol # Must use the same connection as the parent
|
self.protocol = parent.protocol # Must use the same connection as the parent
|
||||||
|
@ -37,6 +37,7 @@ async def test_invalid_connection(dev):
|
|||||||
async def test_initial_update_emeter(dev, mocker):
|
async def test_initial_update_emeter(dev, mocker):
|
||||||
"""Test that the initial update performs second query if emeter is available."""
|
"""Test that the initial update performs second query if emeter is available."""
|
||||||
dev._last_update = None
|
dev._last_update = None
|
||||||
|
dev._features = set()
|
||||||
spy = mocker.spy(dev.protocol, "query")
|
spy = mocker.spy(dev.protocol, "query")
|
||||||
await dev.update()
|
await dev.update()
|
||||||
# Devices with small buffers may require 3 queries
|
# Devices with small buffers may require 3 queries
|
||||||
@ -48,6 +49,7 @@ async def test_initial_update_emeter(dev, mocker):
|
|||||||
async def test_initial_update_no_emeter(dev, mocker):
|
async def test_initial_update_no_emeter(dev, mocker):
|
||||||
"""Test that the initial update performs second query if emeter is available."""
|
"""Test that the initial update performs second query if emeter is available."""
|
||||||
dev._last_update = None
|
dev._last_update = None
|
||||||
|
dev._features = set()
|
||||||
spy = mocker.spy(dev.protocol, "query")
|
spy = mocker.spy(dev.protocol, "query")
|
||||||
await dev.update()
|
await dev.update()
|
||||||
# 2 calls are necessary as some devices crash on unexpected modules
|
# 2 calls are necessary as some devices crash on unexpected modules
|
||||||
|
Loading…
Reference in New Issue
Block a user