Roborock Integration with Q Revo Vacuum / Mop - Segment cleaning

Problem Statement: As my roborock can do vacuuming and mopping, I’m trying to understand how to specify the cleaning mode when using segment cleaning. Has anyone figured this out?

What I’ve tried: I read all the documentation available here, https://www.home-assistant.io/integrations/roborock/ and the API command list from https://python-roborock.readthedocs.io/en/latest/api_commands.html. The few discovered API calls that I would logically think are connected to the problem statement have no details on the API attributes.

Example Code:

action:
  - service: vacuum.send_command
    data:
      command: app_segment_clean
      params:
        - segments:
            - 17
          repeat: 1
    target:
      device_id: 976d6012174bdfadc3b28a966561f617

Did you solved this? I´m going to buy the Q revo, and want this feature myself.

Can we get this one back to life?

I want to have the HA Scheduler Component to manage the cleaning schedule for the Q Evo. Using the latest version of the Scheduler component, you can send multiple commands.

I want to set up the schedule to vacuum one day and vacuum + mop on another day. However I am struggling to understand how Q Evo gets commands from HA.

Help would be appreciated!

Set it first before the segment cleaning. Not sure about Q revo but this is fine with my Roborock 7.

If you are asking can you do something like this:

clean segment 17 twice
clean and mop segment 19 three times

AFAIK, you cannot in one command. In my setup, I use an automation tied to some input_select helpers that have the list of options:

alias: Set Vacuum Mode
description: ""
trigger:
  - platform: state
    entity_id:
      - input_select.vac_mop_intensity
      - input_select.vac_speed
      - input_select.vac_mop_route
condition: []
action:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{trigger.entity_id == 'input_select.vac_mop_intensity'}}"
        sequence:
          - service: vacuum.send_command
            data:
              command: set_water_box_custom_mode
              params: |
                {% if states("input_select.vac_mop_intensity") == "Off" %}
                  {{ 200 }}
                {% elif states("input_select.vac_mop_intensity") == "Low" %}
                  {{ 201 }}
                {% elif states("input_select.vac_mop_intensity") == "Medium" %}
                  {{ 202 }}
                {% elif states("input_select.vac_mop_intensity") == "High" %}
                  {{ 203}}
                {% endif %}
            target:
              entity_id: vacuum.roborock_s7
      - conditions:
          - condition: template
            value_template: "{{trigger.entity_id == 'input_select.vac_mop_route'}}"
        sequence:
          - service: vacuum.send_command
            data:
              command: set_mop_mode
              params: |
                {% if states("input_select.vac_mop_route") == "Standard" %}
                  {{ 300 }}
                {% elif states("input_select.vac_mop_route") == "Deep" %}
                  {{ 301 }}
                {% elif states("input_select.vac_mop_route") == "Deep+" %}
                  {{ 303 }}
                {% endif %}
            target:
              entity_id: vacuum.roborock_s7
      - conditions:
          - condition: template
            value_template: "{{trigger.entity_id == 'input_select.vac_speed'}}"
        sequence:
          - service: vacuum.send_command
            data_template:
              command: set_custom_mode
              params: |
                {% if states("input_select.vac_speed") == "Silent" %}
                  {{ 101 }}
                {% elif states("input_select.vac_speed") == "Balanced" %}
                  {{ 102 }}
                {% elif states("input_select.vac_speed") == "Turbo" %}
                  {{ 103 }}
                {% elif states("input_select.vac_speed") == "Max" %}
                  {{ 104 }}
                {% elif states("input_select.vac_speed") == "Max+" %}
                  {{ 105 }}
                {% elif states("input_select.vac_speed") == "Off" %}
                  {{ 100 }}
                {% endif %}
            target:
              entity_id: vacuum.roborock_s7
mode: single

In the GUI like this:

I can change speed, mop, route and then select a list of rooms and execute. But as I said, you can send a list of rooms and modes (like vacuum Dining Room and then mop Kitchen).

NOTE: I use the numeric values but I would assume you could use names in some of the commands. The values I have I got by examining the code so I don’t know if they will work with other vacuums. I just set all the modes available and looked at things as a test. Looking at the state in developer tools, here you can see “104” maps to “max”:

3 Likes

Q Revo comments:

  1. set_custom_mode has to be 105 (and not 100, as noted for Roborock 7 above) to disable vacuum (for mop only).
  2. set_water_box_custom_mode values seems to be the same.

