python-roborock 7.8.1__tar.gz → 7.9.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 (134) hide show
  1. {python_roborock-7.8.1 → python_roborock-7.9.0}/PKG-INFO +1 -1
  2. {python_roborock-7.8.1 → python_roborock-7.9.0}/pyproject.toml +1 -1
  3. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/v1/v1_containers.py +22 -0
  4. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/__init__.py +4 -0
  5. python_roborock-7.9.0/roborock/devices/traits/v1/mop_dryer.py +51 -0
  6. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/web_api.py +33 -4
  7. {python_roborock-7.8.1 → python_roborock-7.9.0}/.gitignore +0 -0
  8. {python_roborock-7.8.1 → python_roborock-7.9.0}/LICENSE +0 -0
  9. {python_roborock-7.8.1 → python_roborock-7.9.0}/README.md +0 -0
  10. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/__init__.py +0 -0
  11. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/broadcast_protocol.py +0 -0
  12. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/callbacks.py +0 -0
  13. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/cli.py +0 -0
  14. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/const.py +0 -0
  15. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/__init__.py +0 -0
  16. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q10/__init__.py +0 -0
  17. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
  18. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
  19. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q7/__init__.py +0 -0
  20. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
  21. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
  22. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/code_mappings.py +0 -0
  23. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/containers.py +0 -0
  24. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/dyad/__init__.py +0 -0
  25. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
  26. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/dyad/dyad_containers.py +0 -0
  27. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/mower/__init__.py +0 -0
  28. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/mower/mower_code_mappings.py +0 -0
  29. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/mower/mower_containers.py +0 -0
  30. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/v1/__init__.py +0 -0
  31. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/v1/v1_clean_modes.py +0 -0
  32. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/v1/v1_code_mappings.py +0 -0
  33. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/zeo/__init__.py +0 -0
  34. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
  35. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/data/zeo/zeo_containers.py +0 -0
  36. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/device_features.py +0 -0
  37. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/README.md +0 -0
  38. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/__init__.py +0 -0
  39. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/cache.py +0 -0
  40. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/device.py +0 -0
  41. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/device_manager.py +0 -0
  42. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/file_cache.py +0 -0
  43. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/rpc/__init__.py +0 -0
  44. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/rpc/a01_channel.py +0 -0
  45. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
  46. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
  47. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/rpc/v1_channel.py +0 -0
  48. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/__init__.py +0 -0
  49. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/a01/__init__.py +0 -0
  50. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/a01/device_feature.py +0 -0
  51. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/__init__.py +0 -0
  52. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
  53. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/button_light.py +0 -0
  54. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/child_lock.py +0 -0
  55. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/clean_history.py +0 -0
  56. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/command.py +0 -0
  57. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/common.py +0 -0
  58. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/consumable.py +0 -0
  59. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/do_not_disturb.py +0 -0
  60. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/dust_collection.py +0 -0
  61. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/goto.py +0 -0
  62. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/map.py +0 -0
  63. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/maps.py +0 -0
  64. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/network_info.py +0 -0
  65. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/remote.py +0 -0
  66. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/status.py +0 -0
  67. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
  68. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q10/volume.py +0 -0
  69. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
  70. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
  71. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q7/map.py +0 -0
  72. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/b01/q7/map_content.py +0 -0
  73. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/common.py +0 -0
  74. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/traits_mixin.py +0 -0
  75. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/child_lock.py +0 -0
  76. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
  77. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/command.py +0 -0
  78. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/common.py +0 -0
  79. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/consumeable.py +0 -0
  80. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/device_features.py +0 -0
  81. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
  82. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
  83. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
  84. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/home.py +0 -0
  85. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/led_status.py +0 -0
  86. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/map_content.py +0 -0
  87. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/maps.py +0 -0
  88. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/network_info.py +0 -0
  89. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/obstacle_photos.py +0 -0
  90. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/rooms.py +0 -0
  91. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/routines.py +0 -0
  92. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
  93. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/status.py +0 -0
  94. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
  95. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/volume.py +0 -0
  96. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
  97. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/transport/__init__.py +0 -0
  98. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/transport/channel.py +0 -0
  99. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/transport/local_channel.py +0 -0
  100. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/devices/transport/mqtt_channel.py +0 -0
  101. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/diagnostics.py +0 -0
  102. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/exceptions.py +0 -0
  103. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/__init__.py +0 -0
  104. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/b01_grid_layers.py +0 -0
  105. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/b01_map_parser.py +0 -0
  106. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/b01_q10_map_parser.py +0 -0
  107. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/b01_q10_overlays.py +0 -0
  108. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/b01_q10_render.py +0 -0
  109. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/map_parser.py +0 -0
  110. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/proto/__init__.py +0 -0
  111. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/proto/b01_scmap.proto +0 -0
  112. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/proto/b01_scmap_pb2.py +0 -0
  113. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/map/room_colors.py +0 -0
  114. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/mqtt/__init__.py +0 -0
  115. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/mqtt/health_manager.py +0 -0
  116. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/mqtt/roborock_session.py +0 -0
  117. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/mqtt/session.py +0 -0
  118. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocol.py +0 -0
  119. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocols/__init__.py +0 -0
  120. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocols/a01_protocol.py +0 -0
  121. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocols/b01_q10_protocol.py +0 -0
  122. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocols/b01_q7_protocol.py +0 -0
  123. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/protocols/v1_protocol.py +0 -0
  124. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/py.typed +0 -0
  125. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/roborock_message.py +0 -0
  126. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/roborock_typing.py +0 -0
  127. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/__init__.py +0 -0
  128. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/a01_simulator.py +0 -0
  129. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/b01_q10_simulator.py +0 -0
  130. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/channel.py +0 -0
  131. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/cloud.py +0 -0
  132. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/simulator.py +0 -0
  133. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/testing/v1_simulator.py +0 -0
  134. {python_roborock-7.8.1 → python_roborock-7.9.0}/roborock/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-roborock
