python-roborock 3.1.2__tar.gz → 3.2.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 (93) hide show
  1. {python_roborock-3.1.2 → python_roborock-3.2.0}/PKG-INFO +1 -1
  2. {python_roborock-3.1.2 → python_roborock-3.2.0}/pyproject.toml +1 -1
  3. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/device.py +40 -1
  4. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/__init__.py +13 -1
  5. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/device_features.py +5 -0
  6. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/network_info.py +1 -0
  7. {python_roborock-3.1.2 → python_roborock-3.2.0}/.gitignore +0 -0
  8. {python_roborock-3.1.2 → python_roborock-3.2.0}/LICENSE +0 -0
  9. {python_roborock-3.1.2 → python_roborock-3.2.0}/README.md +0 -0
  10. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/__init__.py +0 -0
  11. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/api.py +0 -0
  12. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/broadcast_protocol.py +0 -0
  13. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/callbacks.py +0 -0
  14. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/cli.py +0 -0
  15. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/cloud_api.py +0 -0
  16. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/command_cache.py +0 -0
  17. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/const.py +0 -0
  18. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/__init__.py +0 -0
  19. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q10/__init__.py +0 -0
  20. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
  21. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
  22. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q7/__init__.py +0 -0
  23. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
  24. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
  25. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/code_mappings.py +0 -0
  26. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/containers.py +0 -0
  27. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/dyad/__init__.py +0 -0
  28. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
  29. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/dyad/dyad_containers.py +0 -0
  30. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/v1/__init__.py +0 -0
  31. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/v1/v1_clean_modes.py +0 -0
  32. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/v1/v1_code_mappings.py +0 -0
  33. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/v1/v1_containers.py +0 -0
  34. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/zeo/__init__.py +0 -0
  35. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
  36. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/data/zeo/zeo_containers.py +0 -0
  37. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/device_features.py +0 -0
  38. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/README.md +0 -0
  39. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/__init__.py +0 -0
  40. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/a01_channel.py +0 -0
  41. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/b01_channel.py +0 -0
  42. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/cache.py +0 -0
  43. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/channel.py +0 -0
  44. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/device_manager.py +0 -0
  45. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/local_channel.py +0 -0
  46. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/mqtt_channel.py +0 -0
  47. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/__init__.py +0 -0
  48. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/a01/__init__.py +0 -0
  49. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/b01/__init__.py +0 -0
  50. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/traits_mixin.py +0 -0
  51. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/child_lock.py +0 -0
  52. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
  53. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/command.py +0 -0
  54. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/common.py +0 -0
  55. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/consumeable.py +0 -0
  56. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
  57. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
  58. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
  59. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/home.py +0 -0
  60. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/led_status.py +0 -0
  61. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/map_content.py +0 -0
  62. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/maps.py +0 -0
  63. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/rooms.py +0 -0
  64. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
  65. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/status.py +0 -0
  66. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
  67. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/volume.py +0 -0
  68. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
  69. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/v1_channel.py +0 -0
  70. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/devices/v1_rpc_channel.py +0 -0
  71. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/exceptions.py +0 -0
  72. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/map/__init__.py +0 -0
  73. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/map/map_parser.py +0 -0
  74. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/mqtt/__init__.py +0 -0
  75. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/mqtt/roborock_session.py +0 -0
  76. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/mqtt/session.py +0 -0
  77. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/protocol.py +0 -0
  78. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/protocols/a01_protocol.py +0 -0
  79. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/protocols/b01_protocol.py +0 -0
  80. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/protocols/v1_protocol.py +0 -0
  81. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/py.typed +0 -0
  82. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/roborock_future.py +0 -0
  83. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/roborock_message.py +0 -0
  84. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/roborock_typing.py +0 -0
  85. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/util.py +0 -0
  86. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_1_apis/__init__.py +0 -0
  87. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_1_apis/roborock_client_v1.py +0 -0
  88. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
  89. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
  90. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_a01_apis/__init__.py +0 -0
  91. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
  92. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
  93. {python_roborock-3.1.2 → python_roborock-3.2.0}/roborock/web_api.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-roborock
3
- Version: 3.1.2
3
+ Version: 3.2.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 = "3.1.2"
3
+ version = "3.2.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"
@@ -6,7 +6,8 @@ until the API is stable.
6
6
 
7
7
  import logging
8
8
  from abc import ABC