Hi @kbrown01, would you like to share the code used for the robot.
Thx Leo

Most of code is posted here: GitHub - kbrown01/Roborock-Interface: A collection of cards and automations for the Roborock in Home Assistant
While I have made a few changes, that is still relevant I believe,

Hi

I have a q revo and would like to get this setup. I’m not sure where to create the JSON file :

    "rooms": [
        {
            "name": "kitchen",
            "boolean": "input_boolean.vac_kitchen",
            "id": "17"
            },
        {
            "name": "dining_room",
            "boolean": "input_boolean.vac_dining_room",
            "id": "16"
            },
        {
            "name": "foyer",
            "boolean": "input_boolean.vac_foyer",
            "id": "18"
            },
        {
            "name": "laundry",
            "boolean": "input_boolean.vac_laundry",
            "id": "20"
            },
        {
            "name": "living_room",
            "boolean": "input_boolean.vac_living_room",
            "id": "19"
            },
        {
            "name": "master_bedroom",
            "boolean": "input_boolean.vac_master_bedroom",
            "id": "21"
            },
        {
            "name": "master_bathroom",
            "boolean": "input_boolean.vac_maste
r_bathroom",
            "id": "22"
            },
        {
            "name": "guest_bathroom",
            "boolean": "input_boolean.vac_guest_bathroom",
            "id": "23"
            }
    ]
}

I take it the rest sensor goes in configuration.yaml ?

Any help is appreciated

Create it anywhere your install can reach it. It really depends on your installation. It is not possible for me to guess what installation type you have and what path you would use.

Sorry if that seemed a bit of a daft or noob question. I’m still quite new to this and this is my first attempt at a rest sensor. I thought the file had to go in a certain location but then realized the sensor points to the file location.

I am running haos installed directly on a laptop using the x86 method. Not using windows or anything.

So I created a folder and pasted the file in the main directory using file editor. The path is shown in file editor as:
/homeassistant/roborock/roborock.json

I then added the sensor to configuration file in the sensors block like this:

- platform: rest
  name: roborock_rooms
  resource: http://192.xxx.xx.xxx:8123/homeassistant/roborock/roborock.json
  value_template: "{{ now() }}"
  json_attributes:
    - rooms

Does the file path look correct? The sensor shows up in my entities but when I check the state in developer tools the attributes only shows the friendly name. I don’t see the list of rooms and is numbers

Again, appreciate any help you can give

Edit: I just noticed this error in logs

Logger: homeassistant.components.rest.util
Source: components/rest/util.py:37
Integration: RESTful (documentation, issues)
First occurred: 17:17:55 (25 occurrences)
Last logged: 17:29:51

REST result could not be parsed as JSON

This is the file

{
    "rooms": [
        {
            "name": "kitchen",
            "boolean": "input_boolean.vac_kitchen",
            "id": "17"
            },
        {
            "name": "dining_room",
            "boolean": "input_boolean.vac_dining_room",
            "id": "16"
            },
        {
            "name": "foyer",
            "boolean": "input_boolean.vac_foyer",
            "id": "18"
            },
        {
            "name": "laundry",
            "boolean": "input_boolean.vac_laundry",
            "id": "20"
            },
        {
            "name": "living_room",
            "boolean": "input_boolean.vac_living_room",
            "id": "19"
            },
        {
            "name": "master_bedroom",
            "boolean": "input_boolean.vac_master_bedroom",
            "id": "21"
            },
        {
            "name": "master_bathroom",
            "boolean": "input_boolean.vac_master_bathroom",
            "id": "22"
            },
        {
            "name": "guest_bathroom",
            "boolean": "input_boolean.vac_guest_bathroom",
            "id": "23"
            }
    ]
}

OK. Mine is here:

.homeassistant/www/Roborock/roborock.json

Which in my installation is referenced as:

http://192.168.1.245:8123/local/Roborock/roborock.json

So the www directory under .homeassistant is mapped to “local” by Home Assistant.
This is where I put all my local JSON files that I use in sensors for various things.

A good way to test is just take a computer and surf to that URL. If I do that from a computer in my house, I get this:

Thanks! Got it working now.

I have setup the cards and automations. Just need to adapt the code to my setup and hopefully should all work.

Thanks for your help. I now have this all set up and working well.

