python-roborock 0.4.7__tar.gz → 0.4.9__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-0.4.7 → python_roborock-0.4.9}/PKG-INFO +1 -1
- {python_roborock-0.4.7 → python_roborock-0.4.9}/pyproject.toml +1 -1
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/api.py +2 -2
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/cloud_api.py +5 -5
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/local_api.py +3 -3
- python_roborock-0.4.9/roborock/offline/offline.py +26 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/typing.py +9 -5
- python_roborock-0.4.7/roborock/offline/offline.py +0 -35
- {python_roborock-0.4.7 → python_roborock-0.4.9}/LICENSE +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/README.md +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/__init__.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/cli.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/code_mappings.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/containers.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/exceptions.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/roborock_queue.py +0 -0
- {python_roborock-0.4.7 → python_roborock-0.4.9}/roborock/util.py +0 -0
|
@@ -147,7 +147,7 @@ class RoborockClient:
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
def _encode_msg(self, device_id, request_id, protocol, timestamp, payload, prefix=None) -> bytes:
|
|
150
|
-
local_key = self.devices_info[device_id].
|
|
150
|
+
local_key = self.devices_info[device_id].local_key
|
|
151
151
|
aes_key = md5bin(encode_timestamp(timestamp) + local_key + self._salt)
|
|
152
152
|
cipher = AES.new(aes_key, AES.MODE_ECB)
|
|
153
153
|
encrypted = cipher.encrypt(pad(payload, AES.block_size))
|
|
@@ -173,7 +173,7 @@ class RoborockClient:
|
|
|
173
173
|
|
|
174
174
|
async def on_message(self, device_id, msg) -> bool:
|
|
175
175
|
try:
|
|
176
|
-
data = self._decode_msg(msg, self.devices_info[device_id].
|
|
176
|
+
data = self._decode_msg(msg, self.devices_info[device_id].local_key)
|
|
177
177
|
protocol = data.get("protocol")
|
|
178
178
|
if protocol == 102 or protocol == 4:
|
|
179
179
|
payload = json.loads(data.get("payload").decode())
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
import secrets
|
|
6
6
|
import threading
|
|
7
7
|
from asyncio import Lock
|
|
8
|
-
from typing import Any
|
|
8
|
+
from typing import Any
|
|
9
9
|
from urllib.parse import urlparse
|
|
10
10
|
|
|
11
11
|
import paho.mqtt.client as mqtt
|
|
@@ -22,7 +22,7 @@ from .containers import (
|
|
|
22
22
|
)
|
|
23
23
|
from .roborock_queue import RoborockQueue
|
|
24
24
|
from .typing import (
|
|
25
|
-
RoborockCommand, RoborockDeviceProp,
|
|
25
|
+
RoborockCommand, RoborockDeviceProp, RoborockDeviceInfo,
|
|
26
26
|
)
|
|
27
27
|
from .util import run_in_executor
|
|
28
28
|
|
|
@@ -34,10 +34,10 @@ MQTT_KEEPALIVE = 60
|
|
|
34
34
|
class RoborockMqttClient(RoborockClient, mqtt.Client):
|
|
35
35
|
_thread: threading.Thread
|
|
36
36
|
|
|
37
|
-
def __init__(self, user_data: UserData,
|
|
37
|
+
def __init__(self, user_data: UserData, devices_info: dict[str, RoborockDeviceInfo]) -> None:
|
|
38
38
|
rriot = user_data.rriot
|
|
39
39
|
endpoint = base64.b64encode(md5bin(rriot.endpoint)[8:14]).decode()
|
|
40
|
-
RoborockClient.__init__(self, endpoint,
|
|
40
|
+
RoborockClient.__init__(self, endpoint, devices_info)
|
|
41
41
|
mqtt.Client.__init__(self, protocol=mqtt.MQTTv5)
|
|
42
42
|
self._mqtt_user = rriot.user
|
|
43
43
|
self._hashed_user = md5hex(self._mqtt_user + ":" + rriot.endpoint)[2:10]
|
|
@@ -192,7 +192,7 @@ class RoborockMqttClient(RoborockClient, mqtt.Client):
|
|
|
192
192
|
_LOGGER.debug(f"id={request_id} Requesting method {method} with {params}")
|
|
193
193
|
request_protocol = 101
|
|
194
194
|
response_protocol = 301 if method in SPECIAL_COMMANDS else 102
|
|
195
|
-
msg = super()._encode_msg(device_id, request_protocol, timestamp, payload)
|
|
195
|
+
msg = super()._encode_msg(device_id, request_id, request_protocol, timestamp, payload)
|
|
196
196
|
self._send_msg_raw(device_id, msg)
|
|
197
197
|
(response, err) = await self._async_response(request_id, response_protocol)
|
|
198
198
|
if err:
|
|
@@ -10,7 +10,7 @@ import async_timeout
|
|
|
10
10
|
|
|
11
11
|
from roborock.api import RoborockClient, SPECIAL_COMMANDS
|
|
12
12
|
from roborock.exceptions import RoborockTimeout, CommandVacuumError
|
|
13
|
-
from roborock.typing import RoborockCommand,
|
|
13
|
+
from roborock.typing import RoborockCommand, RoborockLocalDeviceInfo
|
|
14
14
|
from roborock.util import get_running_loop_or_create_one
|
|
15
15
|
|
|
16
16
|
secured_prefix = 199
|
|
@@ -35,11 +35,11 @@ class RoborockProtocol(asyncio.DatagramProtocol):
|
|
|
35
35
|
|
|
36
36
|
class RoborockLocalClient(RoborockClient):
|
|
37
37
|
|
|
38
|
-
def __init__(self, devices_info: dict[str,
|
|
38
|
+
def __init__(self, devices_info: dict[str, RoborockLocalDeviceInfo]):
|
|
39
39
|
super().__init__("abc", devices_info)
|
|
40
40
|
self.loop = get_running_loop_or_create_one()
|
|
41
41
|
self.device_listener: dict[str, RoborockSocketListener] = {
|
|
42
|
-
device_id: RoborockSocketListener(device_info.
|
|
42
|
+
device_id: RoborockSocketListener(device_info.ip, device_id, self.on_message)
|
|
43
43
|
for device_id, device_info in devices_info.items()
|
|
44
44
|
}
|
|
45
45
|
self._mutex = Lock()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from roborock.local_api import RoborockLocalClient
|
|
5
|
+
from roborock.typing import RoborockLocalDeviceInfo
|
|
6
|
+
|
|
7
|
+
local_ip = "<local_ip>"
|
|
8
|
+
local_key = "<local_key>"
|
|
9
|
+
device_id = "<device_id>"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def main():
|
|
13
|
+
logging_config = {
|
|
14
|
+
"level": logging.DEBUG
|
|
15
|
+
}
|
|
16
|
+
logging.basicConfig(**logging_config)
|
|
17
|
+
client = RoborockLocalClient({
|
|
18
|
+
device_id: RoborockLocalDeviceInfo(local_key, "model_test", local_ip)
|
|
19
|
+
})
|
|
20
|
+
await client.async_connect()
|
|
21
|
+
props = await client.get_prop(device_id)
|
|
22
|
+
print(props)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
asyncio.run(main())
|
|
@@ -4,7 +4,7 @@ from enum import Enum
|
|
|
4
4
|
|
|
5
5
|
from .code_mappings import RoborockDockDustCollectionType, RoborockDockWashingModeType
|
|
6
6
|
from .containers import Status, CleanSummary, Consumable, \
|
|
7
|
-
DNDTimer, CleanRecord, SmartWashParameters
|
|
7
|
+
DNDTimer, CleanRecord, SmartWashParameters
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class RoborockDevicePropField(str, Enum):
|
|
@@ -89,10 +89,14 @@ class RoborockCommand(str, Enum):
|
|
|
89
89
|
GET_NETWORK_INFO = "get_network_info"
|
|
90
90
|
|
|
91
91
|
class RoborockDeviceInfo:
|
|
92
|
-
def __init__(self,
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
95
|
-
|
|
92
|
+
def __init__(self, local_key: str, model: str):
|
|
93
|
+
self.local_key = local_key
|
|
94
|
+
self.model = model
|
|
95
|
+
|
|
96
|
+
class RoborockLocalDeviceInfo(RoborockDeviceInfo):
|
|
97
|
+
def __init__(self, local_key: str, model: str, ip: str):
|
|
98
|
+
super().__init__(local_key, model)
|
|
99
|
+
self.ip = ip
|
|
96
100
|
|
|
97
101
|
class RoborockDockSummary:
|
|
98
102
|
def __init__(self, dust_collection_mode: RoborockDockDustCollectionType,
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
from roborock.containers import HomeDataDevice, HomeDataDeviceField, HomeDataProduct, HomeDataProductField, NetworkInfo, \
|
|
5
|
-
NetworkInfoField
|
|
6
|
-
from roborock.local_api import RoborockLocalClient
|
|
7
|
-
from roborock.typing import RoborockDeviceInfo
|
|
8
|
-
|
|
9
|
-
local_ip = "192.168.1.232"
|
|
10
|
-
local_key = "nXTBj42ej5WxQopO"
|
|
11
|
-
device_id = "1r9W0cAmDZ2COuVekgRhKA"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
async def main():
|
|
15
|
-
logging_config = {
|
|
16
|
-
"level": logging.DEBUG
|
|
17
|
-
}
|
|
18
|
-
logging.basicConfig(**logging_config)
|
|
19
|
-
client = RoborockLocalClient({
|
|
20
|
-
device_id: RoborockDeviceInfo(HomeDataDevice({
|
|
21
|
-
HomeDataDeviceField.DUID: device_id,
|
|
22
|
-
HomeDataDeviceField.LOCAL_KEY: local_key
|
|
23
|
-
}), HomeDataProduct({
|
|
24
|
-
HomeDataProductField.MODEL: "test"
|
|
25
|
-
}), NetworkInfo({
|
|
26
|
-
NetworkInfoField.IP: local_ip
|
|
27
|
-
}))
|
|
28
|
-
})
|
|
29
|
-
await client.async_connect()
|
|
30
|
-
props = await client.get_prop(device_id)
|
|
31
|
-
print(props)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if __name__ == "__main__":
|
|
35
|
-
asyncio.run(main())
|
|
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
|