In this guide, I’ll show you how you can control the mop of your Roborock S7 vacuum/mop in Home Assistant. That’s right – it IS possible!

Chances are that if you have a Roborock S7, you were as sad as I was to hear that you can only control the vacuum in Home Assistant, not the mop. Well, the fine folks in this Home Assistant Community thread have found a way to do, so all credit to them. I’m going to show exactly how you can control the mopping mode of your Xiaomi Roborock S7 in Home Assistant.

(I took their ideas a little further – I added an input_select so I can quickly control which rooms to mop from Lovelace)

This image has an empty alt attribute; its file name is image-7.png

Let’s get started!

roborock S7 Robot Vacuum and Mop, 2500PA Suction & Sonic Mopping, Robotic Vacuum Cleaner with Multi-Level Mapping, Works with Alexa, Mop Floors and Vacuum Carpets in One Clean, Perfect for Pet Hai...
$649.99
  • Sonic Mopping Technology. Roborock S7 robot vacuum mops with the power of sound, scrubbing up to 3,000 times per minute. Fed by a 300 ml electronic water tank, stains from coffee to mud and more can...
  • Intelligent Mop Lifting. S7’s VibraRise mop lifts when a carpet is detected, so you can mop hard floors and vacuum carpets in a single clean. It also raises when cleaning is finished to avoid...
We earn a commission if you make a purchase, at no additional cost to you.
07/03/2023 04:18 pm GMT

Roborock S7 Vacuum in Home Assistant Series

In case you are finding this guide from a Google search, you may want to revisit the previous guides I’ve created.


Step 1: Create “Set Roborock Mopping Route” Script

This first script contains a two variables to control the “mopping route” of the vacuum: standard and deep. Later on we will create a 2nd script that calls this script. In the 2nd script, we will hardcode either standard or deep.

Image shown is from the MiHome app

Deep cleaning will stop the vacuum; it will mop only.

  1. Go to Configuration > Automations & Scenes.
  2. Click the Scripts tab.
  3. Add Script.
  4. Click the 3 dots in the top right-corner > Edit in YAML.
  5. Then, paste in the code below.
  6. Change the entity name of your vacuum (highlighted in green below)
alias: Set Roborock mopping route
fields:
  route:
    description: 'Mopping route - can be: standard | deep'
    example: standard
sequence:
  - alias: Config variables
    variables:
      config_mopping_route:
        standard: 300
        deep: 301
      mopping_route: '{{ config_mopping_route[route]}}'
  - choose:
      - alias: Invalid mopping route value
        conditions:
          - condition: template
            value_template: '{{ route not in config_mopping_route|list }}'
        sequence:
          - service: system_log.write
            data:
              message: >-
                Invalid mopping_route value '{{ route }}'. Valid values are {{
                config_mopping_route|list|join(', ') }}
              level: warning
              logger: roborock
    default:
      - alias: Set mopping route
        service: vacuum.send_command
        target:
          entity_id: vacuum.roborock_vacuum_a15
        data:
          command: set_mop_mode
          params: '[{{ mopping_route }}]'
mode: single

Then, save the script.


Step 2: Create Script To Mop An Area (Script 2)

If you followed along with part 2 of my Roborock series, you’ll know that I was able to grab the coordinates of each room in my house. If you haven’t got the coordinates yet, be sure to follow Step 3 of this guide.

Tip: If you’ve already added the Xiaomi Map Card and created zones on your map card, you can just edit the map card to find the coordinates:

The example code below will mop my entry with 2 passes.

Create a new script. Then, paste in this code.

  • Change out your entity names again (green)
  • Update coordinates of your room (orange)
  • Route: Hardcoded to deep mopping (purple) (no vacuum)
    • Can be changed to standard
alias: Mop Entryway
sequence:
  - service: xiaomi_miio.vacuum_remote_control_stop
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 2
      milliseconds: 0
  - service: script.set_mopping_route
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      route: deep
  - service: xiaomi_miio.vacuum_clean_zone
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      repeats: 2
      zone:
        - - 22023
          - 23769
          - 26332
          - 27671
mode: single
icon: mdi:robot-vacuum

This script will now be called script.mop_entryway


Step 3: Test Your Script

Before you continue, you should run this script manually to verify it works correctly. Obviously make sure the mop is installed, too.

In the Scripts tab, click the triangle.

You should hear an audible beep from your Roborock S7, and if you open the MiHome app, you’ll see “Fine mopping in progress. Vacuuming stopped”, which means deep clean has been selected.

