python-roborock 2.31.0__tar.gz → 2.33.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.31.0 → python_roborock-2.33.0}/PKG-INFO +1 -1
- {python_roborock-2.31.0 → python_roborock-2.33.0}/pyproject.toml +2 -2
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/cli.py +15 -8
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/containers.py +7 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/__init__.py +1 -0
- python_roborock-2.33.0/roborock/devices/cache.py +57 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/device_manager.py +19 -6
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/v1_channel.py +20 -7
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/mqtt/roborock_session.py +3 -3
- {python_roborock-2.31.0 → python_roborock-2.33.0}/LICENSE +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/README.md +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/__init__.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/api.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/cloud_api.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/code_mappings.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/command_cache.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/const.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/device_features.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/README.md +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/a01_channel.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/channel.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/device.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/local_channel.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/mqtt_channel.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/traits/dyad.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/traits/status.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/traits/trait.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/traits/zeo.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/devices/v1_rpc_channel.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/exceptions.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/local_api.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/protocol.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/py.typed +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/roborock_future.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/roborock_message.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/util.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/__init__.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/roborock_client_v1.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_a01_apis/__init__.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
- {python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/web_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.33.0"
|
|
4
4
|
description = "A package to control Roborock vacuums."
|
|
5
5
|
authors = ["humbertogontijo <humbertogontijo@users.noreply.github.com>"]
|
|
6
6
|
license = "GPL-3.0-only"
|
|
@@ -39,7 +39,7 @@ requires = ["poetry-core==1.8.0"]
|
|
|
39
39
|
build-backend = "poetry.core.masonry.api"
|
|
40
40
|
|
|
41
41
|
[tool.poetry.group.dev.dependencies]
|
|
42
|
-
pytest-asyncio = "
|
|
42
|
+
pytest-asyncio = ">=1.1.0"
|
|
43
43
|
pytest = "*"
|
|
44
44
|
pre-commit = ">=3.5,<5.0"
|
|
45
45
|
mypy = "*"
|
|
@@ -12,6 +12,7 @@ from pyshark.packet.packet import Packet # type: ignore
|
|
|
12
12
|
|
|
13
13
|
from roborock import RoborockException
|
|
14
14
|
from roborock.containers import DeviceData, HomeData, HomeDataProduct, LoginData, NetworkInfo, RoborockBase, UserData
|
|
15
|
+
from roborock.devices.cache import Cache, CacheData
|
|
15
16
|
from roborock.devices.device_manager import create_device_manager, create_home_data_api
|
|
16
17
|
from roborock.protocol import MessageParser
|
|
17
18
|
from roborock.util import run_sync
|
|
@@ -39,7 +40,7 @@ class ConnectionCache(RoborockBase):
|
|
|
39
40
|
network_info: dict[str, NetworkInfo] | None = None
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
class RoborockContext:
|
|
43
|
+
class RoborockContext(Cache):
|
|
43
44
|
roborock_file = Path("~/.roborock").expanduser()
|
|
44
45
|
_cache_data: ConnectionCache | None = None
|
|
45
46
|
|
|
@@ -68,6 +69,18 @@ class RoborockContext:
|
|
|
68
69
|
self.validate()
|
|
69
70
|
return self._cache_data
|
|
70
71
|
|
|
72
|
+
async def get(self) -> CacheData:
|
|
73
|
+
"""Get cached value."""
|
|
74
|
+
connection_cache = self.cache_data()
|
|
75
|
+
return CacheData(home_data=connection_cache.home_data, network_info=connection_cache.network_info or {})
|
|
76
|
+
|
|
77
|
+
async def set(self, value: CacheData) -> None:
|
|
78
|
+
"""Set value in the cache."""
|
|
79
|
+
connection_cache = self.cache_data()
|
|
80
|
+
connection_cache.home_data = value.home_data
|
|
81
|
+
connection_cache.network_info = value.network_info
|
|
82
|
+
self.update(connection_cache)
|
|
83
|
+
|
|
71
84
|
|
|
72
85
|
@click.option("-d", "--debug", default=False, count=True)
|
|
73
86
|
@click.version_option(package_name="python-roborock")
|
|
@@ -119,14 +132,8 @@ async def session(ctx, duration: int):
|
|
|
119
132
|
|
|
120
133
|
home_data_api = create_home_data_api(cache_data.email, cache_data.user_data)
|
|
121
134
|
|
|
122
|
-
async def home_data_cache() -> HomeData:
|
|
123
|
-
if cache_data.home_data is None:
|
|
124
|
-
cache_data.home_data = await home_data_api()
|
|
125
|
-
context.update(cache_data)
|
|
126
|
-
return cache_data.home_data
|
|
127
|
-
|
|
128
135
|
# Create device manager
|
|
129
|
-
device_manager = await create_device_manager(cache_data.user_data,
|
|
136
|
+
device_manager = await create_device_manager(cache_data.user_data, home_data_api, context)
|
|
130
137
|
|
|
131
138
|
devices = await device_manager.get_devices()
|
|
132
139
|
click.echo(f"Discovered devices: {', '.join([device.name for device in devices])}")
|
|
@@ -425,6 +425,13 @@ class Status(RoborockBase):
|
|
|
425
425
|
raise RoborockException("Attempted to get mop_mode before status has been updated.")
|
|
426
426
|
return self.mop_mode.as_dict().get(mop_mode)
|
|
427
427
|
|
|
428
|
+
@property
|
|
429
|
+
def current_map(self) -> int | None:
|
|
430
|
+
"""Returns the current map ID if the map is present."""
|
|
431
|
+
if self.map_status is not None:
|
|
432
|
+
return (self.map_status - 3) // 4
|
|
433
|
+
return None
|
|
434
|
+
|
|
428
435
|
|
|
429
436
|
@dataclass
|
|
430
437
|
class S4MaxStatus(Status):
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""This module provides caching functionality for the Roborock device management system.
|
|
2
|
+
|
|
3
|
+
This module defines a cache interface that you may use to cache device
|
|
4
|
+
information to avoid unnecessary API calls. Callers may implement
|
|
5
|
+
this interface to provide their own caching mechanism.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Protocol
|
|
10
|
+
|
|
11
|
+
from roborock.containers import HomeData, NetworkInfo
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class CacheData:
|
|
16
|
+
"""Data structure for caching device information."""
|
|
17
|
+
|
|
18
|
+
home_data: HomeData | None = None
|
|
19
|
+
"""Home data containing device and product information."""
|
|
20
|
+
|
|
21
|
+
network_info: dict[str, NetworkInfo] = field(default_factory=dict)
|
|
22
|
+
"""Network information indexed by device DUID."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Cache(Protocol):
|
|
26
|
+
"""Protocol for a cache that can store and retrieve values."""
|
|
27
|
+
|
|
28
|
+
async def get(self) -> CacheData:
|
|
29
|
+
"""Get cached value."""
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
async def set(self, value: CacheData) -> None:
|
|
33
|
+
"""Set value in the cache."""
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class InMemoryCache(Cache):
|
|
38
|
+
"""In-memory cache implementation."""
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
self._data = CacheData()
|
|
42
|
+
|
|
43
|
+
async def get(self) -> CacheData:
|
|
44
|
+
return self._data
|
|
45
|
+
|
|
46
|
+
async def set(self, value: CacheData) -> None:
|
|
47
|
+
self._data = value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class NoCache(Cache):
|
|
51
|
+
"""No-op cache implementation."""
|
|
52
|
+
|
|
53
|
+
async def get(self) -> CacheData:
|
|
54
|
+
return CacheData()
|
|
55
|
+
|
|
56
|
+
async def set(self, value: CacheData) -> None:
|
|
57
|
+
pass
|
|
@@ -18,6 +18,7 @@ from roborock.mqtt.session import MqttSession
|
|
|
18
18
|
from roborock.protocol import create_mqtt_params
|
|
19
19
|
from roborock.web_api import RoborockApiClient
|
|
20
20
|
|
|
21
|
+
from .cache import Cache, NoCache
|
|
21
22
|
from .channel import Channel
|
|
22
23
|
from .mqtt_channel import create_mqtt_channel
|
|
23
24
|
from .traits.dyad import DyadApi
|
|
@@ -32,8 +33,6 @@ __all__ = [
|
|
|
32
33
|
"create_device_manager",
|
|
33
34
|
"create_home_data_api",
|
|
34
35
|
"DeviceManager",
|
|
35
|
-
"HomeDataApi",
|
|
36
|
-
"DeviceCreator",
|
|
37
36
|
]
|
|
38
37
|
|
|
39
38
|
|
|
@@ -57,19 +56,27 @@ class DeviceManager:
|
|
|
57
56
|
home_data_api: HomeDataApi,
|
|
58
57
|
device_creator: DeviceCreator,
|
|
59
58
|
mqtt_session: MqttSession,
|
|
59
|
+
cache: Cache,
|
|
60
60
|
) -> None:
|
|
61
61
|
"""Initialize the DeviceManager with user data and optional cache storage.
|
|
62
62
|
|
|
63
63
|
This takes ownership of the MQTT session and will close it when the manager is closed.
|
|
64
64
|
"""
|
|
65
65
|
self._home_data_api = home_data_api
|
|
66
|
+
self._cache = cache
|
|
66
67
|
self._device_creator = device_creator
|
|
67
68
|
self._devices: dict[str, RoborockDevice] = {}
|
|
68
69
|
self._mqtt_session = mqtt_session
|
|
69
70
|
|
|
70
71
|
async def discover_devices(self) -> list[RoborockDevice]:
|
|
71
72
|
"""Discover all devices for the logged-in user."""
|
|
72
|
-
|
|
73
|
+
cache_data = await self._cache.get()
|
|
74
|
+
if not cache_data.home_data:
|
|
75
|
+
_LOGGER.debug("No cached home data found, fetching from API")
|
|
76
|
+
cache_data.home_data = await self._home_data_api()
|
|
77
|
+
await self._cache.set(cache_data)
|
|
78
|
+
home_data = cache_data.home_data
|
|
79
|
+
|
|
73
80
|
device_products = home_data.device_products
|
|
74
81
|
_LOGGER.debug("Discovered %d devices %s", len(device_products), home_data)
|
|
75
82
|
|
|
@@ -118,13 +125,19 @@ def create_home_data_api(email: str, user_data: UserData) -> HomeDataApi:
|
|
|
118
125
|
return home_data_api
|
|
119
126
|
|
|
120
127
|
|
|
121
|
-
async def create_device_manager(
|
|
128
|
+
async def create_device_manager(
|
|
129
|
+
user_data: UserData,
|
|
130
|
+
home_data_api: HomeDataApi,
|
|
131
|
+
cache: Cache | None = None,
|
|
132
|
+
) -> DeviceManager:
|
|
122
133
|
"""Convenience function to create and initialize a DeviceManager.
|
|
123
134
|
|
|
124
135
|
The Home Data is fetched using the provided home_data_api callable which
|
|
125
136
|
is exposed this way to allow for swapping out other implementations to
|
|
126
137
|
include caching or other optimizations.
|
|
127
138
|
"""
|
|
139
|
+
if cache is None:
|
|
140
|
+
cache = NoCache()
|
|
128
141
|
|
|
129
142
|
mqtt_params = create_mqtt_params(user_data.rriot)
|
|
130
143
|
mqtt_session = await create_mqtt_session(mqtt_params)
|
|
@@ -135,7 +148,7 @@ async def create_device_manager(user_data: UserData, home_data_api: HomeDataApi)
|
|
|
135
148
|
# TODO: Define a registration mechanism/factory for v1 traits
|
|
136
149
|
match device.pv:
|
|
137
150
|
case DeviceVersion.V1:
|
|
138
|
-
channel = create_v1_channel(user_data, mqtt_params, mqtt_session, device)
|
|
151
|
+
channel = create_v1_channel(user_data, mqtt_params, mqtt_session, device, cache)
|
|
139
152
|
traits.append(StatusTrait(product, channel.rpc_channel))
|
|
140
153
|
case DeviceVersion.A01:
|
|
141
154
|
mqtt_channel = create_mqtt_channel(user_data, mqtt_params, mqtt_session, device)
|
|
@@ -150,6 +163,6 @@ async def create_device_manager(user_data: UserData, home_data_api: HomeDataApi)
|
|
|
150
163
|
raise NotImplementedError(f"Device {device.name} has unsupported version {device.pv}")
|
|
151
164
|
return RoborockDevice(device, channel, traits)
|
|
152
165
|
|
|
153
|
-
manager = DeviceManager(home_data_api, device_creator, mqtt_session=mqtt_session)
|
|
166
|
+
manager = DeviceManager(home_data_api, device_creator, mqtt_session=mqtt_session, cache=cache)
|
|
154
167
|
await manager.discover_devices()
|
|
155
168
|
return manager
|
|
@@ -18,6 +18,7 @@ from roborock.protocols.v1_protocol import (
|
|
|
18
18
|
from roborock.roborock_message import RoborockMessage
|
|
19
19
|
from roborock.roborock_typing import RoborockCommand
|
|
20
20
|
|
|
21
|
+
from .cache import Cache
|
|
21
22
|
from .channel import Channel
|
|
22
23
|
from .local_channel import LocalChannel, LocalSession, create_local_session
|
|
23
24
|
from .mqtt_channel import MqttChannel
|
|
@@ -46,6 +47,7 @@ class V1Channel(Channel):
|
|
|
46
47
|
security_data: SecurityData,
|
|
47
48
|
mqtt_channel: MqttChannel,
|
|
48
49
|
local_session: LocalSession,
|
|
50
|
+
cache: Cache,
|
|
49
51
|
) -> None:
|
|
50
52
|
"""Initialize the V1Channel.
|
|
51
53
|
|
|
@@ -62,7 +64,7 @@ class V1Channel(Channel):
|
|
|
62
64
|
self._mqtt_unsub: Callable[[], None] | None = None
|
|
63
65
|
self._local_unsub: Callable[[], None] | None = None
|
|
64
66
|
self._callback: Callable[[RoborockMessage], None] | None = None
|
|
65
|
-
self.
|
|
67
|
+
self._cache = cache
|
|
66
68
|
|
|
67
69
|
@property
|
|
68
70
|
def is_connected(self) -> bool:
|
|
@@ -131,19 +133,26 @@ class V1Channel(Channel):
|
|
|
131
133
|
|
|
132
134
|
This is a cloud only command used to get the local device's IP address.
|
|
133
135
|
"""
|
|
136
|
+
cache_data = await self._cache.get()
|
|
137
|
+
if cache_data.network_info and (network_info := cache_data.network_info.get(self._device_uid)):
|
|
138
|
+
_LOGGER.debug("Using cached network info for device %s", self._device_uid)
|
|
139
|
+
return network_info
|
|
134
140
|
try:
|
|
135
|
-
|
|
141
|
+
network_info = await self._mqtt_rpc_channel.send_command(
|
|
136
142
|
RoborockCommand.GET_NETWORK_INFO, response_type=NetworkInfo
|
|
137
143
|
)
|
|
138
144
|
except RoborockException as e:
|
|
139
145
|
raise RoborockException(f"Network info failed for device {self._device_uid}") from e
|
|
146
|
+
_LOGGER.debug("Network info for device %s: %s", self._device_uid, network_info)
|
|
147
|
+
cache_data.network_info[self._device_uid] = network_info
|
|
148
|
+
await self._cache.set(cache_data)
|
|
149
|
+
return network_info
|
|
140
150
|
|
|
141
151
|
async def _local_connect(self) -> Callable[[], None]:
|
|
142
152
|
"""Set up local connection if possible."""
|
|
143
153
|
_LOGGER.debug("Attempting to connect to local channel for device %s", self._device_uid)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
host = self._networking_info.ip
|
|
154
|
+
networking_info = await self._get_networking_info()
|
|
155
|
+
host = networking_info.ip
|
|
147
156
|
_LOGGER.debug("Connecting to local channel at %s", host)
|
|
148
157
|
self._local_channel = self._local_session(host)
|
|
149
158
|
try:
|
|
@@ -168,10 +177,14 @@ class V1Channel(Channel):
|
|
|
168
177
|
|
|
169
178
|
|
|
170
179
|
def create_v1_channel(
|
|
171
|
-
user_data: UserData,
|
|
180
|
+
user_data: UserData,
|
|
181
|
+
mqtt_params: MqttParams,
|
|
182
|
+
mqtt_session: MqttSession,
|
|
183
|
+
device: HomeDataDevice,
|
|
184
|
+
cache: Cache,
|
|
172
185
|
) -> V1Channel:
|
|
173
186
|
"""Create a V1Channel for the given device."""
|
|
174
187
|
security_data = create_security_data(user_data.rriot)
|
|
175
188
|
mqtt_channel = MqttChannel(mqtt_session, device.duid, device.local_key, user_data.rriot, mqtt_params)
|
|
176
189
|
local_session = create_local_session(device.local_key)
|
|
177
|
-
return V1Channel(device.duid, security_data, mqtt_channel, local_session=local_session)
|
|
190
|
+
return V1Channel(device.duid, security_data, mqtt_channel, local_session=local_session, cache=cache)
|
|
@@ -125,14 +125,14 @@ class RoborockMqttSession(MqttSession):
|
|
|
125
125
|
except Exception as err:
|
|
126
126
|
# This error is thrown when the MQTT loop is cancelled
|
|
127
127
|
# and the generator is not stopped.
|
|
128
|
-
if "generator didn't stop" in str(err):
|
|
128
|
+
if "generator didn't stop" in str(err) or "generator didn't yield" in str(err):
|
|
129
129
|
_LOGGER.debug("MQTT loop was cancelled")
|
|
130
130
|
return
|
|
131
131
|
if start_future:
|
|
132
132
|
_LOGGER.error("Uncaught error starting MQTT session: %s", err)
|
|
133
133
|
start_future.set_exception(err)
|
|
134
134
|
return
|
|
135
|
-
_LOGGER.
|
|
135
|
+
_LOGGER.exception("Uncaught error during MQTT session: %s", err)
|
|
136
136
|
|
|
137
137
|
self._healthy = False
|
|
138
138
|
_LOGGER.info("MQTT session disconnected, retrying in %s seconds", self._backoff.total_seconds())
|
|
@@ -180,7 +180,7 @@ class RoborockMqttSession(MqttSession):
|
|
|
180
180
|
except asyncio.CancelledError:
|
|
181
181
|
raise
|
|
182
182
|
except Exception as e:
|
|
183
|
-
_LOGGER.
|
|
183
|
+
_LOGGER.exception("Uncaught exception in subscriber callback: %s", e)
|
|
184
184
|
|
|
185
185
|
async def subscribe(self, topic: str, callback: Callable[[bytes], None]) -> Callable[[], None]:
|
|
186
186
|
"""Subscribe to messages on the specified topic and invoke the callback for new messages.
|
|
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.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/roborock_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.31.0 → python_roborock-2.33.0}/roborock/version_a01_apis/roborock_client_a01.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|