python-roborock 2.7.1__tar.gz → 2.8.1__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.
Files changed (28) hide show
  1. {python_roborock-2.7.1 → python_roborock-2.8.1}/PKG-INFO +3 -3
  2. {python_roborock-2.7.1 → python_roborock-2.8.1}/pyproject.toml +4 -3
  3. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/code_mappings.py +31 -0
  4. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/const.py +1 -0
  5. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/containers.py +15 -5
  6. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/roborock_typing.py +1 -0
  7. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_1_apis/roborock_client_v1.py +6 -2
  8. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_1_apis/roborock_mqtt_client_v1.py +16 -1
  9. {python_roborock-2.7.1 → python_roborock-2.8.1}/LICENSE +0 -0
  10. {python_roborock-2.7.1 → python_roborock-2.8.1}/README.md +0 -0
  11. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/__init__.py +0 -0
  12. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/api.py +0 -0
  13. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/cli.py +0 -0
  14. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/cloud_api.py +0 -0
  15. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/command_cache.py +0 -0
  16. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/exceptions.py +0 -0
  17. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/local_api.py +0 -0
  18. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/protocol.py +0 -0
  19. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/py.typed +0 -0
  20. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/roborock_future.py +0 -0
  21. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/roborock_message.py +0 -0
  22. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/util.py +0 -0
  23. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_1_apis/__init__.py +0 -0
  24. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
  25. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_a01_apis/__init__.py +0 -0
  26. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
  27. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
  28. {python_roborock-2.7.1 → python_roborock-2.8.1}/roborock/web_api.py +0 -0
@@ -1,20 +1,19 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-roborock
3
- Version: 2.7.1
3
+ Version: 2.8.1
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
7
7
  Keywords: roborock,vacuum,homeassistant
8
8
  Author: humbertogontijo
9
9
  Author-email: humbertogontijo@users.noreply.github.com
10
- Requires-Python: >=3.10,<4.0
10
+ Requires-Python: >=3.11,<4.0
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
14
  Classifier: Natural Language :: English
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
19
18
  Classifier: Programming Language :: Python :: 3.12
20
19
  Classifier: Programming Language :: Python :: 3.13
@@ -27,6 +26,7 @@ Requires-Dist: dacite (>=1.8.0,<2.0.0)
27
26
  Requires-Dist: paho-mqtt (>=1.6.1,<2.0.0)
28
27
  Requires-Dist: pycryptodome (>=3.18,<4.0)
29
28
  Requires-Dist: pycryptodomex (>=3.18,<4.0) ; sys_platform == "darwin"
29
+ Requires-Dist: vacuum-map-parser-roborock
30
30
  Project-URL: Documentation, https://python-roborock.readthedocs.io/
31
31
  Project-URL: Repository, https://github.com/humbertogontijo/python-roborock
32
32
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-roborock"
3
- version = "2.7.1"
3
+ version = "2.8.1"
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"
@@ -21,7 +21,7 @@ keywords = ["roborock", "vacuum", "homeassistant"]
21
21
  roborock = "roborock.cli:main"
22
22
 
23
23
  [tool.poetry.dependencies]
24
- python = "^3.10"
24
+ python = "^3.11"
25
25
  click = ">=8"
26
26
  aiohttp = "^3.8.2"
27
27
  async-timeout = "*"
@@ -30,6 +30,7 @@ pycryptodomex = {version = "^3.18", markers = "sys_platform == 'darwin'"}
30
30
  paho-mqtt = "^1.6.1"
31
31
  dacite = "^1.8.0"
32
32
  construct = "^2.10.57"
33
+ vacuum-map-parser-roborock = "*"
33
34
 
34
35
 
35
36
  [build-system]
@@ -47,7 +48,7 @@ pyshark = "^0.6"
47
48
 
48
49
  [tool.semantic_release]
49
50
  branch = "main"
50
- version_toml = "pyproject.toml:tool.poetry.version"
51
+ version_toml = ["pyproject.toml:tool.poetry.version"]
51
52
  build_command = "pip install poetry && poetry build"
52
53
  [tool.semantic_release.commit_parser_options]
