Skip to content

Commit 6e00244

Browse files
authored
Merge branch 'main' into dynamic_clean_modes
2 parents cade07d + 2a800c2 commit 6e00244

27 files changed

+619
-292
lines changed

poetry.lock

Lines changed: 24 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "python-roborock"
3-
version = "2.33.0"
3+
version = "2.35.0"
44
description = "A package to control Roborock vacuums."
55
authors = ["humbertogontijo <[email protected]>"]
66
license = "GPL-3.0-only"

roborock/api.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
from __future__ import annotations
44

55
import asyncio
6-
import base64
76
import logging
8-
import secrets
97
import time
108
from abc import ABC, abstractmethod
119
from typing import Any
@@ -37,14 +35,11 @@ class RoborockClient(ABC):
3735
def __init__(self, device_info: DeviceData) -> None:
3836
"""Initialize RoborockClient."""
3937
self.device_info = device_info
40-
self._nonce = secrets.token_bytes(16)
4138
self._waiting_queue: dict[int, RoborockFuture] = {}
4239
self._last_device_msg_in = time.monotonic()
4340
self._last_disconnection = time.monotonic()
4441
self.keep_alive = KEEPALIVE
45-
self._diagnostic_data: dict[str, dict[str, Any]] = {
46-
"misc_info": {"Nonce": base64.b64encode(self._nonce).decode("utf-8")}
47-
}
42+
self._diagnostic_data: dict[str, dict[str, Any]] = {}
4843
self.is_available: bool = True
4944

5045
async def async_release(self) -> None:
@@ -116,7 +111,3 @@ def _async_response(self, request_id: int, protocol_id: int = 0) -> Any:
116111
request_id = new_id
117112
self._waiting_queue[request_id] = queue
118113
return asyncio.ensure_future(self._wait_response(request_id, queue))
119-
120-
@abstractmethod
121-
async def send_message(self, roborock_message: RoborockMessage):
122-
"""Send a message to the Roborock device."""

roborock/clean_modes.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]:
9696
if features.is_customized_clean_supported:
9797
modes.append(VacuumModes.CUSTOMIZED)
9898

99+
def get_clean_modes(features: DeviceFeatures) -> list[CleanModes]:
100+
"""Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'"""
101+
modes = [CleanModes.QUIET, CleanModes.BALANCED, CleanModes.TURBO, CleanModes.MAX]
102+
if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus:
103+
# If the vacuum has max plus mode supported
104+
modes.append(CleanModes.MAX_PLUS)
105+
if features.is_pure_clean_mop_supported:
106+
# If the vacuum is capable of 'pure mop clean' aka no vacuum
107+
modes.append(CleanModes.OFF)
108+
else:
109+
# If not, we can add gentle
110+
modes.append(CleanModes.GENTLE)
99111
return modes
100112

101113

roborock/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ async def _discover(ctx):
163163
if not cache_data:
164164
raise Exception("You need to login first")
165165
client = RoborockApiClient(cache_data.email)
166-
home_data = await client.get_home_data(cache_data.user_data)
166+
home_data = await client.get_home_data_v3(cache_data.user_data)
167167
cache_data.home_data = home_data
168168
context.update(cache_data)
169169
click.echo(f"Discovered devices {', '.join([device.name for device in home_data.get_all_devices()])}")

roborock/devices/b01_channel.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Thin wrapper around the MQTT channel for Roborock B01 devices."""
2+
3+
from __future__ import annotations
4+
5+
import logging
6+
from typing import Any
7+
8+
from roborock.protocols.b01_protocol import (
9+
CommandType,
10+
ParamsType,
11+
decode_rpc_response,
12+
encode_mqtt_payload,
13+
)
14+
15+
from .mqtt_channel import MqttChannel
16+
17+
_LOGGER = logging.getLogger(__name__)
18+
19+
20+
async def send_decoded_command(
21+
mqtt_channel: MqttChannel,
22+
dps: int,
23+
command: CommandType,
24+
params: ParamsType,
25+
) -> dict[int, Any]:
26+
"""Send a command on the MQTT channel and get a decoded response."""
27+
_LOGGER.debug("Sending MQTT command: %s", params)
28+
roborock_message = encode_mqtt_payload(dps, command, params)
29+
response = await mqtt_channel.send_message(roborock_message)
30+
return decode_rpc_response(response) # type: ignore[return-value]

roborock/devices/device_manager.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .cache import Cache, NoCache
2222
from .channel import Channel
2323
from .mqtt_channel import create_mqtt_channel
24+
from .traits.b01.props import B01PropsApi
2425
from .traits.dyad import DyadApi
2526
from .traits.status import StatusTrait
2627
from .traits.trait import Trait
@@ -45,6 +46,7 @@ class DeviceVersion(enum.StrEnum):
4546

4647
V1 = "1.0"
4748
A01 = "A01"
49+
B01 = "B01"
4850
UNKNOWN = "unknown"
4951

5052

@@ -120,7 +122,7 @@ def create_home_data_api(email: str, user_data: UserData) -> HomeDataApi:
120122
client = RoborockApiClient(email)
121123

122124
async def home_data_api() -> HomeData:
123-
return await client.get_home_data(user_data)
125+
return await client.get_home_data_v3(user_data)
124126

125127
return home_data_api
126128

@@ -159,6 +161,9 @@ def device_creator(device: HomeDataDevice, product: HomeDataProduct) -> Roborock
159161
traits.append(ZeoApi(mqtt_channel))
160162
case _:
161163
raise NotImplementedError(f"Device {device.name} has unsupported category {product.category}")
164+
case DeviceVersion.B01:
165+
mqtt_channel = create_mqtt_channel(user_data, mqtt_params, mqtt_session, device)
166+
traits.append(B01PropsApi(mqtt_channel))
162167
case _:
163168
raise NotImplementedError(f"Device {device.name} has unsupported version {device.pv}")
164169
return RoborockDevice(device, channel, traits)

roborock/devices/traits/b01/__init__.py

Whitespace-only changes.

roborock/devices/traits/b01/props.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from typing import Any
5+
6+
from roborock import RoborockB01Methods
7+
from roborock.roborock_message import RoborockB01Props
8+
9+
from ...b01_channel import send_decoded_command
10+
from ...mqtt_channel import MqttChannel
11+
from ..trait import Trait
12+
13+
_LOGGER = logging.getLogger(__name__)
14+
15+
__all__ = [
16+
"B01PropsApi",
17+
]
18+
19+
20+
class B01PropsApi(Trait):
21+
"""API for interacting with B01 devices."""
22+
23+
name = "B01_props"
24+
25+
def __init__(self, channel: MqttChannel) -> None:
26+
"""Initialize the B01Props API."""
27+
self._channel = channel
28+
29+
async def query_values(self, props: list[RoborockB01Props]) -> dict[int, Any]:
30+
"""Query the device for the values of the given Dyad protocols."""
31+
return await send_decoded_command(self._channel, dps=10000, command=RoborockB01Methods.GET_PROP, params=props)

roborock/local_api.py

Lines changed: 0 additions & 139 deletions
This file was deleted.

0 commit comments

Comments
 (0)