roborock.data.v1.v1_clean_modes
1from __future__ import annotations 2 3import typing 4from enum import StrEnum 5from typing import TypeVar 6 7from ...exceptions import RoborockUnsupportedFeature 8from ..code_mappings import RoborockModeEnum 9 10if typing.TYPE_CHECKING: 11 from roborock.device_features import DeviceFeatures 12 13 14class VacuumModes(RoborockModeEnum): 15 GENTLE = ("gentle", 105) 16 OFF = ("off", 105) 17 QUIET = ("quiet", 101) 18 BALANCED = ("balanced", 102) 19 TURBO = ("turbo", 103) 20 MAX = ("max", 104) 21 MAX_PLUS = ("max_plus", 108) 22 OFF_RAISE_MAIN_BRUSH = ("off_raise_main_brush", 109) 23 CUSTOMIZED = ("custom", 106) 24 SMART_MODE = ("smart_mode", 110) 25 26 27class CleanRoutes(RoborockModeEnum): 28 STANDARD = ("standard", 300) 29 DEEP = ("deep", 301) 30 DEEP_PLUS = ("deep_plus", 303) 31 FAST = ("fast", 304) 32 DEEP_PLUS_CN = ("deep_plus_cn", 305, "deep_plus") 33 SMART_MODE = ("smart_mode", 306) 34 CUSTOMIZED = ("custom", 302) 35 36 37class VacuumModesOld(RoborockModeEnum): 38 QUIET = ("quiet", 38) 39 BALANCED = ("balanced", 60) 40 TURBO = ("turbo", 75) 41 MAX = ("max", 100) 42 43 44class WaterModes(RoborockModeEnum): 45 OFF = ("off", 200) 46 LOW = ("low", 201) 47 MILD = ("mild", 201) 48 MEDIUM = ("medium", 202) 49 STANDARD = ("standard", 202) 50 HIGH = ("high", 203) 51 INTENSE = ("intense", 203) 52 MIN = ("min", 205) 53 MAX = ("max", 206) 54 CUSTOMIZED = ("custom", 204) 55 CUSTOM = ("custom_water_flow", 207) 56 EXTREME = ("extreme", 208) 57 SMART_MODE = ("smart_mode", 209) 58 PURE_WATER_FLOW_START = ("slight", 221) 59 PURE_WATER_FLOW_SMALL = ("low", 225) 60 PURE_WATER_FLOW_MIDDLE = ("medium", 235) 61 PURE_WATER_FLOW_LARGE = ("moderate", 245) 62 PURE_WATER_SUPER_BEGIN = ("high", 248) 63 PURE_WATER_FLOW_END = ("extreme", 250) 64 65 66class WashTowelModes(RoborockModeEnum): 67 SMART = ("smart", 10) 68 LIGHT = ("light", 0) 69 BALANCED = ("balanced", 1) 70 DEEP = ("deep", 2) 71 SUPER_DEEP = ("super_deep", 8) 72 73 74class CleaningMode(StrEnum): 75 """High-level cleaning intent derived from the lower-level motor settings. 76 77 Prefer this abstraction when you want to present or switch between the 78 user-facing cleaning behaviors exposed by the app. The lower-level 79 `VacuumModes`, `WaterModes`, and `CleanRoutes` enums are still useful for 80 fine-grained selection. 81 """ 82 83 VACUUM = "vacuum" 84 VAC_AND_MOP = "vac_and_mop" 85 MOP = "mop" 86 CUSTOM = "custom" 87 SMART_MODE = "smart_mode" 88 89 90WATER_SLIDE_MODE_MAPPING: dict[int, WaterModes] = { 91 200: WaterModes.OFF, 92 221: WaterModes.PURE_WATER_FLOW_START, 93 225: WaterModes.PURE_WATER_FLOW_SMALL, 94 235: WaterModes.PURE_WATER_FLOW_MIDDLE, 95 245: WaterModes.PURE_WATER_FLOW_LARGE, 96 248: WaterModes.PURE_WATER_SUPER_BEGIN, 97 250: WaterModes.PURE_WATER_FLOW_END, 98} 99 100ModeEnumT = TypeVar("ModeEnumT", bound=RoborockModeEnum) 101 102 103def get_wash_towel_modes(features: DeviceFeatures) -> list[WashTowelModes]: 104 """Get the valid wash towel modes for the device""" 105 modes = [WashTowelModes.LIGHT, WashTowelModes.BALANCED, WashTowelModes.DEEP] 106 if features.is_super_deep_wash_supported and not features.is_dirty_replenish_clean_supported: 107 modes.append(WashTowelModes.SUPER_DEEP) 108 elif features.is_dirty_replenish_clean_supported: 109 modes.append(WashTowelModes.SMART) 110 return modes 111 112 113def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]: 114 """Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'""" 115 modes = [VacuumModes.QUIET, VacuumModes.BALANCED, VacuumModes.TURBO, VacuumModes.MAX] 116 if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus: 117 # If the vacuum has max plus mode supported 118 modes.append(VacuumModes.MAX_PLUS) 119 if features.is_pure_clean_mop_supported: 120 # If the vacuum is capable of 'pure mop clean' aka no vacuum 121 modes.append(VacuumModes.OFF) 122 else: 123 # If not, we can add gentle 124 modes.append(VacuumModes.GENTLE) 125 if features.is_smart_clean_mode_set_supported: 126 modes.append(VacuumModes.SMART_MODE) 127 if features.is_customized_clean_supported: 128 modes.append(VacuumModes.CUSTOMIZED) 129 return modes 130 131 132def get_clean_routes(features: DeviceFeatures, region: str) -> list[CleanRoutes]: 133 """The routes that the vacuum will take while mopping""" 134 if not features.is_clean_route_setting_supported: 135 return [] 136 if features.is_none_pure_clean_mop_with_max_plus: 137 return [CleanRoutes.FAST, CleanRoutes.STANDARD] 138 supported = [CleanRoutes.STANDARD] 139 if not features.is_clean_efficiency_supported: 140 supported.append(CleanRoutes.DEEP) 141 if features.is_careful_slow_mop_supported: 142 if ( 143 not features.is_corner_clean_mode_supported 144 and features.is_clean_route_deep_slow_plus_supported 145 and region == "cn" 146 ): 147 supported.append(CleanRoutes.DEEP_PLUS_CN) 148 else: 149 supported.append(CleanRoutes.DEEP_PLUS) 150 151 if features.is_clean_route_fast_mode_supported: 152 supported.append(CleanRoutes.FAST) 153 if features.is_smart_clean_mode_set_supported: 154 supported.append(CleanRoutes.SMART_MODE) 155 if features.is_customized_clean_supported: 156 supported.append(CleanRoutes.CUSTOMIZED) 157 158 return supported 159 160 161def get_water_modes(features: DeviceFeatures) -> list[WaterModes]: 162 """Get the valid water modes for the device - also known as 'water flow' or 'water level'""" 163 # Water slide mode supports a separate set of water flow codes. 164 if features.is_water_slide_mode_supported: 165 return list(WATER_SLIDE_MODE_MAPPING.values()) 166 167 supported_modes = [WaterModes.OFF] 168 if features.is_mop_shake_module_supported: 169 # For mops that have the vibrating mop pad, they do mild standard intense 170 supported_modes.extend([WaterModes.MILD, WaterModes.STANDARD, WaterModes.INTENSE]) 171 else: 172 supported_modes.extend([WaterModes.LOW, WaterModes.MEDIUM, WaterModes.HIGH]) 173 if features.is_custom_water_box_distance_supported: 174 # This is for devices that allow you to set a custom water flow from 0-100 175 supported_modes.append(WaterModes.CUSTOM) 176 if features.is_mop_shake_module_supported and features.is_mop_shake_water_max_supported: 177 supported_modes.append(WaterModes.EXTREME) 178 if features.is_smart_clean_mode_set_supported: 179 supported_modes.append(WaterModes.SMART_MODE) 180 if features.is_customized_clean_supported: 181 supported_modes.append(WaterModes.CUSTOMIZED) 182 183 return supported_modes 184 185 186def get_water_mode_mapping(features: DeviceFeatures) -> dict[int, str]: 187 """Get water mode mapping by supported feature set. 188 189 WaterModes contains aliases for multiple codes that share the same value 190 string (e.g. low can be 201 or 225). For water slide mode devices we need 191 explicit code mapping to preserve those slide-specific codes. 192 """ 193 if features.is_water_slide_mode_supported: 194 return {code: mode.value for code, mode in WATER_SLIDE_MODE_MAPPING.items()} 195 return {mode.code: mode.value for mode in get_water_modes(features)} 196 197 198def get_cleaning_mode_options(features: DeviceFeatures) -> list[CleaningMode]: 199 """Return the supported high-level cleaning modes for the device. 200 201 These options are the preferred user-facing choices because they bundle the 202 correct fan, water, and mop-route settings together for the device. Callers 203 should generally present these instead of mixing lower-level mode enums 204 unless they explicitly need fine-grained control. 205 """ 206 if not features.is_support_water_mode: 207 return [] 208 209 supported_water_modes = get_water_modes(features) 210 options = [CleaningMode.VACUUM, CleaningMode.VAC_AND_MOP] 211 if features.is_pure_clean_mop_supported: 212 options.append(CleaningMode.MOP) 213 if features.is_customized_clean_supported and WaterModes.CUSTOMIZED in supported_water_modes: 214 options.append(CleaningMode.CUSTOM) 215 if features.is_smart_clean_mode_set_supported and WaterModes.SMART_MODE in supported_water_modes: 216 options.append(CleaningMode.SMART_MODE) 217 return options 218 219 220def get_mop_only_vacuum_mode(features: DeviceFeatures) -> VacuumModes: 221 """Return the vacuum mode used by the app for mop-only cleaning.""" 222 if not features.is_pure_clean_mop_supported: 223 raise RoborockUnsupportedFeature("Mop-only cleaning is not supported") 224 # Main-brush lift is a device capability, not an alternate fan-power 225 # command. The app still sends CleanModeZero (105) for mop-only cleaning. 226 return VacuumModes.OFF 227 228 229def _get_default_mopping_water_mode(features: DeviceFeatures) -> WaterModes: 230 """Pick a sensible default water mode when mopping for the device.""" 231 # Water-slide devices use a disjoint set of water codes; pick a mid-flow 232 # slide code instead of the standard 202, which they don't accept. 233 if features.is_water_slide_mode_supported: 234 return WaterModes.PURE_WATER_FLOW_MIDDLE 235 return WaterModes.STANDARD 236 237 238def _get_clean_motor_mode_params( 239 mode: CleaningMode, 240 features: DeviceFeatures, 241) -> tuple[VacuumModes, WaterModes, CleanRoutes]: 242 """Return (fan_power, water_box_mode, mop_mode) enums for the high-level mode.""" 243 if mode == CleaningMode.VACUUM: 244 return (VacuumModes.BALANCED, WaterModes.OFF, CleanRoutes.STANDARD) 245 if mode == CleaningMode.VAC_AND_MOP: 246 return (VacuumModes.BALANCED, _get_default_mopping_water_mode(features), CleanRoutes.STANDARD) 247 if mode == CleaningMode.MOP: 248 return ( 249 get_mop_only_vacuum_mode(features), 250 _get_default_mopping_water_mode(features), 251 CleanRoutes.STANDARD, 252 ) 253 if mode == CleaningMode.CUSTOM: 254 return (VacuumModes.CUSTOMIZED, WaterModes.CUSTOMIZED, CleanRoutes.CUSTOMIZED) 255 if mode == CleaningMode.SMART_MODE: 256 return (VacuumModes.SMART_MODE, WaterModes.SMART_MODE, CleanRoutes.SMART_MODE) 257 raise RoborockUnsupportedFeature(f"Cleaning mode {mode.value!r} is not supported") 258 259 260def resolve_cleaning_mode(cleaning_mode: str | CleaningMode) -> CleaningMode: 261 """Resolve a string or enum into a CleaningMode value.""" 262 if isinstance(cleaning_mode, CleaningMode): 263 return cleaning_mode 264 try: 265 return CleaningMode(cleaning_mode) 266 except ValueError as err: 267 raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode!r} is not supported") from err 268 269 270def get_cleaning_mode_parameters(cleaning_mode: CleaningMode, features: DeviceFeatures) -> list[dict[str, int]]: 271 """Get the RPC payload for switching the high-level cleaning mode.""" 272 if cleaning_mode not in get_cleaning_mode_options(features): 273 raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode.value!r} is not supported") 274 275 fan_power, water_box_mode, mop_mode = _get_clean_motor_mode_params(cleaning_mode, features) 276 params: dict[str, int] = {"fan_power": fan_power.code, "water_box_mode": water_box_mode.code} 277 if features.is_clean_route_setting_supported: 278 params["mop_mode"] = mop_mode.code 279 return [params] 280 281 282def _resolve_mode_code(value: int | ModeEnumT | None, mode_cls: type[ModeEnumT]) -> ModeEnumT | None: 283 """Resolve a raw code or enum into a RoborockModeEnum.""" 284 if value is None: 285 return None 286 if isinstance(value, mode_cls): 287 return value 288 return mode_cls.from_code_optional(int(value)) 289 290 291def _resolve_clean_mode(value: int | VacuumModes | None, features: DeviceFeatures) -> VacuumModes | None: 292 """Resolve a vacuum mode code, accounting for feature-specific code aliases.""" 293 if value is None or isinstance(value, VacuumModes): 294 return value 295 if value == VacuumModes.OFF.code: 296 if features.is_pure_clean_mop_supported: 297 return get_mop_only_vacuum_mode(features) 298 return VacuumModes.GENTLE 299 return VacuumModes.from_code_optional(value) 300 301 302def get_current_cleaning_mode( 303 clean_mode: int | VacuumModes | None, 304 water_mode: int | WaterModes | None, 305 mop_mode: int | CleanRoutes | None, 306 features: DeviceFeatures, 307) -> CleaningMode | None: 308 """Classify the current high-level cleaning mode from individual mode codes.""" 309 if not features.is_support_water_mode: 310 return None 311 clean_mode_enum = _resolve_clean_mode(clean_mode, features) 312 water_mode_enum = _resolve_mode_code(water_mode, WaterModes) 313 mop_mode_enum = _resolve_mode_code(mop_mode, CleanRoutes) 314 if clean_mode_enum is None or water_mode_enum is None: 315 return None 316 317 if is_smart_mode_set(water_mode_enum, clean_mode_enum, mop_mode_enum): 318 return CleaningMode.SMART_MODE 319 if is_mode_customized(clean_mode_enum, water_mode_enum, mop_mode_enum): 320 return CleaningMode.CUSTOM 321 if water_mode_enum != WaterModes.OFF: 322 try: 323 if clean_mode_enum == get_mop_only_vacuum_mode(features): 324 return CleaningMode.MOP 325 except RoborockUnsupportedFeature: 326 pass 327 if water_mode_enum == WaterModes.OFF: 328 return CleaningMode.VACUUM 329 return CleaningMode.VAC_AND_MOP 330 331 332def is_mode_customized( 333 clean_mode: VacuumModes | None, 334 water_mode: WaterModes | None, 335 mop_mode: CleanRoutes | None, 336) -> bool: 337 """Check if any of the cleaning modes are set to a custom value.""" 338 return ( 339 clean_mode == VacuumModes.CUSTOMIZED 340 or water_mode == WaterModes.CUSTOMIZED 341 or mop_mode == CleanRoutes.CUSTOMIZED 342 ) 343 344 345def is_smart_mode_set( 346 water_mode: WaterModes | None, 347 clean_mode: VacuumModes | None, 348 mop_mode: CleanRoutes | None, 349) -> bool: 350 """Check if the smart mode is set for the given water mode and clean mode""" 351 return ( 352 water_mode == WaterModes.SMART_MODE 353 or clean_mode == VacuumModes.SMART_MODE 354 or mop_mode == CleanRoutes.SMART_MODE 355 )
15class VacuumModes(RoborockModeEnum): 16 GENTLE = ("gentle", 105) 17 OFF = ("off", 105) 18 QUIET = ("quiet", 101) 19 BALANCED = ("balanced", 102) 20 TURBO = ("turbo", 103) 21 MAX = ("max", 104) 22 MAX_PLUS = ("max_plus", 108) 23 OFF_RAISE_MAIN_BRUSH = ("off_raise_main_brush", 109) 24 CUSTOMIZED = ("custom", 106) 25 SMART_MODE = ("smart_mode", 110)
A custom StrEnum that also stores an integer code for each member.
28class CleanRoutes(RoborockModeEnum): 29 STANDARD = ("standard", 300) 30 DEEP = ("deep", 301) 31 DEEP_PLUS = ("deep_plus", 303) 32 FAST = ("fast", 304) 33 DEEP_PLUS_CN = ("deep_plus_cn", 305, "deep_plus") 34 SMART_MODE = ("smart_mode", 306) 35 CUSTOMIZED = ("custom", 302)
A custom StrEnum that also stores an integer code for each member.
38class VacuumModesOld(RoborockModeEnum): 39 QUIET = ("quiet", 38) 40 BALANCED = ("balanced", 60) 41 TURBO = ("turbo", 75) 42 MAX = ("max", 100)
A custom StrEnum that also stores an integer code for each member.
45class WaterModes(RoborockModeEnum): 46 OFF = ("off", 200) 47 LOW = ("low", 201) 48 MILD = ("mild", 201) 49 MEDIUM = ("medium", 202) 50 STANDARD = ("standard", 202) 51 HIGH = ("high", 203) 52 INTENSE = ("intense", 203) 53 MIN = ("min", 205) 54 MAX = ("max", 206) 55 CUSTOMIZED = ("custom", 204) 56 CUSTOM = ("custom_water_flow", 207) 57 EXTREME = ("extreme", 208) 58 SMART_MODE = ("smart_mode", 209) 59 PURE_WATER_FLOW_START = ("slight", 221) 60 PURE_WATER_FLOW_SMALL = ("low", 225) 61 PURE_WATER_FLOW_MIDDLE = ("medium", 235) 62 PURE_WATER_FLOW_LARGE = ("moderate", 245) 63 PURE_WATER_SUPER_BEGIN = ("high", 248) 64 PURE_WATER_FLOW_END = ("extreme", 250)
A custom StrEnum that also stores an integer code for each member.
67class WashTowelModes(RoborockModeEnum): 68 SMART = ("smart", 10) 69 LIGHT = ("light", 0) 70 BALANCED = ("balanced", 1) 71 DEEP = ("deep", 2) 72 SUPER_DEEP = ("super_deep", 8)
A custom StrEnum that also stores an integer code for each member.
75class CleaningMode(StrEnum): 76 """High-level cleaning intent derived from the lower-level motor settings. 77 78 Prefer this abstraction when you want to present or switch between the 79 user-facing cleaning behaviors exposed by the app. The lower-level 80 `VacuumModes`, `WaterModes`, and `CleanRoutes` enums are still useful for 81 fine-grained selection. 82 """ 83 84 VACUUM = "vacuum" 85 VAC_AND_MOP = "vac_and_mop" 86 MOP = "mop" 87 CUSTOM = "custom" 88 SMART_MODE = "smart_mode"
High-level cleaning intent derived from the lower-level motor settings.
Prefer this abstraction when you want to present or switch between the
user-facing cleaning behaviors exposed by the app. The lower-level
VacuumModes, WaterModes, and CleanRoutes enums are still useful for
fine-grained selection.
104def get_wash_towel_modes(features: DeviceFeatures) -> list[WashTowelModes]: 105 """Get the valid wash towel modes for the device""" 106 modes = [WashTowelModes.LIGHT, WashTowelModes.BALANCED, WashTowelModes.DEEP] 107 if features.is_super_deep_wash_supported and not features.is_dirty_replenish_clean_supported: 108 modes.append(WashTowelModes.SUPER_DEEP) 109 elif features.is_dirty_replenish_clean_supported: 110 modes.append(WashTowelModes.SMART) 111 return modes
Get the valid wash towel modes for the device
114def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]: 115 """Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'""" 116 modes = [VacuumModes.QUIET, VacuumModes.BALANCED, VacuumModes.TURBO, VacuumModes.MAX] 117 if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus: 118 # If the vacuum has max plus mode supported 119 modes.append(VacuumModes.MAX_PLUS) 120 if features.is_pure_clean_mop_supported: 121 # If the vacuum is capable of 'pure mop clean' aka no vacuum 122 modes.append(VacuumModes.OFF) 123 else: 124 # If not, we can add gentle 125 modes.append(VacuumModes.GENTLE) 126 if features.is_smart_clean_mode_set_supported: 127 modes.append(VacuumModes.SMART_MODE) 128 if features.is_customized_clean_supported: 129 modes.append(VacuumModes.CUSTOMIZED) 130 return modes
Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'
133def get_clean_routes(features: DeviceFeatures, region: str) -> list[CleanRoutes]: 134 """The routes that the vacuum will take while mopping""" 135 if not features.is_clean_route_setting_supported: 136 return [] 137 if features.is_none_pure_clean_mop_with_max_plus: 138 return [CleanRoutes.FAST, CleanRoutes.STANDARD] 139 supported = [CleanRoutes.STANDARD] 140 if not features.is_clean_efficiency_supported: 141 supported.append(CleanRoutes.DEEP) 142 if features.is_careful_slow_mop_supported: 143 if ( 144 not features.is_corner_clean_mode_supported 145 and features.is_clean_route_deep_slow_plus_supported 146 and region == "cn" 147 ): 148 supported.append(CleanRoutes.DEEP_PLUS_CN) 149 else: 150 supported.append(CleanRoutes.DEEP_PLUS) 151 152 if features.is_clean_route_fast_mode_supported: 153 supported.append(CleanRoutes.FAST) 154 if features.is_smart_clean_mode_set_supported: 155 supported.append(CleanRoutes.SMART_MODE) 156 if features.is_customized_clean_supported: 157 supported.append(CleanRoutes.CUSTOMIZED) 158 159 return supported
The routes that the vacuum will take while mopping
162def get_water_modes(features: DeviceFeatures) -> list[WaterModes]: 163 """Get the valid water modes for the device - also known as 'water flow' or 'water level'""" 164 # Water slide mode supports a separate set of water flow codes. 165 if features.is_water_slide_mode_supported: 166 return list(WATER_SLIDE_MODE_MAPPING.values()) 167 168 supported_modes = [WaterModes.OFF] 169 if features.is_mop_shake_module_supported: 170 # For mops that have the vibrating mop pad, they do mild standard intense 171 supported_modes.extend([WaterModes.MILD, WaterModes.STANDARD, WaterModes.INTENSE]) 172 else: 173 supported_modes.extend([WaterModes.LOW, WaterModes.MEDIUM, WaterModes.HIGH]) 174 if features.is_custom_water_box_distance_supported: 175 # This is for devices that allow you to set a custom water flow from 0-100 176 supported_modes.append(WaterModes.CUSTOM) 177 if features.is_mop_shake_module_supported and features.is_mop_shake_water_max_supported: 178 supported_modes.append(WaterModes.EXTREME) 179 if features.is_smart_clean_mode_set_supported: 180 supported_modes.append(WaterModes.SMART_MODE) 181 if features.is_customized_clean_supported: 182 supported_modes.append(WaterModes.CUSTOMIZED) 183 184 return supported_modes
Get the valid water modes for the device - also known as 'water flow' or 'water level'
187def get_water_mode_mapping(features: DeviceFeatures) -> dict[int, str]: 188 """Get water mode mapping by supported feature set. 189 190 WaterModes contains aliases for multiple codes that share the same value 191 string (e.g. low can be 201 or 225). For water slide mode devices we need 192 explicit code mapping to preserve those slide-specific codes. 193 """ 194 if features.is_water_slide_mode_supported: 195 return {code: mode.value for code, mode in WATER_SLIDE_MODE_MAPPING.items()} 196 return {mode.code: mode.value for mode in get_water_modes(features)}
Get water mode mapping by supported feature set.
WaterModes contains aliases for multiple codes that share the same value string (e.g. low can be 201 or 225). For water slide mode devices we need explicit code mapping to preserve those slide-specific codes.
199def get_cleaning_mode_options(features: DeviceFeatures) -> list[CleaningMode]: 200 """Return the supported high-level cleaning modes for the device. 201 202 These options are the preferred user-facing choices because they bundle the 203 correct fan, water, and mop-route settings together for the device. Callers 204 should generally present these instead of mixing lower-level mode enums 205 unless they explicitly need fine-grained control. 206 """ 207 if not features.is_support_water_mode: 208 return [] 209 210 supported_water_modes = get_water_modes(features) 211 options = [CleaningMode.VACUUM, CleaningMode.VAC_AND_MOP] 212 if features.is_pure_clean_mop_supported: 213 options.append(CleaningMode.MOP) 214 if features.is_customized_clean_supported and WaterModes.CUSTOMIZED in supported_water_modes: 215 options.append(CleaningMode.CUSTOM) 216 if features.is_smart_clean_mode_set_supported and WaterModes.SMART_MODE in supported_water_modes: 217 options.append(CleaningMode.SMART_MODE) 218 return options
Return the supported high-level cleaning modes for the device.
These options are the preferred user-facing choices because they bundle the correct fan, water, and mop-route settings together for the device. Callers should generally present these instead of mixing lower-level mode enums unless they explicitly need fine-grained control.
221def get_mop_only_vacuum_mode(features: DeviceFeatures) -> VacuumModes: 222 """Return the vacuum mode used by the app for mop-only cleaning.""" 223 if not features.is_pure_clean_mop_supported: 224 raise RoborockUnsupportedFeature("Mop-only cleaning is not supported") 225 # Main-brush lift is a device capability, not an alternate fan-power 226 # command. The app still sends CleanModeZero (105) for mop-only cleaning. 227 return VacuumModes.OFF
Return the vacuum mode used by the app for mop-only cleaning.
261def resolve_cleaning_mode(cleaning_mode: str | CleaningMode) -> CleaningMode: 262 """Resolve a string or enum into a CleaningMode value.""" 263 if isinstance(cleaning_mode, CleaningMode): 264 return cleaning_mode 265 try: 266 return CleaningMode(cleaning_mode) 267 except ValueError as err: 268 raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode!r} is not supported") from err
Resolve a string or enum into a CleaningMode value.
271def get_cleaning_mode_parameters(cleaning_mode: CleaningMode, features: DeviceFeatures) -> list[dict[str, int]]: 272 """Get the RPC payload for switching the high-level cleaning mode.""" 273 if cleaning_mode not in get_cleaning_mode_options(features): 274 raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode.value!r} is not supported") 275 276 fan_power, water_box_mode, mop_mode = _get_clean_motor_mode_params(cleaning_mode, features) 277 params: dict[str, int] = {"fan_power": fan_power.code, "water_box_mode": water_box_mode.code} 278 if features.is_clean_route_setting_supported: 279 params["mop_mode"] = mop_mode.code 280 return [params]
Get the RPC payload for switching the high-level cleaning mode.
303def get_current_cleaning_mode( 304 clean_mode: int | VacuumModes | None, 305 water_mode: int | WaterModes | None, 306 mop_mode: int | CleanRoutes | None, 307 features: DeviceFeatures, 308) -> CleaningMode | None: 309 """Classify the current high-level cleaning mode from individual mode codes.""" 310 if not features.is_support_water_mode: 311 return None 312 clean_mode_enum = _resolve_clean_mode(clean_mode, features) 313 water_mode_enum = _resolve_mode_code(water_mode, WaterModes) 314 mop_mode_enum = _resolve_mode_code(mop_mode, CleanRoutes) 315 if clean_mode_enum is None or water_mode_enum is None: 316 return None 317 318 if is_smart_mode_set(water_mode_enum, clean_mode_enum, mop_mode_enum): 319 return CleaningMode.SMART_MODE 320 if is_mode_customized(clean_mode_enum, water_mode_enum, mop_mode_enum): 321 return CleaningMode.CUSTOM 322 if water_mode_enum != WaterModes.OFF: 323 try: 324 if clean_mode_enum == get_mop_only_vacuum_mode(features): 325 return CleaningMode.MOP 326 except RoborockUnsupportedFeature: 327 pass 328 if water_mode_enum == WaterModes.OFF: 329 return CleaningMode.VACUUM 330 return CleaningMode.VAC_AND_MOP
Classify the current high-level cleaning mode from individual mode codes.
333def is_mode_customized( 334 clean_mode: VacuumModes | None, 335 water_mode: WaterModes | None, 336 mop_mode: CleanRoutes | None, 337) -> bool: 338 """Check if any of the cleaning modes are set to a custom value.""" 339 return ( 340 clean_mode == VacuumModes.CUSTOMIZED 341 or water_mode == WaterModes.CUSTOMIZED 342 or mop_mode == CleanRoutes.CUSTOMIZED 343 )
Check if any of the cleaning modes are set to a custom value.
346def is_smart_mode_set( 347 water_mode: WaterModes | None, 348 clean_mode: VacuumModes | None, 349 mop_mode: CleanRoutes | None, 350) -> bool: 351 """Check if the smart mode is set for the given water mode and clean mode""" 352 return ( 353 water_mode == WaterModes.SMART_MODE 354 or clean_mode == VacuumModes.SMART_MODE 355 or mop_mode == CleanRoutes.SMART_MODE 356 )
Check if the smart mode is set for the given water mode and clean mode