Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fe116ea

Browse files
authored
Handle module errors more robustly and add query params to light preset and transition (#1043)
Ensures that all modules try to access their data in `_post_update_hook` in a safe manner and disable themselves if there's an error. Also adds parameters to get_preset_rules and get_on_off_gradually_info to fix issues with recent firmware updates. Cherry pick of [#1036](#1036) to patch
1 parent 2f24797 commit fe116ea

17 files changed

+206
-30
lines changed

devtools/helpers/smartrequests.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,15 @@ def get_preset_rules(params: GetRulesParams | None = None) -> SmartRequest:
284284
"""Get preset rules."""
285285
return SmartRequest("get_preset_rules", params or SmartRequest.GetRulesParams())
286286

287+
@staticmethod
288+
def get_on_off_gradually_info(
289+
params: SmartRequestParams | None = None,
290+
) -> SmartRequest:
291+
"""Get preset rules."""
292+
return SmartRequest(
293+
"get_on_off_gradually_info", params or SmartRequest.SmartRequestParams()
294+
)
295+
287296
@staticmethod
288297
def get_auto_light_info() -> SmartRequest:
289298
"""Get auto light info."""
@@ -382,7 +391,7 @@ def get_component_requests(component_id, ver_code):
382391
"auto_light": [SmartRequest.get_auto_light_info()],
383392
"light_effect": [SmartRequest.get_dynamic_light_effect_rules()],
384393
"bulb_quick_control": [],
385-
"on_off_gradually": [SmartRequest.get_raw_request("get_on_off_gradually_info")],
394+
"on_off_gradually": [SmartRequest.get_on_off_gradually_info()],
386395
"light_strip": [],
387396
"light_strip_lighting_effect": [
388397
SmartRequest.get_raw_request("get_lighting_effect")

kasa/smart/modules/autooff.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ class AutoOff(SmartModule):
1919

2020
def _initialize_features(self):
2121
"""Initialize features after the initial update."""
22-
if not isinstance(self.data, dict):
23-
_LOGGER.warning(
24-
"No data available for module, skipping %s: %s", self, self.data
25-
)
26-
return
27-
2822
self._add_feature(
2923
Feature(
3024
self._device,

kasa/smart/modules/batterysensor.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ def _initialize_features(self):
4343
)
4444
)
4545

46+
def query(self) -> dict:
47+
"""Query to execute during the update cycle."""
48+
return {}
49+
4650
@property
4751
def battery(self):
4852
"""Return battery level."""

kasa/smart/modules/cloud.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from typing import TYPE_CHECKING
66

7-
from ...exceptions import SmartErrorCode
87
from ...feature import Feature
98
from ..smartmodule import SmartModule
109

@@ -18,6 +17,13 @@ class Cloud(SmartModule):
1817
QUERY_GETTER_NAME = "get_connect_cloud_state"
1918
REQUIRED_COMPONENT = "cloud_connect"
2019

20+
def _post_update_hook(self):
21+
"""Perform actions after a device update.
22+
23+
Overrides the default behaviour to disable a module if the query returns
24+
an error because the logic here is to treat that as not connected.
25+
"""
26+
2127
def __init__(self, device: SmartDevice, module: str):
2228
super().__init__(device, module)
2329

@@ -37,6 +43,6 @@ def __init__(self, device: SmartDevice, module: str):
3743
@property
3844
def is_connected(self):
3945
"""Return True if device is connected to the cloud."""
40-
if isinstance(self.data, SmartErrorCode):
46+
if self._has_data_error():
4147
return False
4248
return self.data["status"] == 0

kasa/smart/modules/devicemodule.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ class DeviceModule(SmartModule):
1010

1111
REQUIRED_COMPONENT = "device"
1212

13+
def _post_update_hook(self):
14+
"""Perform actions after a device update.
15+
16+
Overrides the default behaviour to disable a module if the query returns
17+
an error because this module is critical.
18+
"""
19+
1320
def query(self) -> dict:
1421
"""Query to execute during the update cycle."""
1522
query = {

kasa/smart/modules/firmware.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from async_timeout import timeout as asyncio_timeout
1414
from pydantic.v1 import BaseModel, Field, validator
1515

16-
from ...exceptions import SmartErrorCode
1716
from ...feature import Feature
1817
from ..smartmodule import SmartModule
1918

@@ -123,6 +122,13 @@ def query(self) -> dict:
123122
req["get_auto_update_info"] = None
124123
return req
125124

125+
def _post_update_hook(self):
126+
"""Perform actions after a device update.
127+
128+
Overrides the default behaviour to disable a module if the query returns
129+
an error because some of the module still functions.
130+
"""
131+
126132
@property
127133
def current_firmware(self) -> str:
128134
"""Return the current firmware version."""
@@ -136,11 +142,11 @@ def latest_firmware(self) -> str:
136142
@property
137143
def firmware_update_info(self):
138144
"""Return latest firmware information."""
139-
fw = self.data.get("get_latest_fw") or self.data
140-
if not self._device.is_cloud_connected or isinstance(fw, SmartErrorCode):
145+
if not self._device.is_cloud_connected or self._has_data_error():
141146
# Error in response, probably disconnected from the cloud.
142147
return UpdateInfo(type=0, need_to_upgrade=False)
143148

149+
fw = self.data.get("get_latest_fw") or self.data
144150
return UpdateInfo.parse_obj(fw)
145151

146152
@property

kasa/smart/modules/frostprotection.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class FrostProtection(SmartModule):
1414
REQUIRED_COMPONENT = "frost_protection"
1515
QUERY_GETTER_NAME = "get_frost_protection"
1616

17+
def query(self) -> dict:
18+
"""Query to execute during the update cycle."""
19+
return {}
20+
1721
@property
1822
def enabled(self) -> bool:
1923
"""Return True if frost protection is on."""

kasa/smart/modules/humiditysensor.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def __init__(self, device: SmartDevice, module: str):
4545
)
4646
)
4747

48+
def query(self) -> dict:
49+
"""Query to execute during the update cycle."""
50+
return {}
51+
4852
@property
4953
def humidity(self):
5054
"""Return current humidity in percentage."""

kasa/smart/modules/lightpreset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def query(self) -> dict:
140140
"""Query to execute during the update cycle."""
141141
if self._state_in_sysinfo: # Child lights can have states in the child info
142142
return {}
143-
return {self.QUERY_GETTER_NAME: None}
143+
return {self.QUERY_GETTER_NAME: {"start_index": 0}}
144144

145145
async def _check_supported(self):
146146
"""Additional check to see if the module is supported by the device.

kasa/smart/modules/lighttransition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def query(self) -> dict:
230230
if self._state_in_sysinfo:
231231
return {}
232232
else:
233-
return {self.QUERY_GETTER_NAME: None}
233+
return {self.QUERY_GETTER_NAME: {}}
234234

235235
async def _check_supported(self):
236236
"""Additional check to see if the module is supported by the device."""

0 commit comments

Comments
 (0)