A couple of things I noticed. If changes are made to the vac speed or mop intensity in the roborock app then these are not reflected in the card. So if you change settings in the app and then start a clean cycle from ha it will perform according to the roborock app settings and not the card. This has resulted in vac and the mop cleaning when I was expecting vac only. Is there any solution to this?

Edit:

So I think I have managed to come up with a workaround. My first thought was to edit the script to run the set vacuum mode automation first and then begin cleaning. I thought this would update the card settings to the revo but it seems the automation only runs when the inputs actually change. So what I have done now is:

  1. Create 3 input booleans: refresh vac speed, refresh mop intensity, refresh mop route.

  2. Edit the set vacuum mode automation. Added triggers for the input booleans turning on. Changed the condition in the 3 options to include the OR building block. The conditions are now the original template OR the corresponding input booleans is on.

  3. Edit the run vacuum script. Before the run command, add service to turn on and then off each of the input booleans. They need to be turned off again to be ready for the next trigger. I have a short delay between each action.

Now when the clean button is pressed, the booleans are turned on. If the clean modes in the roborock app are different to the card this will update them to match.
Then the clean will start according to the card settings.

This seems to work. I’m not very good with coding and such so if there is a better way of implementing this then please advise. Hope this helps

1 Like

Thanks for sharing this.

I’m also using this interface and have decided to use the core Roborock integration for my Roborock Q Revo.

In the guide for run vacuum script it uses roborock.vacuum_clean_segment service, but this is not supported by the core Roborck integration (I believe now it’s vacuum.send_command service)

What does your script look like for run vacuum from the GUI? Is there a new script that supports the same implementation but with the vacuum.send_command service?

Just reading the documentation, it would be like this:

service: vacuum.send_command
data:
  command: app_segment_clean
  params:
    - segments:
        - 22
        - 23
      repeat: 2
target:
  entity_id: **your vacuum entity**
1 Like

Thanks for sharing. I was trying to see how I could update the script to use the vacuum.send_command serice.

Currently the run vacuum script is:

alias: Run Vacuum
sequence:
  - service: roborock.vacuum_clean_segment
    data_template:
      segments: |
        {% set vacrooms = namespace(roomid=[]) %}
        {% for rooms in state_attr('sensor.roborock_rooms','rooms') -%}
          {% if is_state(rooms.boolean,'on') %}
            {% set room = rooms.id %}
            {% set vacrooms.roomid = vacrooms.roomid + [room] %}
          {% endif %}
        {%- endfor %}
        {{ vacrooms.roomid }}
    target:
      entity_id: vacuum.roborock_q_revo
mode: single

Well if you created the small JSON file that drives sensor.roborock_rooms then all you would do is something like this:

alias: Run Vacuum
sequence:
  - service: vacuum.send_command
    data_template:
      command: app_clean_segment
      params:
          segments: |
              {% set vacrooms = namespace(roomid=[]) %}
              {% for rooms in state_attr('sensor.roborock_rooms','rooms') -%}
                {% if is_state(rooms.boolean,'on') %}
                     {% set room = rooms.id %}
                     {% set vacrooms.roomid = vacrooms.roomid + [room] %}
                  {% endif %}
               {%- endfor %}
               {{ vacrooms.roomid }}
    target:
      entity_id: vacuum.roborock_q_revo
mode: single

NOTE: Untested as I do not use this, indenting may be off.

1 Like

Thanks for the help @kbrown01.

I’ve posted my latest progress here for using your interface with my Q Revo.

  1. I have setup the roborock_rooms sensor, which pulls the attributes from a JSON file sitting on my HA instance. I can see the room attribute on the HA UI.

  2. For the input_select helpers from your guide, I only had to create 1/3 (input_select.vac_speed). The mop route and mop intensity sensors actually come out of the box with the Roborock core integration. So I updated my dashboard widgets to point to those, and removed them from the automation script (see code below).

  3. I ended pulling in slightly different sensors into the dashboard that were available to my Q revo (see screenshots) and updated the YAML for the cards to show the different colours based on status’ I’ve mapped (happy to share the code if anyone is interested).

  4. I did also have to tweak the Set Vacuum Mode automation:

alias: Set Vacuum Mode
description: ""
trigger:
  - platform: state
    entity_id:
      - input_select.vac_speed
