Skip to content

Support the "Clean then mop" cleaning mode (feature bit 93, is_clean_then_mop_mode_supported) #914

Description

@skolodziej

Summary

Recent Roborock devices expose a fourth high-level cleaning mode in the Roborock app, in
addition to Vacuum, Vacuum and mop and Mop:

"Vac then mop" / "Clean then mop" — the robot first runs a vacuum-only pass with the mop
pads detached in the dock, then returns, attaches the pads and runs a second mop-only pass over
the same area.

This is functionally different from vac_and_mop, which is a single pass with the pads attached
the whole time. python-roborock already parses the capability bit for this mode, but nothing in
the library can read or set it, so downstream consumers (notably the Home Assistant Roborock
integration) cannot offer it.

Device

  • Roborock Saros 10R + dock
  • Firmware 02.52.86
  • python-roborock 6.2.1
  • Reached via the official Home Assistant Roborock integration

Evidence that the device supports it

From the Home Assistant diagnostics download for the device (traits.device_features):

isCleanThenMopModeSupported: True
isAutoTearDownMopSupported:  True

isAutoTearDownMopSupported is the mechanical prerequisite (dropping the pads in the dock), and
the mode is selectable and works correctly from the Roborock app on this device.

Current state in the library

roborock/device_features.py declares the capability:

CLEAN_THEN_MOP_MODE = 93          # NewFeatureStrBit

is_clean_then_mop_mode_supported: bool = field(
    metadata={"new_feature_str_bit": NewFeatureStrBit.CLEAN_THEN_MOP_MODE}
)

A search across the package shows is_clean_then_mop_mode_supported is never referenced anywhere
outside its own declaration — no getter, no setter, no enum member.

roborock/data/v1/v1_clean_modes.py has no corresponding value:

class CleaningMode(StrEnum):
    VACUUM = "vacuum"
    VAC_AND_MOP = "vac_and_mop"
    MOP = "mop"
    CUSTOM = "custom"
    SMART_MODE = "smart_mode"

get_cleaning_mode_parameters() builds a set_clean_motor_mode payload from
{fan_power, water_box_mode, mop_mode}. The CleanRoutes codes (300 standard, 301 deep,
302 custom, 303 deep_plus, 304 fast, 305 deep_plus_cn, 306 smart_mode) contain nothing that maps
to a two-pass sequence, so the mode does not appear to be reachable through that command.

What I could not determine

I could not identify which DP carries the setting.

get_status on this device returns the following mode-related fields while a segment clean is
running:

fanPower: 102        # balanced
waterBoxMode: 235    # PURE_WATER_FLOW_MIDDLE
mopMode: 300         # CleanRoutes.STANDARD

get_current_cleaning_mode() classifies this as vac_and_mop. No other field in the status
payload obviously encodes the two-pass behaviour; undocumented candidates in Status are
common_status, replenish_mode, subdivision_sets and kct.

Probing interactively from Home Assistant is not possible: async_send_command in the Roborock
integration returns None and discards the device response, so read commands such as
get_clean_motor_mode produce no visible output.

Three commands are defined in RoborockCommand but never used anywhere in the library, and may
be relevant:

  • get_clean_sequence / set_clean_sequence
  • get_mop_motor_status / set_mop_motor_status
  • set_mop_template_id

I am happy to capture diagnostics in both modes and diff them, or to run specific commands against
the device, if someone can point me at the right ones.

Request

Add support for the "clean then mop" mode, gated on is_clean_then_mop_mode_supported, so that it
can be surfaced as a fourth option alongside vacuum, vac_and_mop and mop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions