python-roborock 2.40.1__tar.gz → 2.41.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_roborock-2.40.1 → python_roborock-2.41.0}/PKG-INFO +1 -1
- {python_roborock-2.40.1 → python_roborock-2.41.0}/pyproject.toml +1 -1
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/containers.py +15 -14
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/device_manager.py +2 -0
- python_roborock-2.41.0/roborock/devices/traits/dnd.py +41 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/status.py +3 -3
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/v1_rpc_channel.py +6 -2
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/protocols/v1_protocol.py +3 -1
- {python_roborock-2.40.1 → python_roborock-2.41.0}/LICENSE +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/README.md +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/api.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/b01_containers.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/callbacks.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/clean_modes.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/cli.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/cloud_api.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/code_mappings.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/command_cache.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/const.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/device_features.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/README.md +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/a01_channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/b01_channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/cache.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/device.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/local_channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/mqtt_channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/b01/props.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/dyad.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/trait.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/traits/zeo.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/devices/v1_channel.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/exceptions.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/protocol.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/protocols/b01_protocol.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/py.typed +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/roborock_future.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/roborock_message.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/util.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/roborock_client_v1.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_a01_apis/__init__.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
- {python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/web_api.py +0 -0
|
@@ -109,8 +109,6 @@ def _decamelize(s: str):
|
|
|
109
109
|
|
|
110
110
|
@dataclass
|
|
111
111
|
class RoborockBase:
|
|
112
|
-
_ignore_keys = [] # type: ignore
|
|
113
|
-
|
|
114
112
|
@staticmethod
|
|
115
113
|
def _convert_to_class_obj(class_type: type, value):
|
|
116
114
|
if get_origin(class_type) is list:
|
|
@@ -134,8 +132,8 @@ class RoborockBase:
|
|
|
134
132
|
return None
|
|
135
133
|
field_types = {field.name: field.type for field in dataclasses.fields(cls)}
|
|
136
134
|
result: dict[str, Any] = {}
|
|
137
|
-
for
|
|
138
|
-
key = _decamelize(
|
|
135
|
+
for orig_key, value in data.items():
|
|
136
|
+
key = _decamelize(orig_key)
|
|
139
137
|
if (field_type := field_types.get(key)) is None:
|
|
140
138
|
continue
|
|
141
139
|
if value == "None" or value is None:
|
|
@@ -178,16 +176,18 @@ class RoborockBaseTimer(RoborockBase):
|
|
|
178
176
|
end_hour: int | None = None
|
|
179
177
|
end_minute: int | None = None
|
|
180
178
|
enabled: int | None = None
|
|
181
|
-
start_time: datetime.time | None = None
|
|
182
|
-
end_time: datetime.time | None = None
|
|
183
179
|
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
@property
|
|
181
|
+
def start_time(self) -> datetime.time | None:
|
|
182
|
+
return (
|
|
186
183
|
datetime.time(hour=self.start_hour, minute=self.start_minute)
|
|
187
184
|
if self.start_hour is not None and self.start_minute is not None
|
|
188
185
|
else None
|
|
189
186
|
)
|
|
190
|
-
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def end_time(self) -> datetime.time | None:
|
|
190
|
+
return (
|
|
191
191
|
datetime.time(hour=self.end_hour, minute=self.end_minute)
|
|
192
192
|
if self.end_hour is not None and self.end_minute is not None
|
|
193
193
|
else None
|
|
@@ -684,19 +684,20 @@ class MultiMapsListMapInfoBakMaps(RoborockBase):
|
|
|
684
684
|
|
|
685
685
|
@dataclass
|
|
686
686
|
class MultiMapsListMapInfo(RoborockBase):
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
mapFlag: int
|
|
687
|
+
map_flag: int
|
|
690
688
|
name: str
|
|
691
689
|
add_time: Any | None = None
|
|
692
690
|
length: Any | None = None
|
|
693
691
|
bak_maps: list[MultiMapsListMapInfoBakMaps] | None = None
|
|
694
692
|
|
|
693
|
+
@property
|
|
694
|
+
def mapFlag(self) -> int:
|
|
695
|
+
"""Alias for map_flag, returns the map flag as an integer."""
|
|
696
|
+
return self.map_flag
|
|
697
|
+
|
|
695
698
|
|
|
696
699
|
@dataclass
|
|
697
700
|
class MultiMapsList(RoborockBase):
|
|
698
|
-
_ignore_keys = ["mapFlag"]
|
|
699
|
-
|
|
700
701
|
max_multi_map: int | None = None
|
|
701
702
|
max_bak_map: int | None = None
|
|
702
703
|
multi_map_count: int | None = None
|
|
@@ -22,6 +22,7 @@ from .cache import Cache, NoCache
|
|
|
22
22
|
from .channel import Channel
|
|
23
23
|
from .mqtt_channel import create_mqtt_channel
|
|
24
24
|
from .traits.b01.props import B01PropsApi
|
|
25
|
+
from .traits.dnd import DoNotDisturbTrait
|
|
25
26
|
from .traits.dyad import DyadApi
|
|
26
27
|
from .traits.status import StatusTrait
|
|
27
28
|
from .traits.trait import Trait
|
|
@@ -152,6 +153,7 @@ async def create_device_manager(
|
|
|
152
153
|
case DeviceVersion.V1:
|
|
153
154
|
channel = create_v1_channel(user_data, mqtt_params, mqtt_session, device, cache)
|
|
154
155
|
traits.append(StatusTrait(product, channel.rpc_channel))
|
|
156
|
+
traits.append(DoNotDisturbTrait(channel.rpc_channel))
|
|
155
157
|
case DeviceVersion.A01:
|
|
156
158
|
mqtt_channel = create_mqtt_channel(user_data, mqtt_params, mqtt_session, device)
|
|
157
159
|
match product.category:
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Module for Roborock V1 devices.
|
|
2
|
+
|
|
3
|
+
This interface is experimental and subject to breaking changes without notice
|
|
4
|
+
until the API is stable.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
from roborock.containers import DnDTimer
|
|
10
|
+
from roborock.devices.v1_rpc_channel import V1RpcChannel
|
|
11
|
+
from roborock.roborock_typing import RoborockCommand
|
|
12
|
+
|
|
13
|
+
from .trait import Trait
|
|
14
|
+
|
|
15
|
+
_LOGGER = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"DoNotDisturbTrait",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class DoNotDisturbTrait(Trait):
|
|
23
|
+
"""Trait for managing Do Not Disturb (DND) settings on Roborock devices."""
|
|
24
|
+
|
|
25
|
+
name = "do_not_disturb"
|
|
26
|
+
|
|
27
|
+
def __init__(self, rpc_channel: V1RpcChannel) -> None:
|
|
28
|
+
"""Initialize the DoNotDisturbTrait."""
|
|
29
|
+
self._rpc_channel = rpc_channel
|
|
30
|
+
|
|
31
|
+
async def get_dnd_timer(self) -> DnDTimer:
|
|
32
|
+
"""Get the current Do Not Disturb (DND) timer settings of the device."""
|
|
33
|
+
return await self._rpc_channel.send_command(RoborockCommand.GET_DND_TIMER, response_type=DnDTimer)
|
|
34
|
+
|
|
35
|
+
async def set_dnd_timer(self, dnd_timer: DnDTimer) -> None:
|
|
36
|
+
"""Set the Do Not Disturb (DND) timer settings of the device."""
|
|
37
|
+
await self._rpc_channel.send_command(RoborockCommand.SET_DND_TIMER, params=dnd_timer.as_dict())
|
|
38
|
+
|
|
39
|
+
async def clear_dnd_timer(self) -> None:
|
|
40
|
+
"""Clear the Do Not Disturb (DND) timer settings of the device."""
|
|
41
|
+
await self._rpc_channel.send_command(RoborockCommand.CLOSE_DND_TIMER)
|
|
@@ -12,20 +12,20 @@ from roborock.containers import (
|
|
|
12
12
|
S7MaxVStatus,
|
|
13
13
|
Status,
|
|
14
14
|
)
|
|
15
|
+
from roborock.devices.v1_rpc_channel import V1RpcChannel
|
|
15
16
|
from roborock.roborock_typing import RoborockCommand
|
|
16
17
|
|
|
17
|
-
from ..v1_rpc_channel import V1RpcChannel
|
|
18
18
|
from .trait import Trait
|
|
19
19
|
|
|
20
20
|
_LOGGER = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
22
|
__all__ = [
|
|
23
|
-
"
|
|
23
|
+
"StatusTrait",
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class StatusTrait(Trait):
|
|
28
|
-
"""
|
|
28
|
+
"""Trait for managing the status of Roborock devices."""
|
|
29
29
|
|
|
30
30
|
name = "status"
|
|
31
31
|
|
|
@@ -132,8 +132,10 @@ class PayloadEncodedV1RpcChannel(BaseV1RpcChannel):
|
|
|
132
132
|
params: ParamsType = None,
|
|
133
133
|
) -> Any:
|
|
134
134
|
"""Send a command and return a parsed response RoborockBase type."""
|
|
135
|
-
_LOGGER.debug("Sending command (%s): %s, params=%s", self._name, method, params)
|
|
136
135
|
request_message = RequestMessage(method, params=params)
|
|
136
|
+
_LOGGER.debug(
|
|
137
|
+
"Sending command (%s, request_id=%s): %s, params=%s", self._name, request_message.request_id, method, params
|
|
138
|
+
)
|
|
137
139
|
message = self._payload_encoder(request_message)
|
|
138
140
|
|
|
139
141
|
future: asyncio.Future[dict[str, Any]] = asyncio.Future()
|
|
@@ -141,8 +143,10 @@ class PayloadEncodedV1RpcChannel(BaseV1RpcChannel):
|
|
|
141
143
|
def find_response(response_message: RoborockMessage) -> None:
|
|
142
144
|
try:
|
|
143
145
|
decoded = decode_rpc_response(response_message)
|
|
144
|
-
except RoborockException:
|
|
146
|
+
except RoborockException as ex:
|
|
147
|
+
_LOGGER.debug("Exception while decoding message (%s): %s", response_message, ex)
|
|
145
148
|
return
|
|
149
|
+
_LOGGER.debug("Received response (request_id=%s): %s", self._name, decoded.request_id)
|
|
146
150
|
if decoded.request_id == request_message.request_id:
|
|
147
151
|
future.set_result(decoded.data)
|
|
148
152
|
|
|
@@ -109,7 +109,7 @@ class ResponseMessage:
|
|
|
109
109
|
def decode_rpc_response(message: RoborockMessage) -> ResponseMessage:
|
|
110
110
|
"""Decode a V1 RPC_RESPONSE message."""
|
|
111
111
|
if not message.payload:
|
|
112
|
-
|
|
112
|
+
return ResponseMessage(request_id=message.seq, data={})
|
|
113
113
|
try:
|
|
114
114
|
payload = json.loads(message.payload.decode())
|
|
115
115
|
except (json.JSONDecodeError, TypeError) as e:
|
|
@@ -141,6 +141,8 @@ def decode_rpc_response(message: RoborockMessage) -> ResponseMessage:
|
|
|
141
141
|
_LOGGER.debug("Decoded V1 message result: %s", result)
|
|
142
142
|
if isinstance(result, list) and result:
|
|
143
143
|
result = result[0]
|
|
144
|
+
if isinstance(result, str) and result == "ok":
|
|
145
|
+
result = {}
|
|
144
146
|
if not isinstance(result, dict):
|
|
145
147
|
raise RoborockException(f"Invalid V1 message format: 'result' should be a dictionary for {message.payload!r}")
|
|
146
148
|
return ResponseMessage(request_id=request_id, data=result)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/roborock_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.40.1 → python_roborock-2.41.0}/roborock/version_a01_apis/roborock_client_a01.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|