python-roborock 5.27.0__tar.gz → 5.28.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.
- {python_roborock-5.27.0 → python_roborock-5.28.0}/PKG-INFO +1 -1
- {python_roborock-5.27.0 → python_roborock-5.28.0}/pyproject.toml +1 -1
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/v1/v1_code_mappings.py +25 -16
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/v1/v1_containers.py +12 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/device_features.py +207 -12
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/__init__.py +18 -9
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/dust_collection_mode.py +6 -2
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/smart_wash_params.py +6 -2
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/wash_towel_mode.py +6 -2
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/testing/v1_simulator.py +1 -1
- {python_roborock-5.27.0 → python_roborock-5.28.0}/.gitignore +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/LICENSE +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/README.md +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/callbacks.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/cli.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/const.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q10/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q7/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/code_mappings.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/dyad/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/dyad/dyad_containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/mower/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/mower/mower_containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/v1/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/v1/v1_clean_modes.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/zeo/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/zeo/zeo_containers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/README.md +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/cache.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/device.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/device_manager.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/file_cache.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/rpc/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/rpc/a01_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/rpc/v1_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/a01/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/button_light.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/child_lock.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/clean_history.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/command.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/common.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/consumable.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/do_not_disturb.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/dust_collection.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/map.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/network_info.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/remote.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/status.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/volume.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/map.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/map_content.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/common.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/traits_mixin.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/child_lock.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/command.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/common.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/consumeable.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/device_features.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/home.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/led_status.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/map_content.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/maps.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/network_info.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/rooms.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/routines.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/status.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/volume.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/local_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/mqtt_channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/diagnostics.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/exceptions.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/b01_grid_layers.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/b01_map_parser.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/b01_q10_map_parser.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/b01_q10_overlays.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/map_parser.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/proto/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/proto/b01_scmap.proto +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/map/proto/b01_scmap_pb2.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/mqtt/health_manager.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocols/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocols/b01_q10_protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocols/b01_q7_protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/py.typed +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/roborock_message.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/testing/__init__.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/testing/channel.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/testing/cloud.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/testing/simulator.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/util.py +0 -0
- {python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/web_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.28.0
|
|
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/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "5.
|
|
3
|
+
version = "5.28.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"
|
|
@@ -650,22 +650,31 @@ class RoborockDockErrorCode(RoborockEnum):
|
|
|
650
650
|
|
|
651
651
|
class RoborockDockTypeCode(RoborockEnum):
|
|
652
652
|
unknown = -9999
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
653
|
+
o0_dock = 0
|
|
654
|
+
o1_dock = 1
|
|
655
|
+
o2_dock = 2
|
|
656
|
+
o3_dock = 3
|
|
657
|
+
oc_dock = 5
|
|
658
|
+
o3_plus_dock = 6
|
|
659
|
+
o4_dock = 7
|
|
660
|
+
pearl_dock = 8
|
|
661
|
+
pearl_plus_dock = 9
|
|
662
|
+
o5_dock = 10
|
|
663
|
+
shell_2s_dock = 11
|
|
664
|
+
couple_dock = 13
|
|
665
|
+
shell_3_dock = 14
|
|
666
|
+
shell_2c_dock = 15
|
|
667
|
+
shell_3s_dock = 16
|
|
668
|
+
k1_dock = 17
|
|
669
|
+
o6_dock = 18
|
|
670
|
+
k1c_dock = 19
|
|
671
|
+
k1s_dock = 20
|
|
672
|
+
shell_e_dock = 21
|
|
673
|
+
shell_2e_dock = 22
|
|
674
|
+
shell_3c_dock = 23
|
|
675
|
+
type_27_dock = 27
|
|
676
|
+
k1c_lite_dock = 28
|
|
677
|
+
shell_2e_lite_dock = 30
|
|
669
678
|
|
|
670
679
|
|
|
671
680
|
class RoborockDockDustCollectionModeCode(RoborockEnum):
|
|
@@ -239,6 +239,12 @@ class Status(RoborockBase):
|
|
|
239
239
|
return map_flag
|
|
240
240
|
return None
|
|
241
241
|
|
|
242
|
+
@property
|
|
243
|
+
def has_am(self) -> bool | None:
|
|
244
|
+
if self.dss is None:
|
|
245
|
+
return None
|
|
246
|
+
return (self.dss & 3) == 2
|
|
247
|
+
|
|
242
248
|
@property
|
|
243
249
|
def clear_water_box_status(self) -> ClearWaterBoxStatus | None:
|
|
244
250
|
if self.dss:
|
|
@@ -376,6 +382,12 @@ class StatusV2(RoborockBase):
|
|
|
376
382
|
return map_flag
|
|
377
383
|
return None
|
|
378
384
|
|
|
385
|
+
@property
|
|
386
|
+
def has_am(self) -> bool | None:
|
|
387
|
+
if self.dss is None:
|
|
388
|
+
return None
|
|
389
|
+
return (self.dss & 3) == 2
|
|
390
|
+
|
|
379
391
|
@property
|
|
380
392
|
def clear_water_box_status(self) -> ClearWaterBoxStatus | None:
|
|
381
393
|
if self.dss:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass, field, fields
|
|
2
2
|
from enum import IntEnum, StrEnum
|
|
3
|
+
from functools import cache
|
|
3
4
|
from typing import Any, Self
|
|
4
5
|
|
|
5
6
|
from roborock.data.code_mappings import RoborockProductNickname
|
|
@@ -644,25 +645,219 @@ class DeviceFeatures(RoborockBase):
|
|
|
644
645
|
return [k for k, v in vars(self).items() if v]
|
|
645
646
|
|
|
646
647
|
|
|
648
|
+
_NO_DOCK_TYPES = {
|
|
649
|
+
RoborockDockTypeCode.unknown,
|
|
650
|
+
RoborockDockTypeCode.o0_dock,
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
_PURE_COLLECT_DOCK_TYPES = {
|
|
654
|
+
RoborockDockTypeCode.o1_dock,
|
|
655
|
+
RoborockDockTypeCode.oc_dock,
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
_PURE_WASH_DOCK_TYPES = {
|
|
659
|
+
RoborockDockTypeCode.o2_dock,
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
_COLLECT_WASH_DOCK_TYPES = {
|
|
663
|
+
RoborockDockTypeCode.o3_dock,
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
_ONLY_X_SERIES_DOCK_TYPES = {
|
|
667
|
+
RoborockDockTypeCode.o2_dock,
|
|
668
|
+
RoborockDockTypeCode.o3_dock,
|
|
669
|
+
RoborockDockTypeCode.o3_plus_dock,
|
|
670
|
+
RoborockDockTypeCode.o4_dock,
|
|
671
|
+
RoborockDockTypeCode.o5_dock,
|
|
672
|
+
RoborockDockTypeCode.o6_dock,
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
_CLEAN_FLUID_AUTO_DELIVERY_DOCK_TYPES = {
|
|
676
|
+
RoborockDockTypeCode.o4_dock,
|
|
677
|
+
RoborockDockTypeCode.pearl_plus_dock,
|
|
678
|
+
RoborockDockTypeCode.shell_3s_dock,
|
|
679
|
+
RoborockDockTypeCode.o6_dock,
|
|
680
|
+
RoborockDockTypeCode.couple_dock,
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
_CLEAN_FLUID_AUTO_DELIVERY_AM_DOCK_TYPES = {
|
|
684
|
+
RoborockDockTypeCode.o5_dock,
|
|
685
|
+
RoborockDockTypeCode.shell_2s_dock,
|
|
686
|
+
RoborockDockTypeCode.shell_3_dock,
|
|
687
|
+
RoborockDockTypeCode.shell_2c_dock,
|
|
688
|
+
RoborockDockTypeCode.k1_dock,
|
|
689
|
+
RoborockDockTypeCode.k1s_dock,
|
|
690
|
+
RoborockDockTypeCode.shell_e_dock,
|
|
691
|
+
RoborockDockTypeCode.shell_2e_dock,
|
|
692
|
+
RoborockDockTypeCode.shell_3c_dock,
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
_AUTO_STERILIZE_DOCK_TYPES = {
|
|
696
|
+
RoborockDockTypeCode.shell_3s_dock,
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
_INNER_CHARGE_HEAD_DOCK_TYPES = {
|
|
700
|
+
RoborockDockTypeCode.o0_dock,
|
|
701
|
+
RoborockDockTypeCode.o1_dock,
|
|
702
|
+
RoborockDockTypeCode.oc_dock,
|
|
703
|
+
RoborockDockTypeCode.o2_dock,
|
|
704
|
+
RoborockDockTypeCode.o3_dock,
|
|
705
|
+
RoborockDockTypeCode.o3_plus_dock,
|
|
706
|
+
RoborockDockTypeCode.o4_dock,
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
_DUST_BUCKET_DOCK_TYPES = {
|
|
710
|
+
RoborockDockTypeCode.o3_dock,
|
|
711
|
+
RoborockDockTypeCode.o3_plus_dock,
|
|
712
|
+
RoborockDockTypeCode.o4_dock,
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
_CLEAN_CAROUSEL_SELF_CLEAN_DOCK_TYPES = {
|
|
716
|
+
RoborockDockTypeCode.shell_3_dock,
|
|
717
|
+
RoborockDockTypeCode.k1_dock,
|
|
718
|
+
RoborockDockTypeCode.couple_dock,
|
|
719
|
+
RoborockDockTypeCode.shell_3s_dock,
|
|
720
|
+
RoborockDockTypeCode.k1s_dock,
|
|
721
|
+
RoborockDockTypeCode.shell_3c_dock,
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
_WATER_UPDOWN_DRAIN_DOCK_TYPES = {
|
|
725
|
+
RoborockDockTypeCode.o4_dock,
|
|
726
|
+
RoborockDockTypeCode.pearl_plus_dock,
|
|
727
|
+
RoborockDockTypeCode.couple_dock,
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
_WATER_UPDOWN_DRAIN_AM_DOCK_TYPES = {
|
|
731
|
+
RoborockDockTypeCode.o5_dock,
|
|
732
|
+
RoborockDockTypeCode.shell_2s_dock,
|
|
733
|
+
RoborockDockTypeCode.shell_3_dock,
|
|
734
|
+
RoborockDockTypeCode.shell_2c_dock,
|
|
735
|
+
RoborockDockTypeCode.shell_3s_dock,
|
|
736
|
+
RoborockDockTypeCode.k1_dock,
|
|
737
|
+
RoborockDockTypeCode.o6_dock,
|
|
738
|
+
RoborockDockTypeCode.shell_e_dock,
|
|
739
|
+
RoborockDockTypeCode.shell_2e_dock,
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
_HATCH_DOOR_DOCK_COOL_FAN_DOCK_TYPES = {
|
|
743
|
+
RoborockDockTypeCode.couple_dock,
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
_SPECIAL_WASH_TEMP_DOCK_TYPES = {
|
|
747
|
+
RoborockDockTypeCode.shell_2e_lite_dock,
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
@dataclass(frozen=True)
|
|
752
|
+
class RoborockDockFeatures:
|
|
753
|
+
"""Capabilities derived from a V1 dock type.
|
|
754
|
+
|
|
755
|
+
This mirrors the Roborock app's DK capability model: feature availability
|
|
756
|
+
should be attached to the dock family instead of repeated per trait.
|
|
757
|
+
"""
|
|
758
|
+
|
|
759
|
+
dock_type: RoborockDockTypeCode
|
|
760
|
+
has_am: bool | None = None
|
|
761
|
+
|
|
762
|
+
@classmethod
|
|
763
|
+
@cache
|
|
764
|
+
def from_dock_type(cls, dock_type: RoborockDockTypeCode | None, has_am: bool | None = None) -> Self:
|
|
765
|
+
"""Return cached capabilities for a V1 dock type."""
|
|
766
|
+
return cls(dock_type or RoborockDockTypeCode.o0_dock, has_am=has_am)
|
|
767
|
+
|
|
768
|
+
def _matches_am_variant(self, dock_types: set[RoborockDockTypeCode]) -> bool:
|
|
769
|
+
return self.has_am is True and self.dock_type in dock_types
|
|
770
|
+
|
|
771
|
+
def _matches_non_am_variant(self, dock_types: set[RoborockDockTypeCode]) -> bool:
|
|
772
|
+
return self.has_am is not True and self.dock_type in dock_types
|
|
773
|
+
|
|
774
|
+
@property
|
|
775
|
+
def has_dock(self) -> bool:
|
|
776
|
+
return self.dock_type not in _NO_DOCK_TYPES
|
|
777
|
+
|
|
778
|
+
@property
|
|
779
|
+
def is_pure_collect(self) -> bool:
|
|
780
|
+
return self.dock_type in _PURE_COLLECT_DOCK_TYPES
|
|
781
|
+
|
|
782
|
+
@property
|
|
783
|
+
def is_pure_wash(self) -> bool:
|
|
784
|
+
return self.dock_type in _PURE_WASH_DOCK_TYPES
|
|
785
|
+
|
|
786
|
+
@property
|
|
787
|
+
def is_collect_wash(self) -> bool:
|
|
788
|
+
return self.dock_type in _COLLECT_WASH_DOCK_TYPES
|
|
789
|
+
|
|
790
|
+
@property
|
|
791
|
+
def is_collect_wash_dry(self) -> bool:
|
|
792
|
+
return self.has_dock and not (self.is_pure_collect or self.is_pure_wash or self.is_collect_wash)
|
|
793
|
+
|
|
794
|
+
@property
|
|
795
|
+
def is_collectable(self) -> bool:
|
|
796
|
+
return self.is_collect_wash or self.is_collect_wash_dry or self.is_pure_collect
|
|
797
|
+
|
|
798
|
+
@property
|
|
799
|
+
def is_washable(self) -> bool:
|
|
800
|
+
return self.is_pure_wash or self.is_collect_wash or self.is_collect_wash_dry
|
|
801
|
+
|
|
802
|
+
@property
|
|
803
|
+
def is_dryable(self) -> bool:
|
|
804
|
+
return self.is_collect_wash_dry
|
|
805
|
+
|
|
806
|
+
@property
|
|
807
|
+
def is_only_x_series(self) -> bool:
|
|
808
|
+
return self.dock_type in _ONLY_X_SERIES_DOCK_TYPES
|
|
809
|
+
|
|
810
|
+
@property
|
|
811
|
+
def is_cleaning_brush_supported(self) -> bool:
|
|
812
|
+
return self.is_only_x_series
|
|
813
|
+
|
|
814
|
+
@property
|
|
815
|
+
def is_clean_fluid_auto_delivery_supported(self) -> bool:
|
|
816
|
+
return self.dock_type in _CLEAN_FLUID_AUTO_DELIVERY_DOCK_TYPES or self._matches_am_variant(
|
|
817
|
+
_CLEAN_FLUID_AUTO_DELIVERY_AM_DOCK_TYPES
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
@property
|
|
821
|
+
def is_auto_sterilize_supported(self) -> bool:
|
|
822
|
+
return self.dock_type in _AUTO_STERILIZE_DOCK_TYPES
|
|
823
|
+
|
|
824
|
+
@property
|
|
825
|
+
def is_inner_charge_head(self) -> bool:
|
|
826
|
+
return self.dock_type in _INNER_CHARGE_HEAD_DOCK_TYPES
|
|
827
|
+
|
|
828
|
+
@property
|
|
829
|
+
def is_dust_bucket_supported(self) -> bool:
|
|
830
|
+
return self.dock_type in _DUST_BUCKET_DOCK_TYPES
|
|
831
|
+
|
|
832
|
+
@property
|
|
833
|
+
def is_clean_carousel_self_clean_supported(self) -> bool:
|
|
834
|
+
return self._matches_non_am_variant(_CLEAN_CAROUSEL_SELF_CLEAN_DOCK_TYPES)
|
|
835
|
+
|
|
836
|
+
@property
|
|
837
|
+
def is_water_updown_drain_supported(self) -> bool:
|
|
838
|
+
return self.dock_type in _WATER_UPDOWN_DRAIN_DOCK_TYPES or self._matches_am_variant(
|
|
839
|
+
_WATER_UPDOWN_DRAIN_AM_DOCK_TYPES
|
|
840
|
+
)
|
|
841
|
+
|
|
842
|
+
@property
|
|
843
|
+
def is_hatch_door_dock_cool_fan_supported(self) -> bool:
|
|
844
|
+
return self.dock_type in _HATCH_DOOR_DOCK_COOL_FAN_DOCK_TYPES
|
|
845
|
+
|
|
846
|
+
@property
|
|
847
|
+
def is_special_support_wash_temp(self) -> bool:
|
|
848
|
+
return self.dock_type in _SPECIAL_WASH_TEMP_DOCK_TYPES
|
|
849
|
+
|
|
850
|
+
|
|
647
851
|
WASH_N_FILL_DOCK_TYPES = [
|
|
648
|
-
RoborockDockTypeCode.
|
|
649
|
-
RoborockDockTypeCode.s8_dock,
|
|
650
|
-
RoborockDockTypeCode.p10_dock,
|
|
651
|
-
RoborockDockTypeCode.p10_pro_dock,
|
|
652
|
-
RoborockDockTypeCode.s8_maxv_ultra_dock,
|
|
653
|
-
RoborockDockTypeCode.qrevo_s_dock,
|
|
654
|
-
RoborockDockTypeCode.saros_r10_dock,
|
|
655
|
-
RoborockDockTypeCode.qrevo_curv_dock,
|
|
656
|
-
RoborockDockTypeCode.qrevo_s5v_dock,
|
|
657
|
-
RoborockDockTypeCode.saros_20_dock,
|
|
852
|
+
dock_type for dock_type in RoborockDockTypeCode if RoborockDockFeatures.from_dock_type(dock_type).is_washable
|
|
658
853
|
]
|
|
659
854
|
|
|
660
855
|
|
|
661
856
|
def is_wash_n_fill_dock(dock_type: RoborockDockTypeCode) -> bool:
|
|
662
857
|
"""Check if the dock type is a wash and fill dock."""
|
|
663
|
-
return dock_type
|
|
858
|
+
return RoborockDockFeatures.from_dock_type(dock_type).is_washable
|
|
664
859
|
|
|
665
860
|
|
|
666
861
|
def is_valid_dock(dock_type: RoborockDockTypeCode) -> bool:
|
|
667
862
|
"""Check if device supports a dock."""
|
|
668
|
-
return dock_type
|
|
863
|
+
return RoborockDockFeatures.from_dock_type(dock_type).has_dock
|
|
@@ -42,8 +42,8 @@ optional traits:
|
|
|
42
42
|
- `requires_feature` - The string name of the device feature that must be supported
|
|
43
43
|
for this trait to be enabled. See `DeviceFeaturesTrait` for a list of
|
|
44
44
|
available features.
|
|
45
|
-
- `
|
|
46
|
-
and returns a boolean indicating whether the trait is supported for that dock
|
|
45
|
+
- `requires_dock_features` - If set, this is a function that accepts a `RoborockDockFeatures`
|
|
46
|
+
and returns a boolean indicating whether the trait is supported for that dock.
|
|
47
47
|
|
|
48
48
|
Additionally, DeviceFeaturesTrait has a method `is_field_supported` that is used to
|
|
49
49
|
check individual trait field values. This is a more fine grained version to allow
|
|
@@ -59,6 +59,7 @@ from typing import Any, get_args
|
|
|
59
59
|
|
|
60
60
|
from roborock.data.containers import HomeData, HomeDataProduct, RoborockBase
|
|
61
61
|
from roborock.data.v1.v1_code_mappings import RoborockDockTypeCode
|
|
62
|
+
from roborock.device_features import RoborockDockFeatures
|
|
62
63
|
from roborock.devices.cache import DeviceCache
|
|
63
64
|
from roborock.devices.traits import Trait
|
|
64
65
|
from roborock.exceptions import RoborockException
|
|
@@ -262,9 +263,10 @@ class PropertiesApi(Trait):
|
|
|
262
263
|
await self.device_features.refresh()
|
|
263
264
|
# Dock type also acts like a device feature for some traits.
|
|
264
265
|
dock_type = await self._dock_type()
|
|
266
|
+
dock_features = RoborockDockFeatures.from_dock_type(dock_type, has_am=self.status.has_am)
|
|
265
267
|
|
|
266
268
|
# Initialize traits with special arguments before the generic loop
|
|
267
|
-
if self.wash_towel_mode is None and self._is_supported(WashTowelModeTrait, "wash_towel_mode",
|
|
269
|
+
if self.wash_towel_mode is None and self._is_supported(WashTowelModeTrait, "wash_towel_mode", dock_features):
|
|
268
270
|
wash_towel_mode = WashTowelModeTrait(self.device_features)
|
|
269
271
|
wash_towel_mode._rpc_channel = self._get_rpc_channel(wash_towel_mode) # type: ignore[assignment]
|
|
270
272
|
self.wash_towel_mode = wash_towel_mode
|
|
@@ -280,7 +282,7 @@ class PropertiesApi(Trait):
|
|
|
280
282
|
|
|
281
283
|
# Union args may not be in declared order
|
|
282
284
|
item_type = union_args[0] if union_args[1] is type(None) else union_args[1]
|
|
283
|
-
if not self._is_supported(item_type, item.name,
|
|
285
|
+
if not self._is_supported(item_type, item.name, dock_features):
|
|
284
286
|
_LOGGER.debug("Trait '%s' not supported, skipping", item.name)
|
|
285
287
|
continue
|
|
286
288
|
_LOGGER.debug("Trait '%s' is supported, initializing", item.name)
|
|
@@ -288,11 +290,11 @@ class PropertiesApi(Trait):
|
|
|
288
290
|
setattr(self, item.name, trait)
|
|
289
291
|
trait._rpc_channel = self._get_rpc_channel(trait)
|
|
290
292
|
|
|
291
|
-
def _is_supported(self, trait_type: type[V1TraitMixin], name: str,
|
|
293
|
+
def _is_supported(self, trait_type: type[V1TraitMixin], name: str, dock_features: RoborockDockFeatures) -> bool:
|
|
292
294
|
"""Check if a trait is supported by the device."""
|
|
293
295
|
|
|
294
|
-
if (
|
|
295
|
-
return
|
|
296
|
+
if (requires_dock_features := getattr(trait_type, "requires_dock_features", None)) is not None:
|
|
297
|
+
return requires_dock_features(dock_features)
|
|
296
298
|
|
|
297
299
|
if (feature_name := getattr(trait_type, "requires_feature", None)) is None:
|
|
298
300
|
_LOGGER.debug("Optional trait missing 'requires_feature' attribute %s, skipping", name)
|
|
@@ -307,16 +309,23 @@ class PropertiesApi(Trait):
|
|
|
307
309
|
if dock_type is not None:
|
|
308
310
|
_LOGGER.debug("Using cached dock type: %s", dock_type)
|
|
309
311
|
try:
|
|
310
|
-
|
|
312
|
+
dock_type = RoborockDockTypeCode(dock_type)
|
|
311
313
|
except ValueError:
|
|
312
314
|
_LOGGER.debug("Cached dock type %s is invalid, refreshing", dock_type)
|
|
315
|
+
else:
|
|
316
|
+
if self.status.dss is None:
|
|
317
|
+
await self.status.refresh()
|
|
318
|
+
if self.status.dock_type is not None:
|
|
319
|
+
dock_type = self.status.dock_type
|
|
320
|
+
await self._set_cached_trait_data("dock_type", dock_type)
|
|
321
|
+
return dock_type
|
|
313
322
|
|
|
314
323
|
_LOGGER.debug("Starting dock type discovery")
|
|
315
324
|
await self.status.refresh()
|
|
316
325
|
_LOGGER.debug("Fetched dock type: %s", self.status.dock_type)
|
|
317
326
|
if self.status.dock_type is None:
|
|
318
327
|
# Explicitly set so we reuse cached value next type
|
|
319
|
-
dock_type = RoborockDockTypeCode.
|
|
328
|
+
dock_type = RoborockDockTypeCode.o0_dock
|
|
320
329
|
else:
|
|
321
330
|
dock_type = self.status.dock_type
|
|
322
331
|
await self._set_cached_trait_data("dock_type", dock_type)
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/dust_collection_mode.py
RENAMED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"""Trait for dust collection mode."""
|
|
2
2
|
|
|
3
3
|
from roborock.data import DustCollectionMode
|
|
4
|
-
from roborock.device_features import
|
|
4
|
+
from roborock.device_features import RoborockDockFeatures
|
|
5
5
|
from roborock.devices.traits.v1 import common
|
|
6
6
|
from roborock.roborock_typing import RoborockCommand
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _supports_dust_collection_mode(dock_features: RoborockDockFeatures) -> bool:
|
|
10
|
+
return dock_features.is_collectable
|
|
11
|
+
|
|
12
|
+
|
|
9
13
|
class DustCollectionModeTrait(DustCollectionMode, common.V1TraitMixin):
|
|
10
14
|
"""Trait for dust collection mode."""
|
|
11
15
|
|
|
12
16
|
command = RoborockCommand.GET_DUST_COLLECTION_MODE
|
|
13
17
|
converter = common.DefaultConverter(DustCollectionMode)
|
|
14
|
-
|
|
18
|
+
requires_dock_features = _supports_dust_collection_mode
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/smart_wash_params.py
RENAMED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
"""Trait for smart wash parameters."""
|
|
2
2
|
|
|
3
3
|
from roborock.data import SmartWashParams
|
|
4
|
-
from roborock.device_features import
|
|
4
|
+
from roborock.device_features import RoborockDockFeatures
|
|
5
5
|
from roborock.devices.traits.v1 import common
|
|
6
6
|
from roborock.roborock_typing import RoborockCommand
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _supports_smart_wash_params(dock_features: RoborockDockFeatures) -> bool:
|
|
10
|
+
return dock_features.is_washable
|
|
11
|
+
|
|
12
|
+
|
|
9
13
|
class SmartWashParamsTrait(SmartWashParams, common.V1TraitMixin):
|
|
10
14
|
"""Trait for smart wash parameters."""
|
|
11
15
|
|
|
12
16
|
command = RoborockCommand.GET_SMART_WASH_PARAMS
|
|
13
17
|
converter = common.DefaultConverter(SmartWashParams)
|
|
14
|
-
|
|
18
|
+
requires_dock_features = _supports_smart_wash_params
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/wash_towel_mode.py
RENAMED
|
@@ -4,18 +4,22 @@ from functools import cached_property
|
|
|
4
4
|
from typing import Self
|
|
5
5
|
|
|
6
6
|
from roborock.data import WashTowelMode, WashTowelModes, get_wash_towel_modes
|
|
7
|
-
from roborock.device_features import
|
|
7
|
+
from roborock.device_features import RoborockDockFeatures
|
|
8
8
|
from roborock.devices.traits.v1 import common
|
|
9
9
|
from roborock.devices.traits.v1.device_features import DeviceFeaturesTrait
|
|
10
10
|
from roborock.roborock_typing import RoborockCommand
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def _supports_wash_towel_mode(dock_features: RoborockDockFeatures) -> bool:
|
|
14
|
+
return dock_features.is_washable
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
class WashTowelModeTrait(WashTowelMode, common.V1TraitMixin):
|
|
14
18
|
"""Trait for wash towel mode."""
|
|
15
19
|
|
|
16
20
|
command = RoborockCommand.GET_WASH_TOWEL_MODE
|
|
17
21
|
converter = common.DefaultConverter(WashTowelMode)
|
|
18
|
-
|
|
22
|
+
requires_dock_features = _supports_wash_towel_mode
|
|
19
23
|
|
|
20
24
|
def __init__(
|
|
21
25
|
self,
|
|
@@ -81,7 +81,7 @@ DEFAULT_STATUS = StatusV2(
|
|
|
81
81
|
home_sec_enable_password=0,
|
|
82
82
|
adbumper_status=[0, 0, 0],
|
|
83
83
|
water_shortage_status=0,
|
|
84
|
-
dock_type=RoborockDockTypeCode.
|
|
84
|
+
dock_type=RoborockDockTypeCode.o4_dock,
|
|
85
85
|
dust_collection_status=0,
|
|
86
86
|
auto_dust_collection=1,
|
|
87
87
|
avoid_count=19,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q10/b01_q10_code_mappings.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q10/b01_q10_containers.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/data/b01_q7/b01_q7_code_mappings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/__init__.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/button_light.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/child_lock.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/clean_history.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/command.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/consumable.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/dust_collection.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q10/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/__init__.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/b01/q7/map_content.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/device_features.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/flow_led_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/traits/v1/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/local_channel.py
RENAMED
|
File without changes
|
{python_roborock-5.27.0 → python_roborock-5.28.0}/roborock/devices/transport/mqtt_channel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|