python-roborock 4.15.0__tar.gz → 4.16.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.
Files changed (97) hide show
  1. {python_roborock-4.15.0 → python_roborock-4.16.0}/PKG-INFO +1 -1
  2. {python_roborock-4.15.0 → python_roborock-4.16.0}/pyproject.toml +1 -1
  3. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q10/common.py +34 -1
  4. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q10/status.py +5 -14
  5. {python_roborock-4.15.0 → python_roborock-4.16.0}/.gitignore +0 -0
  6. {python_roborock-4.15.0 → python_roborock-4.16.0}/LICENSE +0 -0
  7. {python_roborock-4.15.0 → python_roborock-4.16.0}/README.md +0 -0
  8. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/__init__.py +0 -0
  9. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/broadcast_protocol.py +0 -0
  10. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/callbacks.py +0 -0
  11. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/cli.py +0 -0
  12. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/const.py +0 -0
  13. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/__init__.py +0 -0
  14. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q10/__init__.py +0 -0
  15. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
  16. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
  17. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q7/__init__.py +0 -0
  18. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
  19. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
  20. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/code_mappings.py +0 -0
  21. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/containers.py +0 -0
  22. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/dyad/__init__.py +0 -0
  23. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
  24. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/dyad/dyad_containers.py +0 -0
  25. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/v1/__init__.py +0 -0
  26. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/v1/v1_clean_modes.py +0 -0
  27. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/v1/v1_code_mappings.py +0 -0
  28. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/v1/v1_containers.py +0 -0
  29. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/zeo/__init__.py +0 -0
  30. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
  31. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/data/zeo/zeo_containers.py +0 -0
  32. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/device_features.py +0 -0
  33. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/README.md +0 -0
  34. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/__init__.py +0 -0
  35. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/cache.py +0 -0
  36. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/device.py +0 -0
  37. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/device_manager.py +0 -0
  38. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/file_cache.py +0 -0
  39. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/rpc/__init__.py +0 -0
  40. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/rpc/a01_channel.py +0 -0
  41. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
  42. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
  43. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/rpc/v1_channel.py +0 -0
  44. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/__init__.py +0 -0
  45. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/a01/__init__.py +0 -0
  46. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/__init__.py +0 -0
  47. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
  48. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q10/command.py +0 -0
  49. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
  50. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
  51. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
  52. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/traits_mixin.py +0 -0
  53. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/__init__.py +0 -0
  54. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/child_lock.py +0 -0
  55. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
  56. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/command.py +0 -0
  57. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/common.py +0 -0
  58. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/consumeable.py +0 -0
  59. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/device_features.py +0 -0
  60. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
  61. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
  62. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
  63. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/home.py +0 -0
  64. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/led_status.py +0 -0
  65. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/map_content.py +0 -0
  66. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/maps.py +0 -0
  67. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/network_info.py +0 -0
  68. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/rooms.py +0 -0
  69. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/routines.py +0 -0
  70. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
  71. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/status.py +0 -0
  72. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
  73. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/volume.py +0 -0
  74. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
  75. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/transport/__init__.py +0 -0
  76. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/transport/channel.py +0 -0
  77. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/transport/local_channel.py +0 -0
  78. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/devices/transport/mqtt_channel.py +0 -0
  79. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/diagnostics.py +0 -0
  80. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/exceptions.py +0 -0
  81. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/map/__init__.py +0 -0
  82. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/map/map_parser.py +0 -0
  83. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/mqtt/__init__.py +0 -0
  84. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/mqtt/health_manager.py +0 -0
  85. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/mqtt/roborock_session.py +0 -0
  86. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/mqtt/session.py +0 -0
  87. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocol.py +0 -0
  88. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocols/__init__.py +0 -0
  89. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocols/a01_protocol.py +0 -0
  90. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocols/b01_q10_protocol.py +0 -0
  91. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocols/b01_q7_protocol.py +0 -0
  92. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/protocols/v1_protocol.py +0 -0
  93. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/py.typed +0 -0
  94. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/roborock_message.py +0 -0
  95. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/roborock_typing.py +0 -0
  96. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/util.py +0 -0
  97. {python_roborock-4.15.0 → python_roborock-4.16.0}/roborock/web_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-roborock
3
- Version: 4.15.0
3
+ Version: 4.16.0
4
4
  Summary: A package to control Roborock vacuums.
5
5
  Project-URL: Repository, https://github.com/humbertogontijo/python-roborock
6
6
  Project-URL: Documentation, https://python-roborock.readthedocs.io/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-roborock"
3
- version = "4.15.0"
3
+ version = "4.16.0"
4
4
  description = "A package to control Roborock vacuums."
5
5
  authors = [{ name = "humbertogontijo", email = "humbertogontijo@users.noreply.github.com" }, {name="Lash-L"}, {name="allenporter"}]
6
6
  requires-python = ">=3.11, <4"
