Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add common interface for vacuums #1368

Merged
merged 20 commits into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion miio/integrations/vacuum/dreame/dreamevacuum_miot.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from miio.click_common import command, format_output
from miio.exceptions import DeviceException
from miio.interfaces import VacuumInterface
from miio.miot_device import DeviceStatus as DeviceStatusContainer
from miio.miot_device import MiotDevice, MiotMapping

Expand Down Expand Up @@ -402,7 +403,7 @@ def is_water_box_carriage_attached(self) -> Optional[bool]:
return None


class DreameVacuum(MiotDevice):
class DreameVacuum(MiotDevice, VacuumInterface):
_mappings = MIOT_MAPPING

@command(
Expand Down
3 changes: 2 additions & 1 deletion miio/integrations/vacuum/mijia/g1vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import click

from miio.click_common import EnumType, command, format_output
from miio.interfaces import VacuumInterface
from miio.miot_device import DeviceStatus, MiotDevice

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -274,7 +275,7 @@ def total_clean_time(self) -> timedelta:
return timedelta(hours=self.data["total_clean_area"])


class G1Vacuum(MiotDevice):
class G1Vacuum(MiotDevice, VacuumInterface):
"""Support for G1 vacuum (G1, mijia.vacuum.v2)."""

_mappings = MIOT_MAPPING
Expand Down
3 changes: 2 additions & 1 deletion miio/integrations/vacuum/roborock/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)
from miio.device import Device, DeviceInfo
from miio.exceptions import DeviceException, DeviceInfoUnavailableException
from miio.interfaces import VacuumInterface

from .vacuumcontainers import (
CarpetModeStatus,
Expand Down Expand Up @@ -169,7 +170,7 @@ class CarpetCleaningMode(enum.Enum):
]


class RoborockVacuum(Device):
class RoborockVacuum(Device, VacuumInterface):
"""Main class for roborock vacuums (roborock.vacuum.*)."""

_supported_models = SUPPORTED_MODELS
Expand Down
3 changes: 2 additions & 1 deletion miio/integrations/vacuum/roidmi/roidmivacuum_miot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from miio.click_common import EnumType, command
from miio.integrations.vacuum.roborock.vacuumcontainers import DNDStatus
from miio.interfaces import VacuumInterface
from miio.miot_device import DeviceStatus, MiotDevice, MiotMapping

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -534,7 +535,7 @@ def sensor_dirty_left(self) -> timedelta:
return timedelta(minutes=self.data["sensor_dirty_time_left_minutes"])


class RoidmiVacuumMiot(MiotDevice):
class RoidmiVacuumMiot(MiotDevice, VacuumInterface):
"""Interface for Vacuum Eve Plus (roidmi.vacuum.v60)"""

_mappings = _MAPPINGS
Expand Down
3 changes: 2 additions & 1 deletion miio/integrations/vacuum/viomi/viomivacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
ConsumableStatus,
DNDStatus,
)
from miio.interfaces import VacuumInterface
from miio.utils import pretty_seconds

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -482,7 +483,7 @@ def _get_rooms_from_schedules(schedules: List[str]) -> Tuple[bool, Dict]:
return scheduled_found, rooms


class ViomiVacuum(Device):
class ViomiVacuum(Device, VacuumInterface):
"""Interface for Viomi vacuums (viomi.vacuum.v7)."""

_supported_models = SUPPORTED_MODELS
Expand Down
5 changes: 5 additions & 0 deletions miio/interfaces/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Interfaces API."""

from .vacuuminterface import VacuumInterface

__all__ = ["VacuumInterface"]
23 changes: 23 additions & 0 deletions miio/interfaces/vacuuminterface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""`VacuumInterface` is an interface (abstract class) with shared API for all vacuum
devices."""
from abc import abstractmethod


class VacuumInterface:
"""Vacuum API interface."""

@abstractmethod
def home(self):
"""Return to home."""

@abstractmethod
def start(self):
"""Start cleaning."""

@abstractmethod
def stop(self):
"""Validate that Stop cleaning."""

def pause(self):
"""Pause cleaning."""
raise RuntimeError("`pause` not supported")
4 changes: 1 addition & 3 deletions miio/tests/test_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from miio.exceptions import DeviceInfoUnavailableException, PayloadDecodeException

DEVICE_CLASSES = Device.__subclasses__() + MiotDevice.__subclasses__() # type: ignore
DEVICE_CLASSES.remove(MiotDevice)


@pytest.mark.parametrize("max_properties", [None, 1, 15])
Expand Down Expand Up @@ -144,7 +145,4 @@ def test_device_ctor_model(cls):
@pytest.mark.parametrize("cls", DEVICE_CLASSES)
def test_device_supported_models(cls):
"""Make sure that every device subclass has a non-empty supported models."""
if cls.__name__ == "MiotDevice": # skip miotdevice
return

assert cls.supported_models