53
54
  allowed_tags = [
@@ -243,6 +243,15 @@ class RoborockFanSpeedQ7Max(RoborockFanPowerCode):
243
243
  max = 104
244
244
 
245
245
 
246
+ class RoborockFanSpeedQRevoMaster(RoborockFanPowerCode):
247
+ quiet = 101
248
+ balanced = 102
249
+ turbo = 103
250
+ max = 104
251
+ max_plus = 105
252
+ custom = 110 # Smartplan
253
+
254
+
246
255
  class RoborockFanSpeedP10(RoborockFanPowerCode):
247
256
  off = 105
248
257
  quiet = 101
@@ -288,6 +297,7 @@ class RoborockMopModeS8ProUltra(RoborockMopModeCode):
288
297
  class RoborockMopModeS8MaxVUltra(RoborockMopModeCode):
289
298
  standard = 300
290
299
  deep = 301
300
+ custom = 302
291
301
  deep_plus = 303
292
302
  fast = 304
293
303
  deep_plus_pearl = 305
@@ -318,6 +328,17 @@ class RoborockMopIntensityV2(RoborockMopIntensityCode):
318
328
  custom = 207
319
329
 
320
330
 
331
+ class RoborockMopIntensityQRevoMaster(RoborockMopIntensityCode):
332
+ """Describes the mop intensity of the vacuum cleaner."""
333
+
334
+ off = 200
335
+ low = 201
336
+ medium = 202
337
+ high = 203
338
+ custom_water_flow = 207
339
+ custom = 209 # SmartPlan
340
+
341
+
321
342
  class RoborockMopIntensityP10(RoborockMopIntensityCode):
322
343
  """Describes the mop intensity of the vacuum cleaner."""
323
344
 
@@ -362,6 +383,16 @@ class RoborockMopIntensityS6MaxV(RoborockMopIntensityCode):
362
383
  custom_water_flow = 207
363
384
 
364
385
 
386
+ class RoborockMopIntensityQ7Max(RoborockMopIntensityCode):
387
+ """Describes the mop intensity of the vacuum cleaner."""
388
+
389
+ off = 200
390
+ low = 201
391
+ medium = 202
392
+ high = 203
393
+ custom_water_flow = 207
394
+
395
+
365
396
  class RoborockDockErrorCode(RoborockEnum):
366
397
  """Describes the error code of the dock."""
367
398
 
@@ -30,6 +30,7 @@ ROBOROCK_Q5_PRO = "roborock.vacuum.a72"
30
30
  ROBOROCK_Q7 = "roborock.vacuum.a40"
31
31
  ROBOROCK_Q7_MAX = "roborock.vacuum.a38"
32
32
  ROBOROCK_Q7PLUS = "roborock.vacuum.a40"
33
+ ROBOROCK_QREVO_MASTER = "roborock.vacuum.a117"
33
34
  ROBOROCK_Q8_MAX = "roborock.vacuum.a73"
34
35
  ROBOROCK_G10S_PRO = "roborock.vacuum.a26"
35
36
  ROBOROCK_G10S = "roborock.vacuum.a46"
@@ -20,6 +20,7 @@ from .code_mappings import (
20
20
  RoborockFanPowerCode,
21
21
  RoborockFanSpeedP10,
22
22
  RoborockFanSpeedQ7Max,
23
+ RoborockFanSpeedQRevoMaster,
23
24
  RoborockFanSpeedS6Pure,
24
25
  RoborockFanSpeedS7,
25
26
  RoborockFanSpeedS7MaxV,
@@ -28,11 +29,12 @@ from .code_mappings import (
28
29
  RoborockInCleaning,
29
30
  RoborockMopIntensityCode,
30
31
  RoborockMopIntensityP10,
32
+ RoborockMopIntensityQ7Max,
33
+ RoborockMopIntensityQRevoMaster,
31
34
  RoborockMopIntensityS5Max,
32
35
  RoborockMopIntensityS6MaxV,
33
36
  RoborockMopIntensityS7,
34
37
  RoborockMopIntensityS8MaxVUltra,
35
- RoborockMopIntensityV2,
36
38
  RoborockMopModeCode,
37
39
  RoborockMopModeS7,
38
40
  RoborockMopModeS8MaxVUltra,
@@ -49,6 +51,7 @@ from .const import (
49
51
  ROBOROCK_G10S_PRO,
50
52
  ROBOROCK_P10,
51
53
  ROBOROCK_Q7_MAX,
54
+ ROBOROCK_QREVO_MASTER,
52
55
  ROBOROCK_QREVO_MAXV,
53
56
  ROBOROCK_QREVO_PRO,
54
57
  ROBOROCK_QREVO_S,
@@ -138,12 +141,12 @@ class RoborockBase:
138
141
  cls_annotations.update(getattr(base, "__annotations__", {}))
139
142
  remove_keys = []
140
143
  for key, value in data.items():
141
- if value == "None" or value is None:
142
- data[key] = None
143
- continue
144
144
  if key not in cls_annotations:
145
145
  remove_keys.append(key)
146
146
  continue
147
+ if value == "None" or value is None:
148
+ data[key] = None
149
+ continue
147
150
  field_type: str = cls_annotations[key]
148
151
  if "|" in field_type:
149
152
  # It's a union
@@ -567,7 +570,13 @@ class S5MaxStatus(Status):
567
570
  @dataclass
568
571
  class Q7MaxStatus(Status):
569
572
  fan_power: RoborockFanSpeedQ7Max | None = None
570
- water_box_mode: RoborockMopIntensityV2 | None = None
573
+ water_box_mode: RoborockMopIntensityQ7Max | None = None
574
+
575
+
576
+ @dataclass
577
+ class QRevoMasterStatus(Status):
578
+ fan_power: RoborockFanSpeedQRevoMaster | None = None
579
+ water_box_mode: RoborockMopIntensityQRevoMaster | None = None
571
580
 
572
581
 
573
582
  @dataclass
@@ -627,6 +636,7 @@ ModelStatus: dict[str, type[Status]] = {
627
636
  ROBOROCK_S4_MAX: S4MaxStatus,
628
637
  ROBOROCK_S5_MAX: S5MaxStatus,
629
638
  ROBOROCK_Q7_MAX: Q7MaxStatus,
639
+ ROBOROCK_QREVO_MASTER: QRevoMasterStatus,
630
640
  ROBOROCK_S6: S6PureStatus,
631
641
  ROBOROCK_S6_MAXV: S6MaxVStatus,
632
642
  ROBOROCK_S6_PURE: S6PureStatus,
@@ -116,6 +116,7 @@ class RoborockCommand(str, Enum):
116
116
  GET_MAP_STATUS = "get_map_status"
117
117
  GET_MAP_V1 = "get_map_v1"
118
118
  GET_MAP_V2 = "get_map_v2"
119
+ GET_MAP_CALIBRATION = "get_map_calibration" # Custom command
119
120
  GET_MOP_MOTOR_STATUS = "get_mop_motor_status"
120
121
  GET_MOP_TEMPLATE_PARAMS_BY_ID = "get_mop_template_params_by_id"
121
122
  GET_MOP_TEMPLATE_PARAMS_SUMMARY = "get_mop_template_params_summary"
@@ -55,10 +55,14 @@ from roborock.roborock_message import (
55
55
  )
56
56
  from roborock.util import RepeatableTask, get_next_int, unpack_list
57
57
 
58
- COMMANDS_SECURED = [
58
+ COMMANDS_SECURED = {
59
59
  RoborockCommand.GET_MAP_V1,
60
60
  RoborockCommand.GET_MULTI_MAP,
61
- ]
61
+ }
62
+
63
+ CUSTOM_COMMANDS = {RoborockCommand.GET_MAP_CALIBRATION}
64
+
65
+ CLOUD_REQUIRED = COMMANDS_SECURED.union(CUSTOM_COMMANDS)
62
66
 
63
67
  WASH_N_FILL_DOCK = [
64
68
  RoborockDockTypeCode.empty_wash_fill_dock,
@@ -2,6 +2,10 @@ import asyncio
2
2
  import base64
3
3
 
4
4
  import paho.mqtt.client as mqtt
5
+ from vacuum_map_parser_base.config.color import ColorsPalette
6
+ from vacuum_map_parser_base.config.image_config import ImageConfig
7
+ from vacuum_map_parser_base.config.size import Sizes
8
+ from vacuum_map_parser_roborock.map_data_parser import RoborockMapDataParser
5
9
 
6
10
  from roborock.cloud_api import RoborockMqttClient
7
11
 
@@ -13,7 +17,7 @@ from ..roborock_message import (
13
17
  RoborockMessageProtocol,
14
18
  )
15
19
  from ..roborock_typing import RoborockCommand
16
- from .roborock_client_v1 import COMMANDS_SECURED, RoborockClientV1
20
+ from .roborock_client_v1 import COMMANDS_SECURED, CUSTOM_COMMANDS, RoborockClientV1
17
21
 
18
22
 
19
23
  class RoborockMqttClientV1(RoborockMqttClient, RoborockClientV1):
@@ -66,10 +70,21 @@ class RoborockMqttClientV1(RoborockMqttClient, RoborockClientV1):
66
70
  method: RoborockCommand | str,
67
71
  params: list | dict | int | None = None,
68
72
  ):
73
+ if method in CUSTOM_COMMANDS:
74
+ # When we have more custom commands do something more complicated here
75
+ return await self._get_calibration_points()
69
76
  request_id, timestamp, payload = self._get_payload(method, params, True)
70
77
  request_protocol = RoborockMessageProtocol.RPC_REQUEST
71
78
  roborock_message = RoborockMessage(timestamp=timestamp, protocol=request_protocol, payload=payload)
72
79
  return await self.send_message(roborock_message)
73
80
 
81
+ async def _get_calibration_points(self):
82
+ map: bytes = await self.send_command(RoborockCommand.GET_MAP_V1)
83
+ parser = RoborockMapDataParser(ColorsPalette(), Sizes(), [], ImageConfig(), [])
84
+ parsed_map = parser.parse(map)
85
+ calibration = parsed_map.calibration()
86
+ self._logger.info(parsed_map.calibration())
87
+ return calibration
88
+
74
89
  async def get_map_v1(self) -> bytes | None:
75
90
  return await self.send_command(RoborockCommand.GET_MAP_V1)
File without changes