-
-
Notifications
You must be signed in to change notification settings - Fork 567
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve roborock update handling (#1685)
Not all devices support all features, but we have currently no way of knowing what is supported. In order to allow the embedding of all supported information in the status container while avoiding making unnecessary I/O on subsequent queries, this introduces a small helper to do just that. The initial status() call will call all defined devicestatus-returning methods to find out which information is acquired correctly, and skip the unsupported queries in the following update cycles. This also embeds some more information (last clean details, mop dryer settings).
- Loading branch information
Showing
5 changed files
with
132 additions
and
29 deletions.
There are no files selected for viewing
28 changes: 28 additions & 0 deletions
28
miio/integrations/roborock/vacuum/tests/test_updatehelper.py
This file contains 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 |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from unittest.mock import MagicMock | ||
|
||
from miio import DeviceException | ||
|
||
from ..updatehelper import UpdateHelper | ||
|
||
|
||
def test_updatehelper(): | ||
"""Test that update helper removes erroring methods from future updates.""" | ||
main_status = MagicMock() | ||
second_status = MagicMock() | ||
unsupported = MagicMock(side_effect=DeviceException("Broken")) | ||
helper = UpdateHelper(main_status) | ||
helper.add_update_method("working", second_status) | ||
helper.add_update_method("broken", unsupported) | ||
|
||
helper.status() | ||
|
||
main_status.assert_called_once() | ||
second_status.assert_called_once() | ||
unsupported.assert_called_once() | ||
|
||
# perform second update | ||
helper.status() | ||
|
||
assert main_status.call_count == 2 | ||
assert second_status.call_count == 2 | ||
assert unsupported.call_count == 1 |
This file contains 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
This file contains 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 |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import logging | ||
from typing import Callable, Dict | ||
|
||
from miio import DeviceException, DeviceStatus | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class UpdateHelper: | ||
"""Helper class to construct status containers using multiple status methods. | ||
This is used to perform status fetching on integrations that require calling | ||
multiple methods, some of which may not be supported by the target device. | ||
This class automatically removes the methods that failed from future updates, | ||
to avoid unnecessary device I/O. | ||
""" | ||
|
||
def __init__(self, main_update_method: Callable): | ||
self._update_methods: Dict[str, Callable] = {} | ||
self._main_update_method = main_update_method | ||
|
||
def add_update_method(self, name: str, update_method: Callable): | ||
"""Add status method to be called.""" | ||
_LOGGER.debug(f"Adding {name} to update cycle: {update_method}") | ||
self._update_methods[name] = update_method | ||
|
||
def status(self) -> DeviceStatus: | ||
statuses = self._update_methods.copy() | ||
main_status = self._main_update_method() | ||
for name, method in statuses.items(): | ||
try: | ||
main_status.embed(name, method()) | ||
_LOGGER.debug(f"Success for {name}") | ||
except DeviceException as ex: | ||
_LOGGER.debug( | ||
"Unable to query %s, removing from next query: %s", name, ex | ||
) | ||
self._update_methods.pop(name) | ||
|
||
return main_status |
This file contains 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
This file contains 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