3
- Version: 7.8.1
3
+ Version: 7.9.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 = "7.8.1"
3
+ version = "7.9.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"
@@ -459,6 +459,28 @@ class SmartWashParams(RoborockBase):
459
459
  wash_interval: int | None = None
460
460
 
461
461
 
462
+ @dataclass
463
+ class MopDryerProfile(RoborockBase):
464
+ """Dryer parameters for one state of the auto mop-drying setting."""
465
+
466
+ cliff_on: int | None = None
467
+ cliff_off: int | None = None
468
+ count: int | None = None
469
+ dry_time: int | None = None
470
+ """Drying duration in seconds. Only present in the ``on`` profile."""
471
+ dry_heating_film_time: int | None = None
472
+ """Heating element run time in seconds. Only present in the ``on`` profile."""
473
+
474
+
475
+ @dataclass
476
+ class MopDryerSetting(RoborockBase):
477
+ """Auto mop-drying setting, as returned by APP_GET_DRYER_SETTING."""
478
+
479
+ status: int | None = None
480
+ on: MopDryerProfile | None = None
481
+ off: MopDryerProfile | None = None
482
+
483
+
462
484
  @dataclass
463
485
  class DustCollectionMode(RoborockBase):
464
486
  mode: RoborockDockDustCollectionModeCode | None = None
