python-roborock 7.2.0__py3-none-any.whl → 7.2.2__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-roborock
3
- Version: 7.2.0
3
+ Version: 7.2.2
4
4
  Summary: A package to control Roborock vacuums.
5
5
  Project-URL: Repository, https://github.com/python-roborock/python-roborock
6
6
  Project-URL: Documentation, https://python-roborock.readthedocs.io/
@@ -3,7 +3,7 @@ roborock/broadcast_protocol.py,sha256=fjNQW7NdBKRzSy6126TfCSoYGpT2Esj9Jd-t7tXFc_
3
3
  roborock/callbacks.py,sha256=w2yPXtWFH7zfoFsLPYoCTbfwbE9p1ivA7iDcw20lJQI,4300
4
4
  roborock/cli.py,sha256=3OrJAmd9c52cyKLC9jF4-O5UkVXJAWZilOzvnxP7jyc,64097
5
5
  roborock/const.py,sha256=fWpgUPrCgLnaXmncgjCLZET-t7wHWQlpyzV8qHtTjb4,2860
6
- roborock/device_features.py,sha256=i4YrJUfS8ZPB8azK8grAiBxoLS2MyGJcdwOvGtnUuFg,45866
6
+ roborock/device_features.py,sha256=EbMvw4vz0HvN23x9stj5CfNu45HE1tqg4HyygAzkU5Q,46753
7
7
  roborock/diagnostics.py,sha256=OVfPCjBVidAlQtFz-WRlgCWOBIaXlO-73xQloXJaLwI,5107
8
8
  roborock/exceptions.py,sha256=t2YvfSRMymZPtdPV238itjxVJTaTq5-uBL_EM5FTlfg,3159
9
9
  roborock/protocol.py,sha256=eNUL6UGmtSdfsGM1mlYjmorukGGudV45iKXUA7a-Qa8,20193
@@ -103,7 +103,7 @@ roborock/map/b01_grid_layers.py,sha256=VluAmKEIBTsvzGB5pUrr8iYFiyEx5siyDwBKft1C2
103
103
  roborock/map/b01_map_parser.py,sha256=tTeeWH4fA4Pv4DvqN7PBQs92DuWTaD2rvD44Mo_t3OY,4433
104
104
  roborock/map/b01_q10_map_parser.py,sha256=EQMx2ZNVjHKsmKr6vR8JS7o86IZu85dNg3bKi5S0ZYw,29985
105
105
  roborock/map/b01_q10_overlays.py,sha256=JmriUbT4-oe6NiE94VttMplFc1HHQrAGNQIiZHj5QKk,6640
106
- roborock/map/b01_q10_render.py,sha256=0K7x5AErSaowAH3ZUkStUXFgH4GM0debu0jIEJhlgVk,13360
106
+ roborock/map/b01_q10_render.py,sha256=b7YUBr53WXxOJhXbfb5IVmgi82iGcC0lJ_j9Ef3kV7M,13502
107
107
  roborock/map/map_parser.py,sha256=2Rse_VhC2HEfjO2aXw7p-QhYN3NLl9JoRbxqxGGPR64,7275
108
108
  roborock/map/room_colors.py,sha256=5Q85oR_7xsUyzHYGOJPuzsZ6LQSCpJwfxfWql1v6T1E,2152
109
109
  roborock/map/proto/__init__.py,sha256=XcH_s-E67_hcQNwqSkdtY7DgYE0mRBBJwctzsf8zng4,60
@@ -125,8 +125,8 @@ roborock/testing/channel.py,sha256=vjulT5MHBe8lAq6XITUqcxJVcCILWx7ZEcw5imTx0Tk,7
125
125
  roborock/testing/cloud.py,sha256=L2L0KlZDYaMuoV19KUQUoq5EAUDeNQ1lJ8Ew5YaOgjo,11946
126
126
  roborock/testing/simulator.py,sha256=g8ZUWVSjgAzuRRxWOCeOq-7deodyEItwUpqEw9RzCmQ,4347
127
127
  roborock/testing/v1_simulator.py,sha256=TQ2PsRoP_4kJvVn-Tm532ByHuaCKltsVjvTa2Ju4PAo,14407
128
- python_roborock-7.2.0.dist-info/METADATA,sha256=FIUbTM4uQDYeOtX_WjwGgRQz7MqfiYsDlQFlNGQsZoM,5278
129
- python_roborock-7.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
130
- python_roborock-7.2.0.dist-info/entry_points.txt,sha256=EvC1nMqi9ZXKgZnqlNXA33v_3nzgPNjnM0mzWlrehnY,47
131
- python_roborock-7.2.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
132
- python_roborock-7.2.0.dist-info/RECORD,,
128
+ python_roborock-7.2.2.dist-info/METADATA,sha256=vTfS-_x5Ut3raIemhgfVUN--QARO-jlmV5Ft9Fr0Xrs,5278
129
+ python_roborock-7.2.2.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
130
+ python_roborock-7.2.2.dist-info/entry_points.txt,sha256=EvC1nMqi9ZXKgZnqlNXA33v_3nzgPNjnM0mzWlrehnY,47
131
+ python_roborock-7.2.2.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
132
+ python_roborock-7.2.2.dist-info/RECORD,,
@@ -4,7 +4,7 @@ from functools import cache
4
4
  from typing import Any, Self
5
5
 
6
6
  from roborock.data.code_mappings import RoborockProductNickname
7
- from roborock.data.containers import RoborockBase
7
+ from roborock.data.containers import RoborockBase, _decamelize
8
8
  from roborock.data.v1 import RoborockDockTypeCode
9
9
 
10
10
 
@@ -654,6 +654,26 @@ class DeviceFeatures(RoborockBase):
654
654
 
655
655
  return cls(**kwargs)
656
656
 
657
+ @classmethod
658
+ def from_dict(cls, data: dict[str, Any]) -> Self | None:
659
+ """Create device features, rejecting incomplete cached capabilities.
660
+
661
+ Persisted feature data may have been written by an older version of the
662
+ library that did not yet know about every capability. Missing boolean
663
+ fields therefore mean the cached feature set is stale, not that those
664
+ capabilities are unsupported. Return ``None`` so callers rediscover the
665
+ complete feature set from the device.
666
+ """
667
+ if not isinstance(data, dict):
668
+ return None
669
+
670
+ serialized_fields = {_decamelize(key) for key in data}
671
+ required_fields = {feature.name for feature in fields(cls) if feature.type is bool}
672
+ if not required_fields.issubset(serialized_fields):
673
+ return None
674
+
675
+ return super().from_dict(data)
676
+
657
677
  def get_supported_features(self) -> list[str]:
658
678
  """Returns a list of supported features (Primarily used for logging purposes)."""
659
679
  return [k for k, v in vars(self).items() if v]
@@ -185,8 +185,10 @@ def _vector_calibration(
185
185
  trace_calibration: GridCalibration | None,
186
186
  ) -> GridCalibration | None:
187
187
  """Derive the 5 mm erase/restriction-vector transform."""
188
- y_sign = trace_calibration.y_sign if trace_calibration is not None else 1
189
- if calibration := _calibration_from_header_metadata(packet, y_sign=y_sign):
188
+ # Header vectors share the map packet's fixed top-down coordinate frame.
189
+ # A trace fit may choose either Y orientation, but that must not move saved
190
+ # erase/restriction geometry when a cleaning trace appears or disappears.
191
+ if calibration := _calibration_from_header_metadata(packet):
190
192
  return calibration
191
193
  if trace_calibration is None:
192
194
  return None