FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Keep multi requests for smartcam devices after a timeout by hugaraujo · Pull Request #1802 · python-kasa/python-kasa · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (3) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
2 changes: 2 additions & 0 deletions kasa/protocols/smartcamprotocol.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class SingleRequest:
class SmartCamProtocol(SmartProtocol):
"""Class for SmartCam Protocol."""

REQUIRES_MULTIREQUESTS = True

def _get_list_request(
self, method: str, params: dict | None, start_index: int
) -> dict:
Expand Down
5 changes: 5 additions & 0 deletions kasa/protocols/smartprotocol.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class SmartProtocol(BaseProtocol):

BACKOFF_SECONDS_AFTER_TIMEOUT = 1
DEFAULT_MULTI_REQUEST_BATCH_SIZE = 5
# True if the device rejects single requests, so batching is never disabled.
REQUIRES_MULTIREQUESTS = False

def __init__(
self,
Expand Down Expand Up @@ -248,6 +250,8 @@ async def _execute_multiple_query(
try:
response_step = await self._transport.send(smart_request)
except TimeoutError as ex:
if self.REQUIRES_MULTIREQUESTS:
raise
# P300 does not respond to some batched requests (e.g. both child
# list requests together) so disable batching. Batch size is never
# 1 here as that case sends single requests above.
Expand Down Expand Up @@ -278,6 +282,7 @@ async def _execute_multiple_query(
SmartErrorCode.INTERNAL_UNKNOWN_ERROR,
}
and self._multi_request_batch_size != 1
and not self.REQUIRES_MULTIREQUESTS
):
self._multi_request_batch_size = 1
raise _RetryableError(
Expand Down
33 changes: 33 additions & 0 deletions tests/protocols/test_smartprotocol.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,39 @@ async def _send(request: str) -> dict:
assert send_mock.call_count == 3


async def test_smartcam_multiple_request_timeout_keeps_batching(
dummy_protocol: SmartProtocol, mocker: MockerFixture
) -> None:
"""Test that a timeout does not disable batching for smartcam devices."""
protocol = SmartCamProtocol(transport=dummy_protocol._transport)
requests = {f"get_method_{i}": {"foo": "bar"} for i in range(3)}
batch_response = {
"result": {
"responses": [
{"method": method, "result": {"great": "success"}, "error_code": 0}
for method in requests
]
},
"error_code": 0,
}

send_mock = mocker.patch.object(
protocol._transport,
"send",
side_effect=[TimeoutError("Simulated timeout"), batch_response],
)
mocker.patch("asyncio.sleep")
batch_size = protocol._multi_request_batch_size
assert batch_size > 1
resp = await protocol.query(requests, retry_count=1)
assert resp == {method: {"great": "success"} for method in requests}
assert protocol._multi_request_batch_size == batch_size
# The timed out batch + the retried batch, no single requests
assert send_mock.call_count == 2
for call in send_mock.call_args_list:
assert json.loads(call.args[0])["method"] == "multipleRequest"


async def test_childdevicewrapper_unwrapping(
dummy_protocol: SmartProtocol, mocker: MockerFixture
) -> None:
Expand Down
Loading

Back | FazBrowse Home | New Git URL