@@ -82,6 +82,7 @@ from . import (
82
82
  led_status,
83
83
  map_content,
84
84
  maps,
85
+ mop_dryer,
85
86
  network_info,
86
87
  obstacle_photos,
87
88
  rooms,
@@ -105,6 +106,7 @@ from .home import HomeTrait
105
106
  from .led_status import LedStatusTrait
106
107
  from .map_content import MapContentTrait
107
108
  from .maps import MapsTrait
109
+ from .mop_dryer import MopDryerTrait
108
110
  from .network_info import NetworkInfoTrait
109
111
  from .obstacle_photos import ObstaclePhotoTrait
110
112
  from .rooms import RoomsTrait
@@ -132,6 +134,7 @@ __all__ = [
132
134
  "led_status",
133
135
  "map_content",
134
136
  "maps",
137
+ "mop_dryer",
135
138
  "network_info",
136
139
  "obstacle_photos",
137
140
  "rooms",
@@ -175,6 +178,7 @@ class PropertiesApi(Trait):
175
178
  wash_towel_mode: WashTowelModeTrait | None = None
176
179
  smart_wash_params: SmartWashParamsTrait | None = None
177
180
  obstacle_photos: ObstaclePhotoTrait | None = None
181
+ mop_dryer: MopDryerTrait | None = None
178
182
 
179
183
  def __init__(
180
184
  self,
@@ -0,0 +1,51 @@
1
+ """Trait for the dock mop dryer."""
2
+
3
+ from roborock.data import MopDryerSetting
4
+ from roborock.device_features import RoborockDockFeatures
5
+ from roborock.devices.traits.v1 import common
6
+ from roborock.roborock_typing import RoborockCommand
7
+
8
+ _STATUS_PARAM = "status"
9
+
10
+
11
+ def _supports_mop_dryer(dock_features: RoborockDockFeatures) -> bool:
12
+ return dock_features.is_dryable
13
+
14
+
15
+ class MopDryerTrait(MopDryerSetting, common.V1TraitMixin, common.RoborockSwitchBase):
16
+ """Trait for the dock mop dryer.
17
+
18
+ The switch controls the auto mop-drying setting, i.e. whether the dock
19
+ dries the mop after washing. ``start_dry`` and ``stop_dry`` control a
20
+ drying cycle directly. Whether a cycle is currently running is reported
21
+ as ``dry_status`` on the device status.
22
+ """
23
+
24
+ command = RoborockCommand.APP_GET_DRYER_SETTING
25
+ converter = common.DefaultConverter(MopDryerSetting)
26
+ requires_dock_features = _supports_mop_dryer
27
+
28
+ @property
29
+ def is_on(self) -> bool:
30
+ """Return whether auto mop drying is enabled."""
31
+ return self.status == 1
32
+
33
+ async def enable(self) -> None:
34
+ """Enable auto mop drying."""
35
+ await self.rpc_channel.send_command(RoborockCommand.APP_SET_DRYER_SETTING, params={_STATUS_PARAM: 1})
36
+ # Optimistic update to avoid an extra refresh
37
+ self.status = 1
38
+
39
+ async def disable(self) -> None:
40
+ """Disable auto mop drying."""
41
+ await self.rpc_channel.send_command(RoborockCommand.APP_SET_DRYER_SETTING, params={_STATUS_PARAM: 0})
42
+ # Optimistic update to avoid an extra refresh
43
+ self.status = 0
44
+
45
+ async def start_dry(self) -> None:
46
+ """Start a mop drying cycle."""
47
+ await self.rpc_channel.send_command(RoborockCommand.APP_SET_DRYER_STATUS, params={_STATUS_PARAM: 1})
48
+
49
+ async def stop_dry(self) -> None:
50
+ """Stop the running mop drying cycle."""
51
+ await self.rpc_channel.send_command(RoborockCommand.APP_SET_DRYER_STATUS, params={_STATUS_PARAM: 0})
@@ -38,6 +38,10 @@ BASE_URLS = [
38
38
  "https://ruiot.roborock.com",
39
39
  ]
40
40
 
41
+ # Fallback user agreement version, used only if the latest version cannot be fetched.
42
+ DEFAULT_AGREEMENT_MAJOR_VERSION = 14
43
+ DEFAULT_AGREEMENT_MINOR_VERSION = 0
44
+
41
45
 
42
46
  @dataclass
43
47
  class IotLoginInfo:
@@ -292,6 +296,34 @@ class RoborockApiClient:
292
296
 
293
297
  return code_response["data"]["k"]
294
298
 
299
+ async def _get_agreement_version(self, country: str) -> dict[str, int]:
300
+ """Get the latest user agreement version for the given country.
301
+
302
+ The login endpoint rejects a stale agreement version with code 3006. The
303
+ current version differs per server and per country, so it must be looked
304
+ up rather than hardcoded. Falls back to the previously hardcoded values
305
+ if the lookup fails so that login is never blocked by this request.
306
+ """
307
+ try:
308
+ base_url = await self.base_url
309
+ agreement_request = PreparedRequest(base_url, self.session, {"header_clientlang": "en"})
310
+ response = await agreement_request.request(
311
+ "get",
312
+ "/api/v3/app/agreement/latest",
313
+ params={"country": country},
314
+ )
315
+ if response is not None and response.get("code") == 200:
316
+ data = response.get("data") or {}
317
+ major = data.get("majorVersion")
318
+ minor = data.get("minorVersion")
319
+ if isinstance(major, int) and isinstance(minor, int):
320
+ _LOGGER.debug("Using user agreement version %s.%s for %s", major, minor, country)
321
+ return {"majorVersion": major, "minorVersion": minor}
322
+ _LOGGER.debug("Unexpected agreement version response: %s", response)
323
+ except RoborockException as err:
324
+ _LOGGER.debug("Could not fetch latest user agreement version: %s", err)
325
+ return {"majorVersion": DEFAULT_AGREEMENT_MAJOR_VERSION, "minorVersion": DEFAULT_AGREEMENT_MINOR_VERSION}
326
+
295
327
  async def code_login_v4(
296
328
  self, code: int | str, country: str | None = None, country_code: int | None = None
297
329
  ) -> UserData:
@@ -334,10 +366,7 @@ class RoborockApiClient:
334
366
  "countryCode": country_code,
335
367
  "email": self._username,
336
368
  "code": code,
337
- # Major and minor version are the user agreement version, we will need to see if this needs to be
338
- # dynamic https://usiot.roborock.com/api/v3/app/agreement/latest?country=US
339
- "majorVersion": 14,
340
- "minorVersion": 0,
369
+ **await self._get_agreement_version(country),
341
370
  },
342
371
  )
343
372
  if login_response is None:
File without changes