@@ -36,12 +36,41 @@ and call `update_from_dps` whenever new data is received from the device stream.
36
36
  """
37
37
 
38
38
  import dataclasses
39
+ import logging
40
+ from collections.abc import Callable
39
41
  from typing import Any
40
42
 
43
+ from roborock.callbacks import CallbackList
41
44
  from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
42
45
  from roborock.data.containers import RoborockBase
43
46
 
44
47
 
48
+ class TraitUpdateListener:
49
+ """Trait update listener.
50
+
51
+ This is a base class for traits to support notifying listeners when they
52
+ have been updated. Clients may register callbacks to be notified when the
53
+ trait has been updated. When the listener callback is invoked, the client
54
+ should read the trait's properties to get the updated values.
55
+ """
56
+
57
+ def __init__(self, logger: logging.Logger) -> None:
58
+ """Initialize the trait update listener."""
59
+ self._update_callbacks: CallbackList[None] = CallbackList(logger=logger)
60
+
61
+ def add_update_listener(self, callback: Callable[[], None]) -> Callable[[], None]:
62
+ """Register a callback when the trait has been updated.
63
+
64
+ Returns a callable to remove the listener.
65
+ """
66
+ # We wrap the callback to ignore the value passed to it.
67
+ return self._update_callbacks.add_callback(lambda _: callback())
68
+
69
+ def _notify_update(self) -> None:
70
+ """Notify all update listeners."""
71
+ self._update_callbacks(None)
72
+
73
+
45
74
  class DpsDataConverter:
46
75
  """Utility to handle the transformation and merging of DPS data into models.
47
76
 
@@ -66,7 +95,7 @@ class DpsDataConverter:
66
95
  dps_field_map[dps_id] = field_obj.name
67
96
  return cls(dps_type_map, dps_field_map)
68
97
 
69
- def update_from_dps(self, target: RoborockBase, decoded_dps: dict[B01_Q10_DP, Any]) -> None:
98
+ def update_from_dps(self, target: RoborockBase, decoded_dps: dict[B01_Q10_DP, Any]) -> bool:
70
99
  """Convert and merge raw DPS data into the target object.
71
100
 
72
101
  Uses the pre-calculated type mapping to ensure values are converted to the
@@ -75,8 +104,12 @@ class DpsDataConverter:
75
104
  Args:
76
105
  target: The target object to update.
77
106
  decoded_dps: The decoded DPS data to convert.
107
+
108
+ Returns:
109
+ True if any values were updated, False otherwise.
78
110
  """
79
111
  conversions = RoborockBase.convert_dict(self._dps_type_map, decoded_dps)
80
112
  for dps_id, value in conversions.items():
81
113
  field_name = self._dps_field_map[dps_id]
82
114
  setattr(target, field_name, value)
115
+ return bool(conversions)
@@ -1,21 +1,19 @@
1
1
  """Status trait for Q10 B01 devices."""
2
2
 
3
3
  import logging
4
- from collections.abc import Callable
5
4
  from typing import Any
6
5
 
7
- from roborock.callbacks import CallbackList
8
6
  from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
9
7
  from roborock.data.b01_q10.b01_q10_containers import Q10Status
10
8
 
11
- from .common import DpsDataConverter
9
+ from .common import DpsDataConverter, TraitUpdateListener
12
10
 
13
11
  _LOGGER = logging.getLogger(__name__)
14
12
 
15
13
  _CONVERTER = DpsDataConverter.from_dataclass(Q10Status)
16
14
 
17
15
 
18
- class StatusTrait(Q10Status):
16
+ class StatusTrait(Q10Status, TraitUpdateListener):
19
17
  """Trait for managing the status of Q10 Roborock devices.
20
18
 
21
19
  This is a thin wrapper around Q10Status that provides the Trait interface.
@@ -26,16 +24,9 @@ class StatusTrait(Q10Status):
26
24
  def __init__(self) -> None:
27
25
  """Initialize the status trait."""
28
26
  super().__init__()
29
- self._update_callbacks: CallbackList[dict[B01_Q10_DP, Any]] = CallbackList(logger=_LOGGER)
30
-
31
- def add_update_listener(self, callback: Callable[[dict[B01_Q10_DP, Any]], None]) -> Callable[[], None]:
32
- """Register a callback for decoded DPS updates.
33
-
34
- Returns a callable to remove the listener.
35
- """
36
- return self._update_callbacks.add_callback(callback)
27
+ TraitUpdateListener.__init__(self, logger=_LOGGER)
37
28
 
38
29
  def update_from_dps(self, decoded_dps: dict[B01_Q10_DP, Any]) -> None:
39
30
  """Update the trait from raw DPS data."""
40
- _CONVERTER.update_from_dps(self, decoded_dps)
41
- self._update_callbacks(decoded_dps)
31
+ if _CONVERTER.update_from_dps(self, decoded_dps):
32
+ self._notify_update()