Skip to content

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

Open

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.

Activity

  1. ratman-codes commented on Aug 21, 2026

    @ratman-codes

    You can simulate this now, but would much rather it be a discrete option.

  2. BlackRockCity commented on Aug 28, 2026

    @BlackRockCity

    I have a Saros 10R (roborock.vacuum.a144, firmware 02.50.56) and was able to capture the RPC used by the official Roborock iOS app for the "Vacuum followed by Mop" / "Clean then mop" mode.

    It appears this mode is controlled by app_set_clean_sequence_type, rather than set_clean_motor_mode.

    Enabling "Vacuum followed by Mop"

    When selecting "Vacuum followed by Mop" in the official Roborock app, I captured:

    {
      "method": "app_set_clean_sequence_type",
      "params": {
        "type": 1,
        "water_box_mode": 225,
        "mop_mode": 300,
        "fan_power": 102,
        "repeat": 1
      }
    }

    The robot returned ok.

    I then independently sent the equivalent command through Home Assistant using vacuum.send_command:

    action: vacuum.send_command
    target:
      entity_id: vacuum.saros_10r
    data:
      command: app_set_clean_sequence_type
      params:
        type: 1
        water_box_mode: 225
        mop_mode: 300
        fan_power: 102
        repeat: 1

    This successfully switched the Saros 10R into "Vacuum followed by Mop", and the official Roborock iOS app immediately reflected that mode.

    Disabling the sequence

    I also captured the official app switching from "Vacuum followed by Mop" back to ordinary "Vacuum".

    The app sent:

    {
      "method": "app_set_clean_sequence_type",
      "params": {
        "water_box_mode": 200,
        "mop_mode": 300,
        "fan_power": 102,
        "type": 0
      }
    }

    The robot again returned ok, and the app returned to Vacuum mode.

    So, at least on the Saros 10R:

    • type: 1 enables the sequential Vacuum-then-Mop mode.
    • type: 0 disables the sequential mode.
    • This is a separate RPC from the normal set_clean_motor_mode command.
    • repeat: 1 was present in the official app's enable command.
    • The official disable command I captured did not contain repeat.

    For comparison, I also captured the ordinary cleaning modes from the official app:

    Mode Command fan_power mop_mode water_box_mode
    Vacuum set_clean_motor_mode 102 300 200
    Vac + Mop set_clean_motor_mode 102 300 225
    Mop set_clean_motor_mode 105 300 225
    Vacuum followed by Mop app_set_clean_sequence_type 102 300 225

    The last mode additionally uses type: 1 and repeat: 1.

    This seems to provide the missing command mentioned in this issue. I can provide additional local-server/MQTT traces if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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