python-roborock 2.8.5__tar.gz → 2.9.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.8.5 → python_roborock-2.9.0}/PKG-INFO +45 -1
- python_roborock-2.9.0/README.md +76 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/pyproject.toml +5 -1
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/code_mappings.py +27 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/const.py +1 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/containers.py +34 -20
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/roborock_typing.py +6 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_client_v1.py +7 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/web_api.py +31 -11
- python_roborock-2.8.5/README.md +0 -32
- {python_roborock-2.8.5 → python_roborock-2.9.0}/LICENSE +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/__init__.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/api.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/cli.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/cloud_api.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/command_cache.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/exceptions.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/local_api.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/protocol.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/py.typed +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/roborock_future.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/roborock_message.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/util.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/__init__.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_a01_apis/__init__.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
- {python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.0
|
|
4
4
|
Summary: A package to control Roborock vacuums.
|
|
5
5
|
Home-page: https://github.com/humbertogontijo/python-roborock
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -53,6 +53,50 @@ Install this via pip (or your favourite package manager):
|
|
|
53
53
|
|
|
54
54
|
You can see all of the commands supported [here]("https://python-roborock.readthedocs.io/en/latest/api_commands.html")
|
|
55
55
|
|
|
56
|
+
## Sending Commands
|
|
57
|
+
|
|
58
|
+
Here is an example that requires no manual intervention and can be done all automatically. You can skip some steps by
|
|
59
|
+
caching values or looking at them and grabbing them manually.
|
|
60
|
+
```python
|
|
61
|
+
import asyncio
|
|
62
|
+
|
|
63
|
+
from roborock import HomeDataProduct, DeviceData, RoborockCommand
|
|
64
|
+
from roborock.version_1_apis import RoborockMqttClientV1, RoborockLocalClientV1
|
|
65
|
+
from roborock.web_api import RoborockApiClient
|
|
66
|
+
|
|
67
|
+
async def main():
|
|
68
|
+
web_api = RoborockApiClient(username="youremailhere")
|
|
69
|
+
# Login via your password
|
|
70
|
+
user_data = await web_api.pass_login(password="pass_here")
|
|
71
|
+
# Or login via a code
|
|
72
|
+
await web_api.request_code()
|
|
73
|
+
code = input("What is the code?")
|
|
74
|
+
user_data = await web_api.code_login(code)
|
|
75
|
+
|
|
76
|
+
# Get home data
|
|
77
|
+
home_data = await web_api.get_home_data_v2(user_data)
|
|
78
|
+
|
|
79
|
+
# Get the device you want
|
|
80
|
+
device = home_data.devices[0]
|
|
81
|
+
|
|
82
|
+
# Get product ids:
|
|
83
|
+
product_info: dict[str, HomeDataProduct] = {
|
|
84
|
+
product.id: product for product in home_data.products
|
|
85
|
+
}
|
|
86
|
+
# Create the Mqtt(aka cloud required) Client
|
|
87
|
+
device_data = DeviceData(device, product_info[device.product_id].model)
|
|
88
|
+
mqtt_client = RoborockMqttClientV1(user_data, device_data)
|
|
89
|
+
networking = await mqtt_client.get_networking()
|
|
90
|
+
local_device_data = DeviceData(device, product_info[device.product_id].model, networking)
|
|
91
|
+
local_client = RoborockLocalClientV1(local_device_data)
|
|
92
|
+
# You can use the send_command to send any command to the device
|
|
93
|
+
status = await local_client.send_command(RoborockCommand.GET_STATUS)
|
|
94
|
+
# Or use existing functions that will give you data classes
|
|
95
|
+
status = await local_client.get_status()
|
|
96
|
+
|
|
97
|
+
asyncio.run(main())
|
|
98
|
+
```
|
|
99
|
+
|
|
56
100
|
## Supported devices
|
|
57
101
|
|
|
58
102
|
You can find what devices are supported
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Roborock
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://pypi.org/project/python-roborock/">
|
|
5
|
+
<img src="https://img.shields.io/pypi/v/python-roborock.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
|
|
6
|
+
</a>
|
|
7
|
+
<img src="https://img.shields.io/pypi/pyversions/python-roborock.svg?style=flat-square&logo=python&logoColor=fff" alt="Supported Python versions">
|
|
8
|
+
<img src="https://img.shields.io/pypi/l/python-roborock.svg?style=flat-square" alt="License">
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
Roborock library for online and offline control of your vacuums.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Install this via pip (or your favourite package manager):
|
|
16
|
+
|
|
17
|
+
`pip install python-roborock`
|
|
18
|
+
|
|
19
|
+
## Functionality
|
|
20
|
+
|
|
21
|
+
You can see all of the commands supported [here]("https://python-roborock.readthedocs.io/en/latest/api_commands.html")
|
|
22
|
+
|
|
23
|
+
## Sending Commands
|
|
24
|
+
|
|
25
|
+
Here is an example that requires no manual intervention and can be done all automatically. You can skip some steps by
|
|
26
|
+
caching values or looking at them and grabbing them manually.
|
|
27
|
+
```python
|
|
28
|
+
import asyncio
|
|
29
|
+
|
|
30
|
+
from roborock import HomeDataProduct, DeviceData, RoborockCommand
|
|
31
|
+
from roborock.version_1_apis import RoborockMqttClientV1, RoborockLocalClientV1
|
|
32
|
+
from roborock.web_api import RoborockApiClient
|
|
33
|
+
|
|
34
|
+
async def main():
|
|
35
|
+
web_api = RoborockApiClient(username="youremailhere")
|
|
36
|
+
# Login via your password
|
|
37
|
+
user_data = await web_api.pass_login(password="pass_here")
|
|
38
|
+
# Or login via a code
|
|
39
|
+
await web_api.request_code()
|
|
40
|
+
code = input("What is the code?")
|
|
41
|
+
user_data = await web_api.code_login(code)
|
|
42
|
+
|
|
43
|
+
# Get home data
|
|
44
|
+
home_data = await web_api.get_home_data_v2(user_data)
|
|
45
|
+
|
|
46
|
+
# Get the device you want
|
|
47
|
+
device = home_data.devices[0]
|
|
48
|
+
|
|
49
|
+
# Get product ids:
|
|
50
|
+
product_info: dict[str, HomeDataProduct] = {
|
|
51
|
+
product.id: product for product in home_data.products
|
|
52
|
+
}
|
|
53
|
+
# Create the Mqtt(aka cloud required) Client
|
|
54
|
+
device_data = DeviceData(device, product_info[device.product_id].model)
|
|
55
|
+
mqtt_client = RoborockMqttClientV1(user_data, device_data)
|
|
56
|
+
networking = await mqtt_client.get_networking()
|
|
57
|
+
local_device_data = DeviceData(device, product_info[device.product_id].model, networking)
|
|
58
|
+
local_client = RoborockLocalClientV1(local_device_data)
|
|
59
|
+
# You can use the send_command to send any command to the device
|
|
60
|
+
status = await local_client.send_command(RoborockCommand.GET_STATUS)
|
|
61
|
+
# Or use existing functions that will give you data classes
|
|
62
|
+
status = await local_client.get_status()
|
|
63
|
+
|
|
64
|
+
asyncio.run(main())
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Supported devices
|
|
68
|
+
|
|
69
|
+
You can find what devices are supported
|
|
70
|
+
[here]("https://python-roborock.readthedocs.io/en/latest/supported_devices.html").
|
|
71
|
+
Please note this may not immediately contain the latest devices.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## Credits
|
|
75
|
+
|
|
76
|
+
Thanks @rovo89 for https://gist.github.com/rovo89/dff47ed19fca0dfdda77503e66c2b7c7 And thanks @PiotrMachowski for https://github.com/PiotrMachowski/Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.9.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"
|
|
@@ -45,6 +45,7 @@ mypy = "*"
|
|
|
45
45
|
ruff = "*"
|
|
46
46
|
codespell = "*"
|
|
47
47
|
pyshark = "^0.6"
|
|
48
|
+
aioresponses = "^0.7.7"
|
|
48
49
|
|
|
49
50
|
[tool.semantic_release]
|
|
50
51
|
branch = "main"
|
|
@@ -67,3 +68,6 @@ select=["E", "F", "UP", "I"]
|
|
|
67
68
|
|
|
68
69
|
[tool.ruff.lint.per-file-ignores]
|
|
69
70
|
"*/__init__.py" = ["F401"]
|
|
71
|
+
|
|
72
|
+
[tool.pytest.ini_options]
|
|
73
|
+
asyncio_mode = "auto"
|
|
@@ -254,6 +254,15 @@ class RoborockFanSpeedQRevoMaster(RoborockFanPowerCode):
|
|
|
254
254
|
smart_mode = 110
|
|
255
255
|
|
|
256
256
|
|
|
257
|
+
class RoborockFanSpeedQRevoCurv(RoborockFanPowerCode):
|
|
258
|
+
quiet = 101
|
|
259
|
+
balanced = 102
|
|
260
|
+
turbo = 103
|
|
261
|
+
max = 104
|
|
262
|
+
max_plus = 105
|
|
263
|
+
smart_mode = 110
|
|
264
|
+
|
|
265
|
+
|
|
257
266
|
class RoborockFanSpeedP10(RoborockFanPowerCode):
|
|
258
267
|
off = 105
|
|
259
268
|
quiet = 101
|
|
@@ -279,6 +288,14 @@ class RoborockMopModeCode(RoborockEnum):
|
|
|
279
288
|
"""Describes the mop mode of the vacuum cleaner."""
|
|
280
289
|
|
|
281
290
|
|
|
291
|
+
class RoborockMopModeQRevoCurv(RoborockMopModeCode):
|
|
292
|
+
standard = 300
|
|
293
|
+
deep = 301
|
|
294
|
+
deep_plus = 303
|
|
295
|
+
fast = 304
|
|
296
|
+
smart_mode = 306
|
|
297
|
+
|
|
298
|
+
|
|
282
299
|
class RoborockMopModeS7(RoborockMopModeCode):
|
|
283
300
|
"""Describes the mop mode of the vacuum cleaner."""
|
|
284
301
|
|
|
@@ -351,6 +368,15 @@ class RoborockMopIntensityQRevoMaster(RoborockMopIntensityCode):
|
|
|
351
368
|
smart_mode = 209
|
|
352
369
|
|
|
353
370
|
|
|
371
|
+
class RoborockMopIntensityQRevoCurv(RoborockMopIntensityCode):
|
|
372
|
+
off = 200
|
|
373
|
+
low = 201
|
|
374
|
+
medium = 202
|
|
375
|
+
high = 203
|
|
376
|
+
custom_water_flow = 207
|
|
377
|
+
smart_mode = 209
|
|
378
|
+
|
|
379
|
+
|
|
354
380
|
class RoborockMopIntensityP10(RoborockMopIntensityCode):
|
|
355
381
|
"""Describes the mop intensity of the vacuum cleaner."""
|
|
356
382
|
|
|
@@ -431,6 +457,7 @@ class RoborockDockTypeCode(RoborockEnum):
|
|
|
431
457
|
s8_maxv_ultra_dock = 10
|
|
432
458
|
qrevo_master_dock = 14
|
|
433
459
|
qrevo_s_dock = 15
|
|
460
|
+
qrevo_curv_dock = 17
|
|
434
461
|
|
|
435
462
|
|
|
436
463
|
class RoborockDockDustCollectionModeCode(RoborockEnum):
|
|
@@ -31,6 +31,7 @@ ROBOROCK_Q7 = "roborock.vacuum.a40"
|
|
|
31
31
|
ROBOROCK_Q7_MAX = "roborock.vacuum.a38"
|
|
32
32
|
ROBOROCK_Q7PLUS = "roborock.vacuum.a40"
|
|
33
33
|
ROBOROCK_QREVO_MASTER = "roborock.vacuum.a117"
|
|
34
|
+
ROBOROCK_QREVO_CURV = "roborock.vacuum.a135"
|
|
34
35
|
ROBOROCK_Q8_MAX = "roborock.vacuum.a73"
|
|
35
36
|
ROBOROCK_G10S_PRO = "roborock.vacuum.a26"
|
|
36
37
|
ROBOROCK_G10S = "roborock.vacuum.a46"
|
|
@@ -20,6 +20,7 @@ from .code_mappings import (
|
|
|
20
20
|
RoborockFanPowerCode,
|
|
21
21
|
RoborockFanSpeedP10,
|
|
22
22
|
RoborockFanSpeedQ7Max,
|
|
23
|
+
RoborockFanSpeedQRevoCurv,
|
|
23
24
|
RoborockFanSpeedQRevoMaster,
|
|
24
25
|
RoborockFanSpeedS6Pure,
|
|
25
26
|
RoborockFanSpeedS7,
|
|
@@ -30,12 +31,14 @@ from .code_mappings import (
|
|
|
30
31
|
RoborockMopIntensityCode,
|
|
31
32
|
RoborockMopIntensityP10,
|
|
32
33
|
RoborockMopIntensityQ7Max,
|
|
34
|
+
RoborockMopIntensityQRevoCurv,
|
|
33
35
|
RoborockMopIntensityQRevoMaster,
|
|
34
36
|
RoborockMopIntensityS5Max,
|
|
35
37
|
RoborockMopIntensityS6MaxV,
|
|
36
38
|
RoborockMopIntensityS7,
|
|
37
39
|
RoborockMopIntensityS8MaxVUltra,
|
|
38
40
|
RoborockMopModeCode,
|
|
41
|
+
RoborockMopModeQRevoCurv,
|
|
39
42
|
RoborockMopModeQRevoMaster,
|
|
40
43
|
RoborockMopModeS7,
|
|
41
44
|
RoborockMopModeS8MaxVUltra,
|
|
@@ -52,6 +55,7 @@ from .const import (
|
|
|
52
55
|
ROBOROCK_G10S_PRO,
|
|
53
56
|
ROBOROCK_P10,
|
|
54
57
|
ROBOROCK_Q7_MAX,
|
|
58
|
+
ROBOROCK_QREVO_CURV,
|
|
55
59
|
ROBOROCK_QREVO_MASTER,
|
|
56
60
|
ROBOROCK_QREVO_MAXV,
|
|
57
61
|
ROBOROCK_QREVO_PRO,
|
|
@@ -581,6 +585,13 @@ class QRevoMasterStatus(Status):
|
|
|
581
585
|
mop_mode: RoborockMopModeQRevoMaster | None = None
|
|
582
586
|
|
|
583
587
|
|
|
588
|
+
@dataclass
|
|
589
|
+
class QRevoCurvStatus(Status):
|
|
590
|
+
fan_power: RoborockFanSpeedQRevoCurv | None = None
|
|
591
|
+
water_box_mode: RoborockMopIntensityQRevoCurv | None = None
|
|
592
|
+
mop_mode: RoborockMopModeQRevoCurv | None = None
|
|
593
|
+
|
|
594
|
+
|
|
584
595
|
@dataclass
|
|
585
596
|
class S6MaxVStatus(Status):
|
|
586
597
|
fan_power: RoborockFanSpeedS7MaxV | None = None
|
|
@@ -639,6 +650,7 @@ ModelStatus: dict[str, type[Status]] = {
|
|
|
639
650
|
ROBOROCK_S5_MAX: S5MaxStatus,
|
|
640
651
|
ROBOROCK_Q7_MAX: Q7MaxStatus,
|
|
641
652
|
ROBOROCK_QREVO_MASTER: QRevoMasterStatus,
|
|
653
|
+
ROBOROCK_QREVO_CURV: QRevoCurvStatus,
|
|
642
654
|
ROBOROCK_S6: S6PureStatus,
|
|
643
655
|
ROBOROCK_S6_MAXV: S6MaxVStatus,
|
|
644
656
|
ROBOROCK_S6_PURE: S6PureStatus,
|
|
@@ -881,26 +893,28 @@ class RoborockProductSpec(RoborockBase):
|
|
|
881
893
|
|
|
882
894
|
@dataclass
|
|
883
895
|
class RoborockProduct(RoborockBase):
|
|
884
|
-
id: int
|
|
885
|
-
name: str
|
|
886
|
-
model: str
|
|
887
|
-
packagename: str
|
|
888
|
-
ssid: str
|
|
889
|
-
picurl: str
|
|
890
|
-
cardpicurl: str
|
|
891
|
-
|
|
892
|
-
resetwifipicurl: str
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
896
|
+
id: int | None = None
|
|
897
|
+
name: str | None = None
|
|
898
|
+
model: str | None = None
|
|
899
|
+
packagename: str | None = None
|
|
900
|
+
ssid: str | None = None
|
|
901
|
+
picurl: str | None = None
|
|
902
|
+
cardpicurl: str | None = None
|
|
903
|
+
mediumCardpicurl: str | None = None
|
|
904
|
+
resetwifipicurl: str | None = None
|
|
905
|
+
configPicUrl: str | None = None
|
|
906
|
+
pluginPicUrl: str | None = None
|
|
907
|
+
resetwifitext: dict | None = None
|
|
908
|
+
tuyaid: str | None = None
|
|
909
|
+
status: int | None = None
|
|
910
|
+
rriotid: str | None = None
|
|
911
|
+
pictures: list | None = None
|
|
912
|
+
ncMode: str | None = None
|
|
913
|
+
scope: str | None = None
|
|
914
|
+
product_tags: list | None = None
|
|
915
|
+
agreements: list | None = None
|
|
916
|
+
cardspec: str | None = None
|
|
917
|
+
plugin_pic_url: str | None = None
|
|
904
918
|
products_specification: RoborockProductSpec | None = None
|
|
905
919
|
|
|
906
920
|
def __post_init__(self):
|
|
@@ -461,6 +461,11 @@ class DeviceProp(RoborockBase):
|
|
|
461
461
|
consumable: Consumable = field(default_factory=Consumable)
|
|
462
462
|
last_clean_record: CleanRecord | None = None
|
|
463
463
|
dock_summary: DockSummary | None = None
|
|
464
|
+
dust_collection_mode_name: str | None = None
|
|
465
|
+
|
|
466
|
+
def __post_init__(self) -> None:
|
|
467
|
+
if self.dock_summary and self.dock_summary.dust_collection_mode and self.dock_summary.dust_collection_mode.mode:
|
|
468
|
+
self.dust_collection_mode_name = self.dock_summary.dust_collection_mode.mode.name
|
|
464
469
|
|
|
465
470
|
def update(self, device_prop: DeviceProp) -> None:
|
|
466
471
|
if device_prop.status:
|
|
@@ -473,3 +478,4 @@ class DeviceProp(RoborockBase):
|
|
|
473
478
|
self.last_clean_record = device_prop.last_clean_record
|
|
474
479
|
if device_prop.dock_summary:
|
|
475
480
|
self.dock_summary = device_prop.dock_summary
|
|
481
|
+
self.__post_init__()
|
{python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_client_v1.py
RENAMED
|
@@ -71,6 +71,7 @@ WASH_N_FILL_DOCK = [
|
|
|
71
71
|
RoborockDockTypeCode.p10_pro_dock,
|
|
72
72
|
RoborockDockTypeCode.s8_maxv_ultra_dock,
|
|
73
73
|
RoborockDockTypeCode.qrevo_s_dock,
|
|
74
|
+
RoborockDockTypeCode.qrevo_curv_dock,
|
|
74
75
|
]
|
|
75
76
|
RT = TypeVar("RT", bound=RoborockBase)
|
|
76
77
|
EVICT_TIME = 60
|
|
@@ -420,6 +421,12 @@ class RoborockClientV1(RoborockClient):
|
|
|
420
421
|
consumable = Consumable.from_dict(value)
|
|
421
422
|
for listener in self.listener_model.protocol_handlers.get(data_protocol, []):
|
|
422
423
|
listener(consumable)
|
|
424
|
+
else:
|
|
425
|
+
self._logger.warning(
|
|
426
|
+
f"Unknown data protocol {data_point_number}, please create an "
|
|
427
|
+
f"issue on the python-roborock repository"
|
|
428
|
+
)
|
|
429
|
+
self._logger.info(data)
|
|
423
430
|
return
|
|
424
431
|
except ValueError:
|
|
425
432
|
self._logger.warning(
|
|
@@ -54,7 +54,7 @@ class RoborockApiClient:
|
|
|
54
54
|
raise RoborockMissingParameters(
|
|
55
55
|
"You are missing parameters for this request, are you sure you " "entered your username?"
|
|
56
56
|
)
|
|
57
|
-
raise RoborockUrlException(response.get(
|
|
57
|
+
raise RoborockUrlException(f"error code: {response_code} msg: {response.get('error')}")
|
|
58
58
|
response_data = response.get("data")
|
|
59
59
|
if response_data is None:
|
|
60
60
|
raise RoborockUrlException("response does not have 'data'")
|
|
@@ -146,7 +146,7 @@ class RoborockApiClient:
|
|
|
146
146
|
"""
|
|
147
147
|
raise NotImplementedError("Pass_login_v3 has not yet been implemented")
|
|
148
148
|
|
|
149
|
-
async def code_login(self, code) -> UserData:
|
|
149
|
+
async def code_login(self, code: int | str) -> UserData:
|
|
150
150
|
base_url = await self._get_base_url()
|
|
151
151
|
header_clientid = self._get_header_client_id()
|
|
152
152
|
|
|
@@ -276,7 +276,7 @@ class RoborockApiClient:
|
|
|
276
276
|
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
|
|
277
277
|
product_response = await product_request.request(
|
|
278
278
|
"get",
|
|
279
|
-
"/api/
|
|
279
|
+
"/api/v4/product",
|
|
280
280
|
headers={"Authorization": user_data.token},
|
|
281
281
|
)
|
|
282
282
|
if product_response is None:
|
|
@@ -288,24 +288,44 @@ class RoborockApiClient:
|
|
|
288
288
|
return ProductResponse.from_dict(result)
|
|
289
289
|
raise RoborockException("product result was an unexpected type")
|
|
290
290
|
|
|
291
|
+
async def download_code(self, user_data: UserData, product_id: int):
|
|
292
|
+
base_url = await self._get_base_url()
|
|
293
|
+
header_clientid = self._get_header_client_id()
|
|
294
|
+
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
|
|
295
|
+
request = {"apilevel": 99999, "productids": [product_id], "type": 2}
|
|
296
|
+
response = await product_request.request(
|
|
297
|
+
"post",
|
|
298
|
+
"/api/v1/appplugin",
|
|
299
|
+
json=request,
|
|
300
|
+
headers={"Authorization": user_data.token, "Content-Type": "application/json"},
|
|
301
|
+
)
|
|
302
|
+
return response["data"][0]["url"]
|
|
303
|
+
|
|
304
|
+
async def download_category_code(self, user_data: UserData):
|
|
305
|
+
base_url = await self._get_base_url()
|
|
306
|
+
header_clientid = self._get_header_client_id()
|
|
307
|
+
product_request = PreparedRequest(base_url, {"header_clientid": header_clientid})
|
|
308
|
+
response = await product_request.request(
|
|
309
|
+
"get",
|
|
310
|
+
"api/v1/plugins?apiLevel=99999&type=2",
|
|
311
|
+
headers={
|
|
312
|
+
"Authorization": user_data.token,
|
|
313
|
+
},
|
|
314
|
+
)
|
|
315
|
+
return {r["category"]: r["url"] for r in response["data"]["categoryPluginList"]}
|
|
316
|
+
|
|
291
317
|
|
|
292
318
|
class PreparedRequest:
|
|
293
319
|
def __init__(self, base_url: str, base_headers: dict | None = None) -> None:
|
|
294
320
|
self.base_url = base_url
|
|
295
321
|
self.base_headers = base_headers or {}
|
|
296
322
|
|
|
297
|
-
async def request(self, method: str, url: str, params=None, data=None, headers=None) -> dict:
|
|
323
|
+
async def request(self, method: str, url: str, params=None, data=None, headers=None, json=None) -> dict:
|
|
298
324
|
_url = "/".join(s.strip("/") for s in [self.base_url, url])
|
|
299
325
|
_headers = {**self.base_headers, **(headers or {})}
|
|
300
326
|
async with aiohttp.ClientSession() as session:
|
|
301
327
|
try:
|
|
302
|
-
async with session.request(
|
|
303
|
-
method,
|
|
304
|
-
_url,
|
|
305
|
-
params=params,
|
|
306
|
-
data=data,
|
|
307
|
-
headers=_headers,
|
|
308
|
-
) as resp:
|
|
328
|
+
async with session.request(method, _url, params=params, data=data, headers=_headers, json=json) as resp:
|
|
309
329
|
return await resp.json()
|
|
310
330
|
except ContentTypeError as err:
|
|
311
331
|
"""If we get an error, lets log everything for debugging."""
|
python_roborock-2.8.5/README.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Roborock
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<a href="https://pypi.org/project/python-roborock/">
|
|
5
|
-
<img src="https://img.shields.io/pypi/v/python-roborock.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
|
|
6
|
-
</a>
|
|
7
|
-
<img src="https://img.shields.io/pypi/pyversions/python-roborock.svg?style=flat-square&logo=python&logoColor=fff" alt="Supported Python versions">
|
|
8
|
-
<img src="https://img.shields.io/pypi/l/python-roborock.svg?style=flat-square" alt="License">
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
Roborock library for online and offline control of your vacuums.
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
Install this via pip (or your favourite package manager):
|
|
16
|
-
|
|
17
|
-
`pip install python-roborock`
|
|
18
|
-
|
|
19
|
-
## Functionality
|
|
20
|
-
|
|
21
|
-
You can see all of the commands supported [here]("https://python-roborock.readthedocs.io/en/latest/api_commands.html")
|
|
22
|
-
|
|
23
|
-
## Supported devices
|
|
24
|
-
|
|
25
|
-
You can find what devices are supported
|
|
26
|
-
[here]("https://python-roborock.readthedocs.io/en/latest/supported_devices.html").
|
|
27
|
-
Please note this may not immediately contain the latest devices.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## Credits
|
|
31
|
-
|
|
32
|
-
Thanks @rovo89 for https://gist.github.com/rovo89/dff47ed19fca0dfdda77503e66c2b7c7 And thanks @PiotrMachowski for https://github.com/PiotrMachowski/Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor
|
|
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.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_local_client_v1.py
RENAMED
|
File without changes
|
{python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-2.8.5 → python_roborock-2.9.0}/roborock/version_a01_apis/roborock_client_a01.py
RENAMED
|
File without changes
|
|
File without changes
|