Skip to content

Commit 69b6e0f

Browse files
allenporterCopilotLash-L
authored
feat: Add VacuumTrait to q10 devices (#754)
* Add VacuumTrait to q10 devices * Remove unused logger * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix lint errors * Remove unused logger * Fix test method name * Fix pydoc * chore: wording Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Luke Lashley <conway220@gmail.com>
1 parent 5f5a59b commit 69b6e0f

File tree

3 files changed

+111
-3
lines changed

3 files changed

+111
-3
lines changed

roborock/devices/traits/b01/q10/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
"""Traits for Q10 B01 devices."""
22

3-
from typing import Any
4-
5-
from roborock.devices.rpc.b01_q7_channel import send_decoded_command
63
from roborock.devices.traits import Trait
74
from roborock.devices.transport.mqtt_channel import MqttChannel
85

96
from .command import CommandTrait
7+
from .vacuum import VacuumTrait
108

119
__all__ = [
1210
"Q10PropertiesApi",
@@ -19,9 +17,13 @@ class Q10PropertiesApi(Trait):
1917
command: CommandTrait
2018
"""Trait for sending commands to Q10 devices."""
2119

20+
vacuum: VacuumTrait
21+
"""Trait for sending vacuum related commands to Q10 devices."""
22+
2223
def __init__(self, channel: MqttChannel) -> None:
2324
"""Initialize the B01Props API."""
2425
self.command = CommandTrait(channel)
26+
self.vacuum = VacuumTrait(self.command)
2527

2628

2729
def create(channel: MqttChannel) -> Q10PropertiesApi:
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""Traits for Q10 B01 devices."""
2+
3+
from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
4+
5+
from .command import CommandTrait
6+
7+
8+
class VacuumTrait:
9+
"""Trait for sending vacuum commands.
10+
11+
This is a wrapper around the CommandTrait for sending vacuum related
12+
commands to Q10 devices.
13+
"""
14+
15+
def __init__(self, command: CommandTrait) -> None:
16+
"""Initialize the VacuumTrait."""
17+
self._command = command
18+
19+
async def start_clean(self) -> None:
20+
"""Start cleaning."""
21+
await self._command.send(
22+
command=B01_Q10_DP.START_CLEAN,
23+
# TODO: figure out other commands
24+
# 1 = start cleaning
25+
# 2 = "electoral" clean, also has "clean_parameters"
26+
# 4 = fast create map
27+
params={"cmd": 1},
28+
)
29+
30+
async def pause_clean(self) -> None:
31+
"""Pause cleaning."""
32+
await self._command.send(
33+
command=B01_Q10_DP.PAUSE,
34+
params={},
35+
)
36+
37+
async def resume_clean(self) -> None:
38+
"""Resume cleaning."""
39+
await self._command.send(
40+
command=B01_Q10_DP.RESUME,
41+
params={},
42+
)
43+
44+
async def stop_clean(self) -> None:
45+
"""Stop cleaning."""
46+
await self._command.send(
47+
command=B01_Q10_DP.STOP,
48+
params={},
49+
)
50+
51+
async def return_to_dock(self) -> None:
52+
"""Return to dock."""
53+
await self._command.send(
54+
command=B01_Q10_DP.START_DOCK_TASK,
55+
params={},
56+
)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import json
2+
from collections.abc import Awaitable, Callable
3+
from typing import Any
4+
5+
import pytest
6+
7+
from roborock.devices.traits.b01.q10 import Q10PropertiesApi
8+
from roborock.devices.traits.b01.q10.vacuum import VacuumTrait
9+
from tests.fixtures.channel_fixtures import FakeChannel
10+
11+
12+
@pytest.fixture(name="fake_channel")
13+
def fake_channel_fixture() -> FakeChannel:
14+
return FakeChannel()
15+
16+
17+
@pytest.fixture(name="q10_api")
18+
def q10_api_fixture(fake_channel: FakeChannel) -> Q10PropertiesApi:
19+
return Q10PropertiesApi(fake_channel) # type: ignore[arg-type]
20+
21+
22+
@pytest.fixture(name="vacuumm")
23+
def vacuumm_fixture(q10_api: Q10PropertiesApi) -> VacuumTrait:
24+
return q10_api.vacuum
25+
26+
27+
@pytest.mark.parametrize(
28+
("command_fn", "expected_payload"),
29+
[
30+
(lambda x: x.start_clean(), {"201": {"cmd": 1}}),
31+
(lambda x: x.pause_clean(), {"204": {}}),
32+
(lambda x: x.resume_clean(), {"205": {}}),
33+
(lambda x: x.stop_clean(), {"206": {}}),
34+
(lambda x: x.return_to_dock(), {"203": {}}),
35+
],
36+
)
37+
async def test_vacuum_commands(
38+
vacuumm: VacuumTrait,
39+
fake_channel: FakeChannel,
40+
command_fn: Callable[[VacuumTrait], Awaitable[None]],
41+
expected_payload: dict[str, Any],
42+
) -> None:
43+
"""Test sending a vacuum start command."""
44+
await command_fn(vacuumm)
45+
46+
assert len(fake_channel.published_messages) == 1
47+
message = fake_channel.published_messages[0]
48+
assert message.payload
49+
payload_data = json.loads(message.payload.decode())
50+
assert payload_data == {"dps": expected_payload}

0 commit comments

Comments
 (0)