python-roborock 2.8.5__tar.gz → 2.9.0rc1__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.8.5 → python_roborock-2.9.0rc1}/PKG-INFO +2 -2
  2. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/pyproject.toml +11 -2
  3. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/api.py +16 -10
  4. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/code_mappings.py +3 -16
  5. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/containers.py +3 -5
  6. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_1_apis/roborock_client_v1.py +1 -7
  7. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_1_apis/roborock_local_client_v1.py +0 -1
  8. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -1
  9. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/LICENSE +0 -0
  10. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/README.md +0 -0
  11. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/__init__.py +0 -0
  12. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/cli.py +0 -0
  13. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/cloud_api.py +0 -0
  14. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/command_cache.py +0 -0
  15. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/const.py +0 -0
  16. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/exceptions.py +0 -0
  17. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/local_api.py +0 -0
  18. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/protocol.py +0 -0
  19. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/py.typed +0 -0
  20. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/roborock_future.py +0 -0
  21. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/roborock_message.py +0 -0
  22. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/roborock_typing.py +0 -0
  23. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/util.py +0 -0
  24. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_1_apis/__init__.py +0 -0
  25. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_a01_apis/__init__.py +0 -0
  26. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
  27. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
  28. {python_roborock-2.8.5 → python_roborock-2.9.0rc1}/roborock/web_api.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.1
2
2
  Name: python-roborock
3
- Version: 2.8.5
3
+ Version: 2.9.0rc1
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-roborock"
3
- version = "2.8.5"
3
+ version = "2.9.0-rc.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"
@@ -47,9 +47,18 @@ codespell = "*"
47
47
  pyshark = "^0.6"
48
48
 
49
49
  [tool.semantic_release]
50
- branch = "main"
51
50
  version_toml = ["pyproject.toml:tool.poetry.version"]
52
51
  build_command = "pip install poetry && poetry build"
52
+
53
+ [semantic_release.branches.main]
54
+ match = "release"
55
+ prerelease = false
56
+
57
+ [tool.semantic_release.branches.other]
58
+ match = ".*"
59
+ prerelease_token = "rc"
60
+ prerelease = true
61
+
53
62
  [tool.semantic_release.commit_parser_options]
