Skip to content

Commit

Permalink
Add XML command "CleanArea"
Browse files Browse the repository at this point in the history
  • Loading branch information
flubshi committed Feb 10, 2025
1 parent 86fbe07 commit 3181646
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 8 deletions.
27 changes: 27 additions & 0 deletions deebot_client/commands/xml/clean.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Clean commands."""

from __future__ import annotations

from deebot_client.models import CleanAction, CleanMode

from .common import ExecuteCommand


class CleanArea(ExecuteCommand):
"""Clean area command."""

NAME = "Clean"
HAS_SUB_ELEMENT = True

def __init__(self, mode: CleanMode, area: str, cleanings: int = 1) -> None:
# <ctl><clean type='SpotArea' act='s' speed='standard' deep='1' mid='4,5'/></ctl>

super().__init__(
{
"type": mode.xml_value,
"act": CleanAction.START.xml_value,
"speed": "standard", # TODO: FanSpeedLevel.NORMAL.xml_value, after #560 is merged
"deep": str(cleanings),
"mid": area,
}
)
54 changes: 46 additions & 8 deletions deebot_client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dataclasses import dataclass
from enum import IntEnum, StrEnum, unique
from pathlib import Path
from typing import TYPE_CHECKING, Required, TypedDict
from typing import TYPE_CHECKING, Required, Self, TypedDict

if TYPE_CHECKING:
from deebot_client.capabilities import Capabilities
Expand Down Expand Up @@ -67,19 +67,57 @@ class State(IntEnum):
class CleanAction(StrEnum):
"""Enum class for all possible clean actions."""

START = "start"
PAUSE = "pause"
RESUME = "resume"
STOP = "stop"
xml_value: str

def __new__(cls, value: str, xml_value: str = "") -> Self:
"""New CleanAction."""
obj = str.__new__(cls, value)
obj._value_ = value
obj.xml_value = xml_value
return obj

@classmethod
def from_xml(cls, value: str) -> CleanAction:
"""Get CleanAction from xml value."""
for clean_action in CleanAction:
if clean_action.xml_value == value:
return clean_action

Check warning on line 84 in deebot_client/models.py

View check run for this annotation

Codecov / codecov/patch

deebot_client/models.py#L84

Added line #L84 was not covered by tests

msg = f"{value} is not a valid {cls.__name__}"
raise ValueError(msg)

Check warning on line 87 in deebot_client/models.py

View check run for this annotation

Codecov / codecov/patch

deebot_client/models.py#L86-L87

Added lines #L86 - L87 were not covered by tests

START = "start", "s"
PAUSE = "pause", "p"
RESUME = "resume", "r"
STOP = "stop", "h"


@unique
class CleanMode(StrEnum):
"""Enum class for all possible clean modes."""

AUTO = "auto"
SPOT_AREA = "spotArea"
CUSTOM_AREA = "customArea"
xml_value: str

def __new__(cls, value: str, xml_value: str = "") -> Self:
"""New CleanMode."""
obj = str.__new__(cls, value)
obj._value_ = value
obj.xml_value = xml_value
return obj

@classmethod
def from_xml(cls, value: str) -> CleanMode:
"""Get CleanMode from xml value."""
for clean_mode in CleanMode:
if clean_mode.xml_value == value:
return clean_mode

Check warning on line 113 in deebot_client/models.py

View check run for this annotation

Codecov / codecov/patch

deebot_client/models.py#L113

Added line #L113 was not covered by tests

msg = f"{value} is not a valid {cls.__name__}"
raise ValueError(msg)

Check warning on line 116 in deebot_client/models.py

View check run for this annotation

Codecov / codecov/patch

deebot_client/models.py#L115-L116

Added lines #L115 - L116 were not covered by tests

AUTO = "auto", "auto"
SPOT_AREA = "spotArea", "SpotArea"
CUSTOM_AREA = "customArea", "spot"


@dataclass(frozen=True)
Expand Down
24 changes: 24 additions & 0 deletions tests/commands/xml/test_clean.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from __future__ import annotations

import pytest

from deebot_client.command import CommandResult
from deebot_client.commands.xml.clean import CleanArea
from deebot_client.message import HandlingState
from deebot_client.models import CleanMode
from tests.commands import assert_command

from . import get_request_xml


@pytest.mark.parametrize(
("command", "command_result"),
[
(CleanArea(CleanMode.SPOT_AREA, "4", 1), HandlingState.SUCCESS),
],
)
async def test_CleanArea(command: CleanArea, command_result: HandlingState) -> None:
json = get_request_xml("<ctl ret='ok'/>")
await assert_command(
command, json, None, command_result=CommandResult(command_result)
)

0 comments on commit 3181646

Please sign in to comment.