If it doesn’t work, you may need to go into File Editor > Scripts.yaml. It shouldn’t matter, but if your script name has a bunch of numbers instead of a name, you can simply change it to something like mop_livingroom, mop_kitchen, etc.


Step 4: Duplicate Step #3 Script for Each Room

After you confirm the script works for one room, go ahead and copy the YAML from Step 2 into a new script. Do this for each room, changing the Alias and Coordinates each time.

Once complete, you should have several scripts named like:

  • script.mop_office
  • script.mop_dining_room
  • script.mop_entryway

Step 5: Create Input Select to Mop Each Zone (or rooms)

  1. Configuration > Automations & Scenes > Helpers. Then click Add Helper > Dropdown.
  2. Give your dropdown a name like “Mop Rooms”.
  3. Add as many rooms as you created scripts for

Your entity name is now:

input_select.mop_rooms

Then click Create.


Step 6: Create Automation to Trigger Scripts

Next, you need to create an automation that will run “Run Mop Zone”. Basically, whenever you choose a room from the dropdown, it will call this scripts you created in steps 2 and 3.

Create a new automation and paste this YAML. The data_template code is very particular on how it’s formatted.

  • Change robot entity name
  • Change script names
  • Change these to match input_select names
  • Input select name
alias: Run Mop Zone
description: ''
trigger: []
condition: []
action:
  - service: vacuum.stop
    target:
      entity_id: vacuum.roborock_vacuum_a15
  - delay:
      hours: 0
      minutes: 0
      seconds: 3
      milliseconds: 0
  - service: script.turn_on
    data_template:
      entity_id: >
        {% if states.input_select.mop_rooms.state == "Office" %}
        script.mop_office {% elif states.input_select.mop_rooms.state ==
        "Dining Room" %} script.mop_dining_room  {% elif
        states.input_select.mop_rooms.state == "Entry" %}
        script.mop_entryway 
mode: single

Step 7: Create Lovelace Button to Trigger Automation based on input select

Next, it’s time to create a Lovelace button you can click to run the mop.

I found a simple Grid card setup works pretty. Here’s the YAML for it. If you’ve been following my guide exactly, you should only need to change out the entity ID of your robot vacuum with your own.

On your Lovelace dashboard, Add Card > Manual > paste the code below.

type: grid
cards:
  - type: entities
    entities:
      - entity: input_select.mop_rooms
  - type: grid
    cards:
      - type: button
        tap_action:
          action: call-service
          service: automation.trigger
          service_data: {}
          target:
            entity_id: automation.run_mop_zone
        entity: vacuum.roborock_vacuum_a15
        name: Start Mop
      - type: button
        tap_action:
          action: call-service
          service: vacuum.stop
          service_data: {}
          target:
            entity_id: vacuum.roborock_vacuum_a15
        name: Stop Mop
        entity: vacuum.roborock_vacuum_a15
      - type: button
        tap_action:
          action: call-service
          service: vacuum.return_to_base
          service_data: {}
          target: {}
        name: Return to Dock
        entity: vacuum.roborock_vacuum_a15
square: false
columns: 1

Step 8: Reset Mop Mode & Map Route

It’s important to note that once you run your mop, it will stay in “deep” mopping mode, which means it won’t vacuum.

So, you can create another script that sets it back to “standard”. Whenever it switches from Deep to Standard, the last used “vacuum power” and “scrub intensity” will go back to whatever it was previously set to. For example, if the last time you vacuumed you had it set to “turbo” and Scrub Intensity was “intense”, running this script will go back to that, like this:

So, the first thing we need to do is create a new script. This script was created by someone in the Community forum, but it basically lets you configure the scrubbing intensity/vacuum power. We are going to call this one later one.

Script To Set Mopping Mode

Copy and paste this into a new script exactly as is. Just change out the entity ID.

alias: Set Roborock manual vacuum and mopping settings
fields:
  vacuum:
    description: 'Vacuum mode - can be: silent | balanced | turbo | max'
    example: max
  mopping:
    description: 'Mopping mode - can be: off | low | medium | high'
    example: 'off'