54
63
  allowed_tags = [
55
64
  "chore",
@@ -7,7 +7,7 @@ import base64
7
7
  import logging
8
8
  import secrets
9
9
  import time
10
- from collections.abc import Coroutine
10
+ from collections.abc import Callable, Coroutine
11
11
  from typing import Any
12
12
 
13
13
  from .containers import (
@@ -36,8 +36,8 @@ class RoborockClient:
36
36
  self._endpoint = endpoint
37
37
  self._nonce = secrets.token_bytes(16)
38
38
  self._waiting_queue: dict[int, RoborockFuture] = {}
39
- self._last_device_msg_in = time.monotonic()
40
- self._last_disconnection = time.monotonic()
39
+ self._last_device_msg_in = self.time_func()
40
+ self._last_disconnection = self.time_func()
41
41
  self.keep_alive = KEEPALIVE
42
42
  self._diagnostic_data: dict[str, dict[str, Any]] = {
43
43
  "misc_info": {"Nonce": base64.b64encode(self._nonce).decode("utf-8")}
@@ -59,6 +59,15 @@ class RoborockClient:
59
59
  def diagnostic_data(self) -> dict:
60
60
  return self._diagnostic_data
61
61
 
62
+ @property
63
+ def time_func(self) -> Callable[[], float]:
64
+ try:
65
+ # Use monotonic clock if available
66
+ time_func = time.monotonic
67
+ except AttributeError:
68
+ time_func = time.time
69
+ return time_func
70
+
62
71
  async def async_connect(self):
63
72
  raise NotImplementedError
64
73
 
@@ -72,13 +81,13 @@ class RoborockClient:
72
81
  raise NotImplementedError
73
82
 
74
83
  def on_connection_lost(self, exc: Exception | None) -> None:
75
- self._last_disconnection = time.monotonic()
84
+ self._last_disconnection = self.time_func()
76
85
  self._logger.info("Roborock client disconnected")
77
86
  if exc is not None:
78
87
  self._logger.warning(exc)
79
88
 
80
89
  def should_keepalive(self) -> bool:
81
- now = time.monotonic()
90
+ now = self.time_func()
82
91
  # noinspection PyUnresolvedReferences
83
92
  if now - self._last_disconnection > self.keep_alive**2 and now - self._last_device_msg_in > self.keep_alive:
84
93
  return False
@@ -107,11 +116,8 @@ class RoborockClient:
107
116
  if request_id in self._waiting_queue:
108
117
  new_id = get_next_int(10000, 32767)
109
118
  _LOGGER.warning(
110
- "Attempting to create a future with an existing id %s (%s)... New id is %s. "
111
- "Code may not function properly.",
112
- request_id,
113
- protocol_id,
114
- new_id,
119
+ f"Attempting to create a future with an existing request_id... New id is {new_id}. "
120
+ f"Code may not function properly."
115
121
  )
116
122
  request_id = new_id
117
123
  self._waiting_queue[request_id] = queue
@@ -244,14 +244,12 @@ class RoborockFanSpeedQ7Max(RoborockFanPowerCode):
244
244
 
245
245
 
246
246
  class RoborockFanSpeedQRevoMaster(RoborockFanPowerCode):
247
- off = 105
248
247
  quiet = 101
249
248
  balanced = 102
250
249
  turbo = 103
251
250
  max = 104
252
- custom = 106
253
- max_plus = 108
254
- smart_mode = 110
251
+ max_plus = 105
252
+ custom = 110 # Smartplan
255
253
 
256
254
 
257
255
  class RoborockFanSpeedP10(RoborockFanPowerCode):
@@ -306,15 +304,6 @@ class RoborockMopModeS8MaxVUltra(RoborockMopModeCode):
306
304
  smart_mode = 306
307
305
 
308
306
 
309
- class RoborockMopModeQRevoMaster(RoborockMopModeCode):
310
- standard = 300
311
- deep = 301
312
- custom = 302
313
- deep_plus = 303
314
- fast = 304
315
- smart_mode = 306
316
-
317
-
318
307
  class RoborockMopIntensityCode(RoborockEnum):
319
308
  """Describes the mop intensity of the vacuum cleaner."""
320
309
 
@@ -346,9 +335,8 @@ class RoborockMopIntensityQRevoMaster(RoborockMopIntensityCode):
346
335
  low = 201
347
336
  medium = 202
348
337
  high = 203
349
- custom = 204
350
338
  custom_water_flow = 207
351
- smart_mode = 209
339
+ custom = 209 # SmartPlan
352
340
 
353
341
 
354
342
  class RoborockMopIntensityP10(RoborockMopIntensityCode):
@@ -429,7 +417,6 @@ class RoborockDockTypeCode(RoborockEnum):
429
417
  p10_dock = 8
430
418
  p10_pro_dock = 9
431
419
  s8_maxv_ultra_dock = 10
432
- qrevo_master_dock = 14
433
420
  qrevo_s_dock = 15
434
421
 
435
422
 
@@ -36,7 +36,6 @@ from .code_mappings import (
36
36
  RoborockMopIntensityS7,
37
37
  RoborockMopIntensityS8MaxVUltra,
38
38
  RoborockMopModeCode,
39
- RoborockMopModeQRevoMaster,
40
39
  RoborockMopModeS7,
41
40
  RoborockMopModeS8MaxVUltra,
42
41
  RoborockMopModeS8ProUltra,
@@ -142,12 +141,12 @@ class RoborockBase:
142
141
  cls_annotations.update(getattr(base, "__annotations__", {}))
143
142
  remove_keys = []
144
143
  for key, value in data.items():
145
- if key not in cls_annotations:
146
- remove_keys.append(key)
147
- continue
148
144
  if value == "None" or value is None:
149
145
  data[key] = None
150
146
  continue
147
+ if key not in cls_annotations:
148
+ remove_keys.append(key)
149
+ continue
151
150
  field_type: str = cls_annotations[key]
152
151
  if "|" in field_type:
153
152
  # It's a union
@@ -578,7 +577,6 @@ class Q7MaxStatus(Status):
578
577
  class QRevoMasterStatus(Status):
579
578
  fan_power: RoborockFanSpeedQRevoMaster | None = None
580
579
  water_box_mode: RoborockMopIntensityQRevoMaster | None = None
581
- mop_mode: RoborockMopModeQRevoMaster | None = None
582
580
 
583
581
 
584
582
  @dataclass
@@ -361,7 +361,7 @@ class RoborockClientV1(RoborockClient):
361
361
 
362
362
  def on_message_received(self, messages: list[RoborockMessage]) -> None:
363
363
  try:
364
- self._last_device_msg_in = time.monotonic()
364
+ self._last_device_msg_in = self.time_func()
365
365
  for data in messages:
366
366
  protocol = data.protocol
367
367
  if data.payload and protocol in [
@@ -391,8 +391,6 @@ class RoborockClientV1(RoborockClient):
391
391
  if isinstance(result, list) and len(result) == 1:
392
392
  result = result[0]
393
393
  queue.resolve((result, None))
394
- else:
395
- self._logger.debug("Received response for unknown request id %s", request_id)
396
394
  else:
397
395
  try:
398
396
  data_protocol = RoborockDataProtocol(int(data_point_number))
@@ -445,14 +443,10 @@ class RoborockClientV1(RoborockClient):
445
443
  if isinstance(decompressed, list):
446
444
  decompressed = decompressed[0]
447
445
  queue.resolve((decompressed, None))
448
- else:
449
- self._logger.debug("Received response for unknown request id %s", request_id)
450
446
  else:
451
447
  queue = self._waiting_queue.get(data.seq)
452
448
  if queue:
453
449
  queue.resolve((data.payload, None))
454
- else:
455
- self._logger.debug("Received response for unknown request id %s", data.seq)
456
450
  except Exception as ex:
457
451
  self._logger.exception(ex)
458
452
 
@@ -18,7 +18,6 @@ class RoborockLocalClientV1(RoborockLocalClient, RoborockClientV1):
18
18
  ) -> RoborockMessage:
19
19
  secured = True if method in COMMANDS_SECURED else False
20
20
  request_id, timestamp, payload = self._get_payload(method, params, secured)
21
- self._logger.debug("Building message id %s for method %s", request_id, method)
22
21
  request_protocol = RoborockMessageProtocol.GENERAL_REQUEST
23
22
  message_retry: MessageRetry | None = None
24
23
  if method == RoborockCommand.RETRY_REQUEST and isinstance(params, dict):
@@ -74,7 +74,6 @@ class RoborockMqttClientV1(RoborockMqttClient, RoborockClientV1):
74
74
  # When we have more custom commands do something more complicated here
75
75
  return await self._get_calibration_points()
76
76
  request_id, timestamp, payload = self._get_payload(method, params, True)
77
- self._logger.debug("Building message id %s for method %s", request_id, method)
78
77
  request_protocol = RoborockMessageProtocol.RPC_REQUEST
79
78
  roborock_message = RoborockMessage(timestamp=timestamp, protocol=request_protocol, payload=payload)
80
79
  return await self.send_message(roborock_message)