-
-
Notifications
You must be signed in to change notification settings - Fork 558
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add fan speed presets to VacuumInterface (#1405)
* Added Xiaomi Vaccum Mop 2 Ultra and Pro+ * Updated automatic formatting using black * Removed duplicated supported models * Extended dreame test to test all supported models * Added test for invalid dreame model * Formatting by black * import isort * Updated readme with newly supported models * Added support for Vacuum interface: VaccumDevice and VacuumMiotDevice * Fixed isort * Removing unnecessary pass * Feedback from PR: VaccumDevice renamed to VacuumInterface * Step2: VacuumInterface no moreinherits Device * Unit test fixed * VaccumInterface published as symbol available for the "interface" package * Added two methods into VacuumInterface: - fan_speed_presets() - set_fan_speed_preset(speed) * Added vacuum unit test * Fixed python 3.10 * Imporved test coverage * Additional increase of test coverage * Added test for param validation in set_fan_speed_preset() * unit test simplification * Feedback from PR * Minor DOCS improvement * Minor docs update * Feedback from PR * Updated noqa codes for new flake8 version * remove copyright notice update * Rework docstrings Co-authored-by: Teemu Rytilahti <tpr@iki.fi>
- Loading branch information
Showing
12 changed files
with
165 additions
and
27 deletions.
There are no files selected for viewing
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
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
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
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
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 |
---|---|---|
@@ -1,5 +1,5 @@ | ||
"""Interfaces API.""" | ||
|
||
from .vacuuminterface import VacuumInterface | ||
from .vacuuminterface import FanspeedPresets, VacuumInterface | ||
|
||
__all__ = ["VacuumInterface"] | ||
__all__ = ["FanspeedPresets", "VacuumInterface"] |
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 |
---|---|---|
@@ -1,23 +1,46 @@ | ||
"""`VacuumInterface` is an interface (abstract class) with shared API for all vacuum | ||
devices.""" | ||
from abc import abstractmethod | ||
from typing import Dict | ||
|
||
# Dictionary of predefined fan speeds | ||
FanspeedPresets = Dict[str, int] | ||
|
||
|
||
class VacuumInterface: | ||
"""Vacuum API interface.""" | ||
|
||
@abstractmethod | ||
def home(self): | ||
"""Return to home.""" | ||
"""Return vacuum robot to home station/dock.""" | ||
|
||
@abstractmethod | ||
def start(self): | ||
"""Start cleaning.""" | ||
|
||
@abstractmethod | ||
def stop(self): | ||
"""Validate that Stop cleaning.""" | ||
"""Stop cleaning.""" | ||
|
||
def pause(self): | ||
"""Pause cleaning.""" | ||
"""Pause cleaning. | ||
:raises RuntimeError: if the method is not supported by the device | ||
""" | ||
raise RuntimeError("`pause` not supported") | ||
|
||
@abstractmethod | ||
def fan_speed_presets(self) -> FanspeedPresets: | ||
"""Return available fan speed presets. | ||
The returned object is a dictionary where the key is user-readable name and the | ||
value is input for :func:`set_fan_speed_preset()`. | ||
""" | ||
|
||
@abstractmethod | ||
def set_fan_speed_preset(self, speed_preset: int) -> None: | ||
"""Set fan speed preset speed. | ||
:param speed_preset: a value from :func:`fan_speed_presets()` | ||
:raises ValueError: for invalid preset value | ||
""" |
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,55 @@ | ||
"""Test of vacuum devices.""" | ||
from collections.abc import Iterable | ||
from typing import List, Sequence, Tuple, Type | ||
|
||
import pytest | ||
|
||
from miio.device import Device | ||
from miio.integrations.vacuum.roborock.vacuum import ROCKROBO_V1 | ||
from miio.interfaces import VacuumInterface | ||
|
||
# list of all supported vacuum classes | ||
VACUUM_CLASSES: Tuple[Type[VacuumInterface], ...] = tuple( | ||
cl for cl in VacuumInterface.__subclasses__() # type: ignore | ||
) | ||
|
||
|
||
def _all_vacuum_models() -> Sequence[Tuple[Type[Device], str]]: | ||
""":return: list of tuples with supported vacuum models with corresponding class""" | ||
result: List[Tuple[Type[Device], str]] = [] | ||
for cls in VACUUM_CLASSES: | ||
assert issubclass(cls, Device) | ||
vacuum_models = cls.supported_models | ||
assert isinstance(vacuum_models, Iterable) | ||
for model in vacuum_models: | ||
result.append((cls, model)) | ||
return result # type: ignore | ||
|
||
|
||
@pytest.mark.parametrize("cls, model", _all_vacuum_models()) | ||
def test_vacuum_fan_speed_presets(cls: Type[Device], model: str) -> None: | ||
"""Test method VacuumInterface.fan_speed_presets()""" | ||
if model == ROCKROBO_V1: | ||
return # this model cannot be tested because presets depends on firmware | ||
dev = cls("127.0.0.1", "68ffffffffffffffffffffffffffffff", model=model) | ||
assert isinstance(dev, VacuumInterface) | ||
presets = dev.fan_speed_presets() | ||
assert presets is not None, "presets must be defined" | ||
assert bool(presets), "presets cannot be empty" | ||
assert isinstance(presets, dict), "presets must be dictionary" | ||
for name, value in presets.items(): | ||
assert isinstance(name, str), "presets key must be string" | ||
assert name, "presets key cannot be empty" | ||
assert isinstance(value, int), "presets value must be integer" | ||
assert value >= 0, "presets value must be >= 0" | ||
|
||
|
||
@pytest.mark.parametrize("cls, model", _all_vacuum_models()) | ||
def test_vacuum_set_fan_speed_presets_fails(cls: Type[Device], model: str) -> None: | ||
"""Test method VacuumInterface.fan_speed_presets()""" | ||
if model == ROCKROBO_V1: | ||
return # this model cannot be tested because presets depends on firmware | ||
dev = cls("127.0.0.1", "68ffffffffffffffffffffffffffffff", model=model) | ||
assert isinstance(dev, VacuumInterface) | ||
with pytest.raises(ValueError): | ||
dev.set_fan_speed_preset(-1) |