sequence:
  - alias: Config variables
    variables:
      config_vacuum:
        silent: 101
        balanced: 102
        turbo: 103
        max: 104
      config_mopping:
        'off': 200
        low: 201
        medium: 202
        high: 203
      vacuum_mode: '{{ config_vacuum[vacuum] }}'
      mopping_mode: '{{ config_mopping[mopping] }}'
  - choose:
      - alias: Invalid vacuum value
        conditions:
          - condition: template
            value_template: '{{ vacuum not in config_vacuum|list }}'
        sequence:
          - service: system_log.write
            data:
              message: >-
                Invalid vacuum value '{{ vacuum }}'. Valid values are {{
                config_vacuum|list|join(', ') }}
              level: warning
              logger: roborock
      - alias: Invalid mopping value
        conditions:
          - condition: template
            value_template: '{{ mopping not in config_mopping|list }}'
        sequence:
          - service: system_log.write
            data:
              message: >-
                Invalid mopping value '{{ lavaggio }}'. Valid values are {{
                config_mopping|list|join(', ') }}
              level: warning
              logger: roborock
    default:
      - alias: Set vacuum mode
        service: vacuum.send_command
        target:
          entity_id: vacuum.roborock_vacuum_a15
        data:
          command: set_custom_mode
          params: '[{{ vacuum_mode }}]'
      - alias: Set mopping mode
        service: vacuum.send_command
        target:
          entity_id: vacuum.roborock_vacuum_a15
        data:
          command: set_water_box_custom_mode
          params: '[{{ mopping_mode }}]'
mode: single

Automation to Reset Mopping Route & Mopping Mode

This automation will call both scripts you created earlier (script.set_mopping_route) and (script.roborock_set_manual_mode).

As you can see in the first service: section of the below automation, it is turning mopping off and setting the vacuum to max power. (variables are pulled from the script above)

The second service: section is setting the mop route to Standard instead of deep.

alias: 'Reset Vacuum: Turn off Mop and Turn to Max'
description: ''
trigger: []
action:
  - service: script.roborock_set_manual_mode
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      vacuum: max
      mopping: 'off'
  - service: script.set_mopping_route
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      route: standard

You can then add that automation to a Lovelace button.

  • Tap Action = Call Service
  • Service: automation.trigger
  • Target: The “Reset Vacuum Turn off Mop & Set to Max” automation above.

Basic Usage

At this point of my Roborock S7 series, you should be able to control all aspects of your vacuum – both the vacuuming and the mopping.

I don’t automate vacuum/mopping yet (simply because I’m not sure if there are kids toys or whatever on the floor, and my robovac battery doesn’t usually last long enough ), so I typically:

  1. Run the vacuum on the specific room
  2. Run the mop on the specific room
  3. Once complete, press the Reset Mop button and remove the mop pad

Reminder: You can add up to 5 rooms to an input_select script at a time. So if you want to put the kitchen, office, entry, breakfast, and game room into a single input_select, you can do that. Do this for both vacuuming and mopping. Then, you’d create a new input select called something like “Vacuum bedrooms” and “Mop Bedrooms”

And here’s the YAML for the grid view above if you’d like to set it up just like mine.

type: grid
cards:
  - type: entities
    entities:
      - entity: input_select.vacuum_rooms
      - entity: input_select.mop_rooms
  - type: grid
    cards:
      - type: button
        tap_action:
          action: call-service
          service: automation.trigger
          service_data: {}
          target:
            entity_id: automation.run_vacuum_zone
        entity: vacuum.roborock_vacuum_a15
        name: Start Vacuum
      - type: button
        tap_action:
          action: call-service
          service: vacuum.stop
          service_data: {}
          target:
            entity_id: vacuum.roborock_vacuum_a15
        name: Stop
        entity: vacuum.roborock_vacuum_a15
      - type: button
        tap_action:
          action: call-service
          service: vacuum.return_to_base
          service_data: {}
          target: {}
        name: Return to Dock
        entity: vacuum.roborock_vacuum_a15
        icon: mdi:robot-happy
      - type: button
        tap_action:
          action: call-service
          service: automation.trigger
          service_data: {}
          target:
            entity_id: automation.run_mop_zone
        entity: vacuum.roborock_vacuum_a15
        name: Start Mop
        icon: mdi:robot-vacuum-variant
      - type: button
        tap_action:
          action: call-service
          service: automation.trigger
          service_data: {}
          target:
            entity_id: automation.test_vacuum_settings
        entity: vacuum.roborock_vacuum_a15
        name: Reset Mop to Vacuum Mode
        icon: mdi:robot-vacuum-variant
square: false
columns: 1

Wrapping Up

Hopefully you guys enjoyed this guide and were able to control your S7 mop in Home Assistant as well!

If you’d like to take it one step further, you can even control the mopping aspect from Google Assistant using your voice. I have a guide on how to trigger vacuuming from Home Assistant with Google Assistant, but you can follow that guide exactly and simply change out the script names with mop scripts you created.

I know there is a TON of info in these Roborock guides, so I may create a shortened/simplified guide with just the yaml later on.


My Favorite Home Assistant Devices

Below are some of the Home Assistant-compatible devices I personally use in my home. I highly recommend each of them.