9
- from collections.abc import Callable
9
+ from collections.abc import Callable, Mapping
10
+ from typing import Any, TypeVar, cast
10
11
 
11
12
  from roborock.data import HomeDataDevice, HomeDataProduct
12
13
  from roborock.roborock_message import RoborockMessage
@@ -113,3 +114,41 @@ class RoborockDevice(ABC, TraitsMixin):
113
114
  def _on_message(self, message: RoborockMessage) -> None:
114
115
  """Handle incoming messages from the device."""
115
116
  _LOGGER.debug("Received message from device: %s", message)
117
+
118
+ def diagnostic_data(self) -> dict[str, Any]:
119
+ """Return diagnostics information about the device."""
120
+ extra: dict[str, Any] = {}
121
+ if self.v1_properties:
122
+ extra["traits"] = _redact_data(self.v1_properties.as_dict())
123
+ return {
124
+ "device": _redact_data(self.device_info.as_dict()),
125
+ "product": _redact_data(self.product.as_dict()),
126
+ **extra,
127
+ }
128
+
129
+
130
+ T = TypeVar("T")
131
+
132
+ REDACT_KEYS = {"duid", "localKey", "mac", "bssid", "sn", "ip"}
133
+ REDACTED = "**REDACTED**"
134
+
135
+
136
+ def _redact_data(data: T) -> T | dict[str, Any]:
137
+ """Redact sensitive data in a dict."""
138
+ if not isinstance(data, (Mapping, list)):
139
+ return data
140
+
141
+ if isinstance(data, list):
142
+ return cast(T, [_redact_data(item) for item in data])
143
+
144
+ redacted = {**data}
145
+
146
+ for key, value in redacted.items():
147
+ if key in REDACT_KEYS:
148
+ redacted[key] = REDACTED
149
+ elif isinstance(value, dict):
150
+ redacted[key] = _redact_data(value)
151
+ elif isinstance(value, list):
152
+ redacted[key] = [_redact_data(item) for item in value]
153
+
154
+ return redacted
@@ -34,7 +34,7 @@ import logging
34
34
  from dataclasses import dataclass, field, fields
35
35
  from typing import Any, get_args
36
36
 
37
- from roborock.data.containers import HomeData, HomeDataProduct
37
+ from roborock.data.containers import HomeData, HomeDataProduct, RoborockBase
38
38
  from roborock.data.v1.v1_code_mappings import RoborockDockTypeCode
39
39
  from roborock.devices.cache import Cache
40
40
  from roborock.devices.traits import Trait
@@ -247,6 +247,18 @@ class PropertiesApi(Trait):
247
247
  _LOGGER.debug("Updating cached trait data: %s", cache_data.trait_data)
248
248
  await self._cache.set(cache_data)
249
249
 
250
+ def as_dict(self) -> dict[str, Any]:
251
+ """Return the trait data as a dictionary."""
252
+ result: dict[str, Any] = {}
253
+ for item in fields(self):
254
+ trait = getattr(self, item.name, None)
255
+ if trait is None or not isinstance(trait, RoborockBase):
256
+ continue
257
+ data = trait.as_dict()
258
+ if data: # Don't omit unset traits
259
+ result[item.name] = data
260
+ return result
261
+
250
262
 
251
263
  def create(
252
264
  device_uid: str,
@@ -1,3 +1,4 @@
1
+ from dataclasses import fields
1
2
  from typing import Self
2
3
 
3
4
  from roborock.data import AppInitStatus, RoborockProductNickname
@@ -16,6 +17,10 @@ class DeviceFeaturesTrait(DeviceFeatures, common.V1TraitMixin):
16
17
  """Initialize MapContentTrait."""
17
18
  self._nickname = product_nickname
18
19
  self._cache = cache
20
+ # All fields of DeviceFeatures are required. Initialize them to False
21
+ # so we have some known state.
22
+ for field in fields(self):
23
+ setattr(self, field.name, False)
19
24
 
20
25
  async def refresh(self) -> Self:
21
26
  """Refresh the contents of this trait.
@@ -29,6 +29,7 @@ class NetworkInfoTrait(NetworkInfo, common.V1TraitMixin):
29
29
  """Initialize the trait."""
30
30
  self._device_uid = device_uid
31
31
  self._cache = cache
32
+ self.ip = ""
32
33
 
33
34
  async def refresh(self) -> Self:
34
35
  """Refresh the network info from the cache."""
File without changes