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)

Let’s get started!
- 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...
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.
- Part 1: https://staging.smarthomepursuits.com/how-to-setup-configure-roborock-s7-with-home-assistant/
- Part 2: https://staging.smarthomepursuits.com/roborock-s7-home-assistant-customize-map-card-create-zone-automations/
- Part 3: https://staging.smarthomepursuits.com/roborock-s7-home-assistant-automations-schedules-and-voice-commands/
- Part 5: https://staging.smarthomepursuits.com/roborock-sequentially-vacuum-multiple-rooms/
- Part 6: https://staging.smarthomepursuits.com/clean-vacuum-mop-card-home-assistant/
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.

Deep cleaning will stop the vacuum; it will mop only.
- Go to Configuration > Automations & Scenes.
- Click the Scripts tab.
- Add Script.
- Click the 3 dots in the top right-corner > Edit in YAML.
- Then, paste in the code below.
- 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)
- Configuration > Automations & Scenes > Helpers. Then click Add Helper > Dropdown.
- Give your dropdown a name like “Mop Rooms”.
- 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:
- Run the vacuum on the specific room
- Run the mop on the specific room
- 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.
- Zwave/Zigbee hub: Nortek GoControl HUSBZB-1
- Smart Plugs: Sonoff S31 Lite Zigbee
- Motion Sensors: Hue Indoor Motion
- Outdoor Camera: Amcrest IP5M Turret
- Robot Vacuum: Roborock S7
The full list of all Home Assistant compatible & recommended devices I use can be found on my Equipment List page.
Scrub intensity and vacuum mode are also available in that thread: https://community.home-assistant.io/t/s7-mop-control/317393/18
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!
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?
Most likely a formatting error somewhere, as all the scripts are literally copied/pasted from my production HA instance to my blog posts.
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?
Have anyone found out about this error? I’m getting the same thing and I cannot fix it
I added {% endif %} at the end and it worked
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?
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.
Thanks for your answer. I have done that but it still does not work. Just can’t figure it out
I am using segments instead of mopping zones. Should that also work or might this be the problem?
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.
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
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.
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.
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!
on which automation? does the error say which line?
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.
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.
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: >”.
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 🙂