The full list of all Home Assistant compatible & recommended devices I use can be found on my Equipment List page.

Similar Posts

21 Comments

    1. Awesome, I just reread that post after a few days and was able to successfully configure scrub intensity and vacuum modes. I just updated my guide and some YAML in it to reflect that. Thanks again!

  1. Run Mop Zone script is throwing this error – Message malformed: template value should be a string for dictionary value @ data[‘action’][2][‘data_template’]

    any ideas?

    1. Most likely a formatting error somewhere, as all the scripts are literally copied/pasted from my production HA instance to my blog posts.

    2. Soepgroenten says:

      did you ever find out what went wrong? Even if i 1>1 copy/paste the script of this (I must say very well explained) blogpost I do exactly get the same issue.
      I discovered the issue relies in the part after the “entity_id: >” (line 16) starting at line 17. and before the last line stating mode: single.
      In other words the issue relies in the whole else/if part of the script.

      @Danny:
      Could it be the copy/paste action messed something up due to the editor in your CMS system?

      1. Have anyone found out about this error? I’m getting the same thing and I cannot fix it

      2. I added {% endif %} at the end and it worked

  2. I don’t know why, but I just can’t get it to work. The vacuum makes the beeping sound when I set it to deep cleaning mode, but the xiaomi app just doesn’t show anything about the mopping mode. (It does when I select mopping from the app) And also the vacuum is still vacuuming. Any Ideas what could be the problem?

    1. The first thing I would do is rename the new scripts inside your scripts.yaml folder. (File editor > scripts.yaml) For example, they are usually named with numbers. Find the new new script you added inside the scripts.yaml and name it set_mopping_route. Because in Step 2 of this guide, it looks for that name.

      1. Thanks for your answer. I have done that but it still does not work. Just can’t figure it out

        1. I am using segments instead of mopping zones. Should that also work or might this be the problem?

          1. That might be the problem.. I am using coordinates/zones inside my individual room scripts. A quick way to test is by grabbing the coordinates of a very small area near your vacuum and plugging those into a new room script (i.e. – Step 2 of this guide). Then test is out and see if it triggers correctly.

  3. I have done that. It was already named correctly. Do you have any other ideas? It would be really awesome if I could start mopping from within home assistant, especially since I implemented the compact vacuum card you showed in this guide! Thanks in advance1

    1. It doesn’t work for me either. I’ve tried to set vacuum mode to “off”, mopping to “intense” and then route to “deep” and it seems to be working.

  4. It doesn’t work for me either. I’ve tried to set vacuum mode to “off”, mopping to “intense” and then route to “deep” and it seems to be working.

  5. Nissar Khurrami says:

    I am also getting the not a valid value for dictionary value @ data[‘entity_id’] error for the automations I have created based on the guides.

    What am I doing wrong?

    Please, help!

    1. on which automation? does the error say which line?

      1. Nissar Khurrami says:

        Hi Danny,

        I have the following 5 automations following the fine guideline here:

        Mop Rooms
        Mop Zones
        Vacuum Rooms
        Vacuum Zones
        Reset: Turn Off Mop & Turn To Max

        I have the following scripts:

        12 scripts for vacuuming individual rooms
        12 for mopping individual rooms
        4 scripts for vacuuming zones (consisting of 3 rooms each)
        4 scripts for mopping zones (consisting of 3 rooms each)
        1 script Set Roborock Manual Vacuum & Mopping Settings
        1 script Set Roborock Mopping Route

        I have tested the scripts and they run fine.

        All of the automations except the Reset: Turn Off Mop & Turn To Max fail with the error not a valid value for dictionary value @ data[‘entity_id’].

        I am not allowed to paste the YAML code here, but it is the one that is described in above under (Step 6: Create Automation to Trigger Scripts). In that YAML code, I understood from the comments that {% endif %} was missing, which I have added. But it is still giving the me error.

        1. So I pasted my code from both my website and what I have in HA into Notepad++ and ran the Compare plugin. It looks like the only difference is that my currently working automations have a data: {} in the Action step. See here: https://imgur.com/a/LL0jJJB

          If adding that fixes it for your automations, I’ll update the code on my articles.

      2. Nissar Khurrami says:

        For some reason, my comments are getting deleted.
        @Danny: It is the automations under step 6 above that is giving me an error. More specifically the part with “data_template:
        entity_id: >”.

  6. Hi Danny,
    You are right, you do not have “data” and the final “endif” in your automation. I had added those in my YAML code, but I realised that during that process, I had deleted the “.state” in my input_selects which was giving me the problem.
    Now, made it through this part, and moving forward 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *