Selective room cleaning with HA Assist and Xiaomi Roborock S6 using python script

Hey Google, clean the living room and the kitchen!

Wouldn’t you expect that to work out of the box with your new modern robot vacuum? With my Xiaomi Roborock S6 it didn’t so this is how I ended up getting it working using HA and IFTTT. This should work with any robot vacuum from Xiaomi with support for maps where rooms can be defined.

This is heavily inspired by Howto: Xiaomi vacuum zoned cleaning and if you want help with setting up the integrations the help you seek is likely in that thread.

Integrations required:

Please make sure the above is already set up and working as I won’t go through that here.

How to set up

IFTTT

Trigger: Google Assistant

Say a phrase with a text ingredient

What do you want to say?

  • Clean the $
  • Vacuum the $
  • Send Roborock to the $

What do you want the Assistant to say in response?

Alright! Sending Roborock to $ !

Service: Webhooks

Make a web request

URL

<Your public Home Assistant IFTTT webhook URL>

Method

POST

Content-type

application/json

Body

{ "action": "vacuum", "area": "{{TextField}}" }

Home Assistant

automations.yaml

- id: '123456789'
  alias: Clean room
  description: Start Roborock room cleaning triggered from Google Assistant (IFTTT)
  trigger:
  - event_data:
      action: vacuum
    event_type: ifttt_webhook_received
    platform: event
  condition: []
  action:
  - alias: ''
    entity_id: vacuum.roborock
    data_template:
      area: '{{ trigger.event.data.area }}'
    service: python_script.vacuum_room

python_scripts/vacuum_room.py

# Vacuum specific room(s), multiple names for a room can be used
roomConfig = {
    16: ["kitchen"],
    17: ["living room"],
    18: ["nursery", "kids room"]
}

entity_id = data.get("entity_id")
area = data.get("area").lower()

roomsToClean = []

for roomNumber, roomNames in roomConfig.items():
    for name in roomNames:
        if name in area: 
            roomsToClean.append(int(roomNumber))
            continue

if entity_id is not None and len(roomsToClean) > 0: 
    service_data = {"entity_id": entity_id, "command": "app_segment_clean", "params": roomsToClean}
    hass.services.call("vacuum", "send_command", service_data, False)

Questions

How do I know which room number corresponds to which room?

I figured it out by trial-and-error. Start the Mi Home app and open the Roborock map. In Home Assistant, go to Developer Tools > Services and then try:

Service: vacuum.send_command
Entity: vacuum.roborock
Service Data:

entity_id: vacuum.roborock
command: app_segment_clean
params: [16]

Try different numbers for params and each room should lit up in the app as Roborock begins room cleaning. You might have to wait a little bit before it shows on the map.

Hope this helps anyone and good luck!

4 Likes

I requested this feature to be native in HA, to replace xtend the vacuum platform, google traits are already supporting zone commands, for now we can use start and stop, it should be easy for devs to extend it to zones… That way we don’t need IFTTT at all, and we can speak native words

2 Likes

i tested the code that was changed by someone to test, so i loaded the google assistant component as a custom … below was the code that we changed hardcoded … it worked, i could say like, hey google,can you please vacuum the kitchen, without ifttt

offcourse it needs to be implemented the correct way with variables

    def sync_attributes(self):
        """Return StartStop attributes for a sync request."""
        return {'pausable':
                self.state.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
                & vacuum.SUPPORT_PAUSE != 0,
                'availableZones':['kitchen', 'living room']}



    async def execute(self, command, data, params):
        """Execute a StartStop command."""
        if command == COMMAND_STARTSTOP:
            if params['start']:
                if params.get('zone') is not None:
                    ZONES = {
                        'kitchen': [14600,17800,20450,21700],
                        'living room': [25480,17400,29530,22250],
                    }
                    await self.hass.services.async_call(
                        self.state.domain, vacuum_xiaomi.SERVICE_CLEAN_ZONE, {
                            ATTR_ENTITY_ID: self.state.entity_id,
                            'zone': [ZONES[params['zone']]],
                            'repeats': 1
                        }, blocking=True, context=data.context)
1 Like

Is the S6 now natively supported into the xiaomi component?

I added the S6 to the integration with a false error… But it appeared somehow in my entities, and I can access it from there

It worked! As it is my first automation with home assistant, I’m pretty happy and proud. Thank You!

But one thing that would be interesting as well, would be to be able to group rooms.

For example, I got a whole part of my flat where we mostly use it when guest comes for dinner and evenings. Let’s call it the “front”.

The front regroups the kitchen, living room and dining room. How would you do that?

roomConfig = {
    24: ["kitchen"],
    16: ["dining room"],
    18: ["living room"],
    20: ["guest toilet"],
    17: ["corridor"],
    22: ["master bedroom", "bedroom"],
    23: ["nursery", "kids room", "babys room"],
    21: ["personal toilet"],
    24,16,18,20: ["front"]
}

Good idea! I would have to change the script a little bit and add something like:

roomGroups = {
    "front": [16, 17, 18]
}

for roomGroupName, roomNumbers in roomGroups.items():
        if roomGroupName in area: 
                 roomsToClean.extend(roomNumbers)
                 continue

This is untested code FYI

1 Like

Thanks, @oscarb! I don’t know anything about python and you made it easy! The code works!

This is how the full python_scripts/vacuum_room.py looks like now for other people that might be wondering.

# Vacuum specific room(s), multiple names for a room can be used
roomConfig = {
    24: ["kitchen"],
    16: ["dining room"],
    18: ["living room"],
    20: ["guest toilet"],
    17: ["corridor"],
    22: ["master bedroom", "bedroom"],
    23: ["nursery", "kids room", "babys room"],
    21: ["personal toilet"]
}
roomGroups = {
    "front": [24, 16, 18, 20]
}

entity_id = data.get("entity_id")
area = data.get("area").lower()
roomsToClean = []
for roomNumber, roomNames in roomConfig.items():
    for name in roomNames:
        if name in area: 
            roomsToClean.append(int(roomNumber))
            continue

for roomGroupName, roomNumbers in roomGroups.items():
    if roomGroupName in area: 
        roomsToClean.extend(roomNumbers)
        continue
        
if entity_id is not None and len(roomsToClean) > 0: 
    service_data = {"entity_id": entity_id, "command": "app_segment_clean", "params": roomsToClean}
    hass.services.call("vacuum", "send_command", service_data, False)
2 Likes

Do we still need IFTTT for this?

Was never needed, you use the GA integration

I cant get the robot to show up in google home? What domain do I need to expose?

For the robot, just the vacuum domain…
For the rooms/zones , you can use scripts

well yeah, i tried that. The vaccum is not showing up in google home.

then there is something wrong with your GA integration, not the vacuum :slight_smile:

Possible, but all the other domains are working as expected.

but i have exposed scripts, every script is a room, i dont use the vacuum domain either

scripts, got it. Thanks :slight_smile:

@oscarb this is awesome thanks for putting in the work! I have this configured currently via IFTTT and ideally would want to get it setup to not depend on that server but I have to use IFTTT for some other things so that’s not critical currently. I do have multiple vacuums and was wondering if someone had some insight into how to split the python scripts and automations.yaml code to allow for that so i could say “vacuum kitchen” and it would know which vacuum to run.

Couldn’t be the problem that the vacuum is chinese version? Because I can’t use the GA integration either.

No thats not related at all