condition: []
action:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{trigger.entity_id == 'input_select.vac_speed'}}"
        sequence:
          - service: vacuum.send_command
            data_template:
              command: set_custom_mode
              params: |
                {% if states("input_select.vac_speed") == "Quiet" %}
                  {{ 101 }}
                {% elif states("input_select.vac_speed") == "Balanced" %}
                  {{ 102 }}
                {% elif states("input_select.vac_speed") == "Turbo" %}
                  {{ 103 }}
                {% elif states("input_select.vac_speed") == "Max" %}
                  {{ 104 }}
                {% elif states("input_select.vac_speed") == "Off" %}
                  {{ 105 }}
                {% endif %}
            target:
              entity_id: vacuum.roborock_q_revo
mode: single
  1. For the script, I’ve used the code shared by @kbrown01 above. This script uses vacuum.send_command which is what’s required for the Roborock core integration for the Revo Q. Note: I still can’t get my dashboard to start a cycle by hitting “Clean” under the Setup cycle cards. Here is the code just in case:
alias: Run Vacuum
sequence:
  - service: vacuum.send_command
    data:
      command: app_segment_clean
      params:
        - segments: |
            {% set vacrooms = namespace(roomid=[]) %}
            {% for rooms in state_attr('sensor.roborock_rooms','rooms') -%}
             {% if is_state(rooms.boolean,'on') %}
              {% set room = rooms.id %}
              {% set vacrooms.roomid = vacrooms.roomid + [room] %}
             {% endif %}
            {%- endfor %}
            {{ vacrooms.roomid }}
    target:
      entity_id: vacuum.roborock_q_revo
mode: single
icon: mdi:robot-vacuum

Things im still figuring out:

  1. I can’t use the “Setup cycle” widgets to start a cycle. I select my rooms, and hit “Clean” but nothing happens. The Logbook shows that the script started and ended, and I don’t see any errors in logs (the settings helpers/selections do work because I can see the app being updated). Separately, if I start a cycle from the map, the buttons update with the orange colours to show a cycle is in progress.

  2. I need to figure out how to draw my rooms on the map. I might re-implement this seperate from the guide shared.

Apologies as I’m very new to this. Hoping someone can help give me some pointers on direction.

Can you share the JSON file for the rooms? It sounds like you have not mapped the room names and segment id’s or something . Or possibly the naming convention I used is different as this hack depends on the naming of the input_boolean.

So in my JSON, I have an entry that is:

            "name": "kitchen",
            "boolean": "input_boolean.vac_kitchen",
            "id": "17"

So this test:

{% if is_state(rooms.boolean,'on') %}

would resolve to:

{% if is_state('input_boolean.vac_kitchen','on') %}

So if the input_boolean.vac_kitchen is toggled to on, then add the id ‘17’ to the list of rooms to vacuum.

I matched the boolean names (I think), what I was confused about is where “name” fields are used.

Here is the roborock.json for rooms:

"rooms": [
    {
        "name": "living_room",
        "boolean": "input_boolean.vac_living_room",
        "id": "16"
        },
    {
        "name": "dining_room",
        "boolean": "input_boolean.vac_dining_room",
        "id": "17"
        },
    {
        "name": "kitchen",
        "boolean": "input_boolean.vac_kitchen",
        "id": "18"
        },
    {
        "name": "main_floor_hallway",
        "boolean": "input_boolean.vac_main_floor_hallway",
        "id": "19"
        },
    {
        "name": "powder_room",
        "boolean": "input_boolean.vac_powder_room",
        "id": "20"
        },
    {
        "name": "entrance",
        "boolean": "input_boolean.vac_entrance",
        "id": "21"
        }
]
}

This is stored in /www/roborock/roborock.json. Here is the sensor on HA:

I’ve then added the sensor to my configuration.yaml

  # Roborock Room Sensor
  - platform: rest
    name: roborock_rooms
    resource: http://192.168.XX.XXX:8123/local/roborock/roborock.json
    value_template: "{{ now() }}"
    json_attributes:
      - rooms

I can browse to http://192.168.XX.XXX:8123/local/roborock/roborock.json from my local browser and see the JSON output.

Here is a screenshot of the logbook if it’s of any help…

Update: When I use the app_segment_clean command following the documentation from Home Assistant, it targets the corresponding room ID okay. It’s when i’m using the script. It’s either the dashboard isn’t passing the ID’s to the script, or the script i’m using isn’t formatted correctly? I found a typo on the script and still doesn’t work