Skip to content

Commit 1ac49be

Browse files
authored
feat: add Q10 remote trait (#813)
* Add Q10 remote control trait * Deleted command Ids from remote.py Added commands enum to b01_q10_code_mappings.py Created pytest file * Updated test and deleted unneeded import * Changed some things, the test should be passed Well, i cant tell * Changed tests * Trying to patch the test * Add Q10 remote trait
1 parent 020dceb commit 1ac49be

4 files changed

Lines changed: 108 additions & 1 deletion

File tree

roborock/data/b01_q10/b01_q10_code_mappings.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from enum import IntEnum
2+
13
from ..code_mappings import RoborockModeEnum
24

35

@@ -217,3 +219,11 @@ class YXDeviceDustCollectionFrequency(RoborockModeEnum):
217219
INTERVAL_30 = "interval_30", 30
218220
INTERVAL_45 = "interval_45", 45
219221
INTERVAL_60 = "interval_60", 60
222+
223+
224+
class RemoteCommand(IntEnum):
225+
FORWARD = 0
226+
LEFT = 2
227+
RIGHT = 3
228+
STOP = 4
229+
EXIT = 5

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import asyncio
44
import logging
5-
from typing import Any
65

76
from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
87
from roborock.devices.rpc.b01_q10_channel import stream_decoded_responses
98
from roborock.devices.traits import Trait
109
from roborock.devices.transport.mqtt_channel import MqttChannel
1110

1211
from .command import CommandTrait
12+
from .remote import RemoteTrait
1313
from .status import StatusTrait
1414
from .vacuum import VacuumTrait
1515

@@ -32,11 +32,15 @@ class Q10PropertiesApi(Trait):
3232
vacuum: VacuumTrait
3333
"""Trait for sending vacuum related commands to Q10 devices."""
3434

35+
remote: RemoteTrait
36+
"""Trait for sending remote control related commands to Q10 devices."""
37+
3538
def __init__(self, channel: MqttChannel) -> None:
3639
"""Initialize the B01Props API."""
3740
self._channel = channel
3841
self.command = CommandTrait(channel)
3942
self.vacuum = VacuumTrait(self.command)
43+
self.remote = RemoteTrait(self.command)
4044
self.status = StatusTrait()
4145
self._subscribe_task: asyncio.Task[None] | None = None
4246

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Traits for Q10 B01 devices."""
2+
3+
from roborock.data.b01_q10.b01_q10_code_mappings import (
4+
B01_Q10_DP,
5+
RemoteCommand,
6+
)
7+
8+
from .command import CommandTrait
9+
10+
11+
class RemoteTrait:
12+
"""Trait for sending vacuum commands.
13+
14+
This is a wrapper around the CommandTrait for sending remote related
15+
commands to Q10 devices.
16+
"""
17+
18+
def __init__(self, command: CommandTrait) -> None:
19+
"""Initialize the RemoteTrait."""
20+
self._command = command
21+
22+
async def _send_remote(self, action: RemoteCommand) -> None:
23+
await self._command.send(B01_Q10_DP.COMMON, params={B01_Q10_DP.REMOTE: action.value})
24+
25+
async def forward(self) -> None:
26+
"""Move forward."""
27+
await self._send_remote(RemoteCommand.FORWARD)
28+
29+
async def left(self) -> None:
30+
"""Turn left."""
31+
await self._send_remote(RemoteCommand.LEFT)
32+
33+
async def right(self) -> None:
34+
"""Turn right."""
35+
await self._send_remote(RemoteCommand.RIGHT)
36+
37+
async def stop(self) -> None:
38+
"""Stop last moving command or start remote control."""
39+
await self._send_remote(RemoteCommand.STOP)
40+
41+
async def exit_remote(self) -> None:
42+
"""Exit remote control."""
43+
await self._send_remote(RemoteCommand.EXIT)
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.remote import RemoteTrait
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="remote")
23+
def remote_fixture(q10_api: Q10PropertiesApi) -> RemoteTrait:
24+
return q10_api.remote
25+
26+
27+
@pytest.mark.parametrize(
28+
("command_fn", "expected_payload"),
29+
[
30+
(lambda x: x.forward(), {"101": {"dpRemote": 0}}),
31+
(lambda x: x.left(), {"101": {"dpRemote": 2}}),
32+
(lambda x: x.right(), {"101": {"dpRemote": 3}}),
33+
(lambda x: x.stop(), {"101": {"dpRemote": 4}}),
34+
(lambda x: x.exit_remote(), {"101": {"dpRemote": 5}}),
35+
],
36+
)
37+
async def test_remote_commands(
38+
remote: RemoteTrait,
39+
fake_channel: FakeChannel,
40+
command_fn: Callable[[RemoteTrait], Awaitable[None]],
41+
expected_payload: dict[str, Any],
42+
) -> None:
43+
"""Test sending a remote start command."""
44+
await command_fn(remote)
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)