python-roborock 2.9.5__tar.gz → 2.9.7__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.9.5 → python_roborock-2.9.7}/PKG-INFO +1 -1
- {python_roborock-2.9.5 → python_roborock-2.9.7}/pyproject.toml +1 -1
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/api.py +4 -11
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/cloud_api.py +7 -5
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/local_api.py +11 -8
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/util.py +3 -3
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_client_v1.py +3 -7
- {python_roborock-2.9.5 → python_roborock-2.9.7}/LICENSE +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/README.md +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/__init__.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/cli.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/code_mappings.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/command_cache.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/const.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/containers.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/exceptions.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/protocol.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/py.typed +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/roborock_future.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/roborock_message.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/roborock_typing.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/__init__.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_a01_apis/__init__.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
- {python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/web_api.py +0 -0
|
@@ -21,7 +21,7 @@ from .roborock_future import RoborockFuture
|
|
|
21
21
|
from .roborock_message import (
|
|
22
22
|
RoborockMessage,
|
|
23
23
|
)
|
|
24
|
-
from .util import get_next_int
|
|
24
|
+
from .util import get_next_int
|
|
25
25
|
|
|
26
26
|
_LOGGER = logging.getLogger(__name__)
|
|
27
27
|
KEEPALIVE = 60
|
|
@@ -35,7 +35,6 @@ class RoborockClient(ABC):
|
|
|
35
35
|
|
|
36
36
|
def __init__(self, device_info: DeviceData) -> None:
|
|
37
37
|
"""Initialize RoborockClient."""
|
|
38
|
-
self.event_loop = get_running_loop_or_create_one()
|
|
39
38
|
self.device_info = device_info
|
|
40
39
|
self._nonce = secrets.token_bytes(16)
|
|
41
40
|
self._waiting_queue: dict[int, RoborockFuture] = {}
|
|
@@ -47,12 +46,6 @@ class RoborockClient(ABC):
|
|
|
47
46
|
}
|
|
48
47
|
self.is_available: bool = True
|
|
49
48
|
|
|
50
|
-
def __del__(self) -> None:
|
|
51
|
-
self.release()
|
|
52
|
-
|
|
53
|
-
def release(self) -> None:
|
|
54
|
-
self.sync_disconnect()
|
|
55
|
-
|
|
56
49
|
async def async_release(self) -> None:
|
|
57
50
|
await self.async_disconnect()
|
|
58
51
|
|
|
@@ -65,12 +58,12 @@ class RoborockClient(ABC):
|
|
|
65
58
|
"""Connect to the Roborock device."""
|
|
66
59
|
|
|
67
60
|
@abstractmethod
|
|
68
|
-
def
|
|
61
|
+
async def async_disconnect(self) -> Any:
|
|
69
62
|
"""Disconnect from the Roborock device."""
|
|
70
63
|
|
|
71
64
|
@abstractmethod
|
|
72
|
-
|
|
73
|
-
"""
|
|
65
|
+
def is_connected(self) -> bool:
|
|
66
|
+
"""Return True if the client is connected to the device."""
|
|
74
67
|
|
|
75
68
|
@abstractmethod
|
|
76
69
|
def on_message_received(self, messages: list[RoborockMessage]) -> None:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import logging
|
|
4
5
|
import threading
|
|
5
6
|
from abc import ABC
|
|
@@ -121,7 +122,7 @@ class RoborockMqttClient(RoborockClient, ABC):
|
|
|
121
122
|
"""Check if the mqtt client is connected."""
|
|
122
123
|
return self._mqtt_client.is_connected()
|
|
123
124
|
|
|
124
|
-
def
|
|
125
|
+
def _sync_disconnect(self) -> Any:
|
|
125
126
|
if not self.is_connected():
|
|
126
127
|
return None
|
|
127
128
|
|
|
@@ -139,7 +140,7 @@ class RoborockMqttClient(RoborockClient, ABC):
|
|
|
139
140
|
|
|
140
141
|
return disconnected_future
|
|
141
142
|
|
|
142
|
-
def
|
|
143
|
+
def _sync_connect(self) -> Any:
|
|
143
144
|
if self.is_connected():
|
|
144
145
|
self._mqtt_client.maybe_restart_loop()
|
|
145
146
|
return None
|
|
@@ -155,14 +156,15 @@ class RoborockMqttClient(RoborockClient, ABC):
|
|
|
155
156
|
|
|
156
157
|
async def async_disconnect(self) -> None:
|
|
157
158
|
async with self._mutex:
|
|
158
|
-
if disconnected_future := self.
|
|
159
|
+
if disconnected_future := self._sync_disconnect():
|
|
159
160
|
# There are no errors set on this future
|
|
160
161
|
await disconnected_future
|
|
161
|
-
|
|
162
|
+
loop = asyncio.get_running_loop()
|
|
163
|
+
await loop.run_in_executor(None, self._mqtt_client.loop_stop)
|
|
162
164
|
|
|
163
165
|
async def async_connect(self) -> None:
|
|
164
166
|
async with self._mutex:
|
|
165
|
-
if connected_future := self.
|
|
167
|
+
if connected_future := self._sync_connect():
|
|
166
168
|
try:
|
|
167
169
|
await connected_future
|
|
168
170
|
except VacuumError as err:
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
from abc import ABC
|
|
6
|
-
from asyncio import Lock, TimerHandle, Transport
|
|
6
|
+
from asyncio import Lock, TimerHandle, Transport, get_running_loop
|
|
7
7
|
from collections.abc import Callable
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
|
|
@@ -61,7 +61,7 @@ class RoborockLocalClient(RoborockClient, ABC):
|
|
|
61
61
|
|
|
62
62
|
def _connection_lost(self, exc: Exception | None):
|
|
63
63
|
"""Called when the transport connection is lost."""
|
|
64
|
-
self.
|
|
64
|
+
self._sync_disconnect()
|
|
65
65
|
self.on_connection_lost(exc)
|
|
66
66
|
|
|
67
67
|
def is_connected(self):
|
|
@@ -72,17 +72,19 @@ class RoborockLocalClient(RoborockClient, ABC):
|
|
|
72
72
|
await self.ping()
|
|
73
73
|
except RoborockException:
|
|
74
74
|
pass
|
|
75
|
-
|
|
75
|
+
loop = asyncio.get_running_loop()
|
|
76
|
+
self.keep_alive_task = loop.call_later(10, lambda: asyncio.create_task(self.keep_alive_func()))
|
|
76
77
|
|
|
77
78
|
async def async_connect(self) -> None:
|
|
78
79
|
should_ping = False
|
|
79
80
|
async with self._mutex:
|
|
80
81
|
try:
|
|
81
82
|
if not self.is_connected():
|
|
82
|
-
self.
|
|
83
|
+
self._sync_disconnect()
|
|
83
84
|
async with async_timeout.timeout(self.queue_timeout):
|
|
84
85
|
self._logger.debug(f"Connecting to {self.host}")
|
|
85
|
-
|
|
86
|
+
loop = get_running_loop()
|
|
87
|
+
self.transport, _ = await loop.create_connection( # type: ignore
|
|
86
88
|
lambda: self._local_protocol, self.host, 58867
|
|
87
89
|
)
|
|
88
90
|
self._logger.info(f"Connected to {self.host}")
|
|
@@ -93,8 +95,9 @@ class RoborockLocalClient(RoborockClient, ABC):
|
|
|
93
95
|
await self.hello()
|
|
94
96
|
await self.keep_alive_func()
|
|
95
97
|
|
|
96
|
-
def
|
|
97
|
-
|
|
98
|
+
def _sync_disconnect(self) -> None:
|
|
99
|
+
loop = asyncio.get_running_loop()
|
|
100
|
+
if self.transport and loop.is_running():
|
|
98
101
|
self._logger.debug(f"Disconnecting from {self.host}")
|
|
99
102
|
self.transport.close()
|
|
100
103
|
if self.keep_alive_task:
|
|
@@ -102,7 +105,7 @@ class RoborockLocalClient(RoborockClient, ABC):
|
|
|
102
105
|
|
|
103
106
|
async def async_disconnect(self) -> None:
|
|
104
107
|
async with self._mutex:
|
|
105
|
-
self.
|
|
108
|
+
self._sync_disconnect()
|
|
106
109
|
|
|
107
110
|
async def hello(self):
|
|
108
111
|
request_id = 1
|
|
@@ -74,8 +74,7 @@ def run_sync():
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
class RepeatableTask:
|
|
77
|
-
def __init__(self,
|
|
78
|
-
self.loop = loop
|
|
77
|
+
def __init__(self, callback: Callable[[], Coroutine], interval: int):
|
|
79
78
|
self.callback = callback
|
|
80
79
|
self.interval = interval
|
|
81
80
|
self._task: TimerHandle | None = None
|
|
@@ -86,7 +85,8 @@ class RepeatableTask:
|
|
|
86
85
|
response = await self.callback()
|
|
87
86
|
except RoborockException:
|
|
88
87
|
pass
|
|
89
|
-
|
|
88
|
+
loop = asyncio.get_running_loop()
|
|
89
|
+
self._task = loop.call_later(self.interval, self._run_task_soon)
|
|
90
90
|
return response
|
|
91
91
|
|
|
92
92
|
def _run_task_soon(self):
|
{python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_client_v1.py
RENAMED
|
@@ -82,11 +82,11 @@ _SendCommandT = Callable[[RoborockCommand | str, list | dict | int | None], Any]
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
class AttributeCache:
|
|
85
|
-
def __init__(self, attribute: RoborockAttribute,
|
|
85
|
+
def __init__(self, attribute: RoborockAttribute, send_command: _SendCommandT):
|
|
86
86
|
self.attribute = attribute
|
|
87
87
|
self._send_command = send_command
|
|
88
88
|
self.attribute = attribute
|
|
89
|
-
self.task = RepeatableTask(
|
|
89
|
+
self.task = RepeatableTask(self._async_value, EVICT_TIME)
|
|
90
90
|
self._value: Any = None
|
|
91
91
|
self._mutex = asyncio.Lock()
|
|
92
92
|
self.unsupported: bool = False
|
|
@@ -156,7 +156,7 @@ class RoborockClientV1(RoborockClient, ABC):
|
|
|
156
156
|
super().__init__(device_info)
|
|
157
157
|
self._status_type: type[Status] = ModelStatus.get(device_info.model, S7MaxVStatus)
|
|
158
158
|
self.cache: dict[CacheableAttribute, AttributeCache] = {
|
|
159
|
-
cacheable_attribute: AttributeCache(attr, self.
|
|
159
|
+
cacheable_attribute: AttributeCache(attr, self._send_command)
|
|
160
160
|
for cacheable_attribute, attr in get_cache_map().items()
|
|
161
161
|
}
|
|
162
162
|
if device_info.device.duid not in self._listeners:
|
|
@@ -164,10 +164,6 @@ class RoborockClientV1(RoborockClient, ABC):
|
|
|
164
164
|
self.listener_model = self._listeners[device_info.device.duid]
|
|
165
165
|
self._endpoint = endpoint
|
|
166
166
|
|
|
167
|
-
def release(self):
|
|
168
|
-
super().release()
|
|
169
|
-
[item.stop() for item in self.cache.values()]
|
|
170
|
-
|
|
171
167
|
async def async_release(self) -> None:
|
|
172
168
|
await super().async_release()
|
|
173
169
|
[item.stop() for item in self.cache.values()]
|
|
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.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_local_client_v1.py
RENAMED
|
File without changes
|
{python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_1_apis/roborock_mqtt_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.9.5 → python_roborock-2.9.7}/roborock/version_a01_apis/roborock_client_a01.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|