My hacky addition of my roborock s7 to HomeKit

Hi!
Have just started using home assistant, mainly so I can expose and integrate all my devices to HomeKit. I have been looking online for a solution to exposing my roborock s7 to HomeKit, however all the results I found were using Homebridge to expose it as a fan and I don’t want to set up homebridge just for this use. I also couldn’t find any updated topics on home assistant about this (taking advantage of preset modes particularly) so here’s my hacky code i made for this. I know it’s very possible to make this more efficient, however this is my first time making a template. (Also first post here).

Also, I haven’t included speed at all in this as I have configured custom speeds and suction for each room using the mi home app.

#configuration.yaml

#for tracking preset mode
input_select:
  roborock_s7_preset_mode:
    name: "Roborock preset mode"
    options:
      - "no bedroom clean"
      - "full clean"
      - "cleaning kitchen"
      - "cleaning x room"

fan:
  -platform: template
  fans:
      roborock_s7:
        friendly_name: "Ron Sweepsley"
        value_template: "{%if states('vacuum.robovac') == 'cleaning' %}on{%elif states('vacuum.robovac') == 'paused' %}on{%else %}off{% endif %}"
        preset_mode_template: "{{ states('input_select.roborock_s7_preset_mode') }}"
        # turn_on and turn_off both dock vacuum as turn_on would activate when disabling a preset.
        turn_on:
          service: vacuum.return_to_base
          data: {}
          target:
            device_id: device id
        turn_off:
          service: vacuum.return_to_base
          data: {}
          target:
            device_id: device id
        # calls a script to process a different cleaning command depending on preset mode
        set_preset_mode:
          service: script.roborock_clean
          data:
            preset_mode: "{{ preset_mode }}"
        preset_modes:
          - "no bedroom clean"
          - "full clean"
          - "cleaning kitchen"
          - "cleaning x bedroom"

And then below is the scipt.roborock_clean that is called when activating a preset mode. This was made in visual editor, probably can also be more efficient.

sequence:
  - service: input_select.select_option
    target:
      entity_id: input_select.roborock_s7_preset_mode
    data:
      option: '{{ preset_mode }}'
  - choose:
      - conditions:
          - condition: state
            entity_id: input_select.roborock_s7_preset_mode
            state: no bedroom clean
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            target:
              device_id: deviceid
            data:
              segments:
                - 16
                - 21
                - 23
                - 24
                - 25
      - conditions:
          - condition: state
            entity_id: input_select.roborock_s7_preset_mode
            state: full clean
        sequence:
          - service: vacuum.start
            target:
              device_id: deviceid
            data: {}
      - conditions:
          - condition: state
            entity_id: input_select.roborock_s7_preset_mode
            state: cleaning kitchen
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 24
            target:
              device_id: deviceid
      #  below is for a specific bedroom
      - conditions:
          - condition: state
            entity_id: input_select.roborock_s7_preset_mode
            state: cleaning x bedroom
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 17
            target:
              device_id: deviceid
    default: []
  - service: fan.set_preset_mode
    data: 'null'
    target:
      entity_id: fan.roborock_s7
mode: queued
alias: Roborock Clean
max: 10

Anyway, I hope this helps someone who’s trying to do what i did. Any suggestions to improve this are welcome :slight_smile:.

Thought I would come back to this, with two main updates:

  1. remove the reliance on an input select list.
  2. added ability to queue 1 room once cleaning has started.

First is the config.yaml part. The preset_mode_template does what I want it to do, however it doesn’t actually do it the way it’s written in code. I would like it do be indicative of the room it’s currently cleaning or queued to clean, but then reset to none or null when finished cleaning.

Somehow tho the error from this preset_mode_template means that preset mode is never changed, however can still be set, and therefore passed to the following script

#config
fan:
  - platform: template
    fans:
      roborock_s7:
        friendly_name: "Ron Sweepsley"
        #value_template: shows status of vacuum
        value_template: "{%if states('vacuum.robovac') == 'cleaning' %}on{%elif states('vacuum.robovac') == 'paused' %}on{%else %}off{% endif %}"
        #prese_mode_template: this is the code I thought would make preset modes turn off when docked,
        # however, it only works as is makes a specifically good error that resets the preset mode.. not quite sure how
        preset_mode_template: "{%if states('vacuum.robovac') == 'docked' %}null{% else %}{{ this.preset_modes.roborock_s7 }}{% endif %}"
        #return vacuum to base on turn on/off
        turn_on:
          service: vacuum.return_to_base
          data: {}
          target:
            device_id: ____
        turn_off:
          service: vacuum.return_to_base
          data: {}
          target:
            device_id: _____
        # when preset mode set, calls script to start cleanings
        set_preset_mode:
          service: script.roborock_clean
          data:
            preset_mode: "{{ preset_mode }}"
        # different preset modes for different rooms/zones
        preset_modes:
          - "room 1"
          - "room 2"
          - "room 3"
          - "room 4"
          - "room group 1"
          - "room group 2"
          - "room group 3"
          - "full clean"
          - "zone clean"

Here is the updated script as well, it is now run parallel, and can queue a room once cleaning has actually started. Also I have used template conditions here instead of the previous state conditions to remove reliance on the input_select.

#script
sequence:
  - service: fan.set_preset_mode
    data:
      preset_mode: "{{ preset_mode }}"
    target:
      entity_id: fan.roborock_s7
  - if:
      - condition: state
        entity_id: vacuum.robovac
        state: cleaning
    then:
      - wait_for_trigger:
          - platform: state
            entity_id:
              - vacuum.robovac
            to: returning
          - platform: state
            entity_id:
              - vacuum.robovac
            to: docked
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room group 1' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            target:
              device_id: ____
            data:
              segments:
                - 22
                - 23
                - 24
                - 25
                - 26
                - 27
                - 30
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'full clean' }}"
        sequence:
          - service: vacuum.start
            target:
              device_id: ____
            data: {}
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room 2' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 25
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room 3' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 18
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room 4' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 17
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room 5' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments: 29
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room group 2' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments:
                - 23
                - 24
                - 25
                - 26
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'room group 3' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_segment
            data:
              segments:
                - 24
                - 26
            target:
              device_id: ____
      - conditions:
          - condition: template
            value_template: "{{ preset_mode == 'zone clean' }}"
        sequence:
          - service: xiaomi_miio.vacuum_clean_zone
            data:
              zone:
                - - 24900
                  - 24400
                  - 26000
                  - 25500
              repeats: 1
            target:
              device_id: ____
    default: []
mode: parallel
alias: Roborock Clean
max: 10
icon: mdi:robot-vacuum

Anyway as before if there are any templating geniuses who could get this running properly that would be awesome, I just haven’t found anything else that integrates a roborock into HomeKit with room control like this anywhere, so this is my wacky solution

1 Like

:slight_smile: I been looking for this.

Got everytime a fan/set_preset_mode connection lost if I try it via the webgui- any tip?

if i try to call the service via services it comes unable to find service: script.roborock_clean

I have copied (and changed entities) your script to the scripts.yaml

and copied the configuration in configuration yaml

Here is what I did to let my Roborock S8 work in Homekit and Alexa:

Created for every room and the whole house a script. Also of return to base:

#  ██████╗  ██████╗ ██████╗  ██████╗ ██████╗  ██████╗  ██████╗██╗  ██╗    ███████╗ █████╗ 
#  ██╔══██╗██╔═══██╗██╔══██╗██╔═══██╗██╔══██╗██╔═══██╗██╔════╝██║ ██╔╝    ██╔════╝██╔══██╗
#  ██████╔╝██║   ██║██████╔╝██║   ██║██████╔╝██║   ██║██║     █████╔╝     ███████╗╚█████╔╝
#  ██╔══██╗██║   ██║██╔══██╗██║   ██║██╔══██╗██║   ██║██║     ██╔═██╗     ╚════██║██╔══██╗
#  ██║  ██║╚██████╔╝██████╔╝╚██████╔╝██║  ██║╚██████╔╝╚██████╗██║  ██╗    ███████║╚█████╔╝
#  ╚═╝  ╚═╝ ╚═════╝ ╚═════╝  ╚═════╝ ╚═╝  ╚═╝ ╚═════╝  ╚═════╝╚═╝  ╚═╝    ╚══════╝ ╚════╝ 
###########################################################################################
# VACUUM CLEANER ACTIONS FOR HOMEKIT AND ALEXA
###########################################################################################
alexa_clean_all:
  alias: "Clean all"
  icon: mdi:start
  sequence:
    - service: vacuum.start
      target:
        entity_id: vacuum.roborock_s8

alexa_return_base:
  alias: "Return to base"
  icon: mdi:start
  sequence:
    - service: vacuum.return_to_base
      target:
        entity_id: vacuum.roborock_s8

alexa_clean_kithcen: # SEGMENT 16
  alias: "Clean kitchen"
  icon: mdi:start
  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 16

    - delay: "00:00:40"

    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: max

alexa_clean_hallway: # SEGMENT 22
  alias: "Clean hallway"
  icon: mdi:start
  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 22

alexa_clean_bedroom: # SEGMENT 21
  alias: "Clean bedroom"
  icon: mdi:start

  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 21

alexa_clean_diningroom: # SEGMENT 20
  alias: "Clean diningroom"
  icon: mdi:start

  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 20

alexa_clean_livingroom: # SEGMENT 19
  alias: "Clean livingroom"
  icon: mdi:start
  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 19

alexa_clean_toilet: # SEGMENT 17
  alias: "Clean toilet"
  icon: mdi:start
  sequence:
    - service: vacuum.set_fan_speed
      target:
        entity_id: vacuum.roborock_s8
      data:
        fan_speed: balanced

    - service: roborock.vacuum_clean_segment
      target:
        entity_id: vacuum.roborock_s8
      data: 
        segments: 17

Created a second bridge for homekit where only those scripts are exposed

- port: 21111
  name: "Roborock"
  mode: bridge
  filter:
    include_entities:
      - script.alexa_clean_bedroom
      - script.alexa_clean_hallway
      - script.alexa_clean_kithcen
      - script.alexa_clean_diningroom
      - script.alexa_clean_livingroom
      - script.alexa_clean_toilet
      - script.alexa_clean_all
      - script.alexa_return_base

For Alexa:

smart_home:
  endpoint: https://api.eu.amazonalexa.com/v3/events
  client_id: !secret alexa_smart_home_id
  client_secret: !secret alexa_smart_home_secret
  filter:
    include_entities:
      - script.alexa_clean_bedroom
      - script.alexa_clean_hallway
      - script.alexa_clean_kithcen
      - script.alexa_clean_diningroom
      - script.alexa_clean_livingroom
      - script.alexa_clean_toilet
      - script.alexa_clean_all
      - script.alexa_return_base

Those scripts shown in Homekit and Alexa. I can ask Siri now:

Hey Siri, clean all or Hey Siri clean living room, etc…
or Alexa clean all or Alexa clean kitchen, etc…

You can even use them in automations in Homekit. When you leave the house run them.

Maybe this will help :slight_smile:

1 Like

Yeah nice work @poudenes , I have actually changed to be more similar to this. I’ve forgotten to update this thread for a while. I still use the script I shared here, however I don’t use the fan template thing at all. Instead I have just set up a bunch of different dummy switches that all trigger the script… I’ll try put it all together again to post sometime.

1 Like

Out of curiosity @poudenes can you start multiple rooms at the same time and the vacuum will clean those rooms? Or will it only clean one?

Anyway, here is the script I currently use. There’s a few steps to set up… 1) you’ll have to make input_booleans in the helpers section of HA for each of your rooms 2) add them to the script by replacing “input_boolean.clean_room_x” for each occurrence in the script with your rooms 3) go through and change the segment numbers to be the appropriate room numbers for each room (there are better guides out there to determine these). 4) add the device ID for the vacuum in the appropriate spots 5) add the entity id for the vacuum in the appropriate spots 6) You can also add additional rooms as required by simply copying a choose condition with the condition of the input_boolean.

Benefit of this automation is that it allows you to flick as many rooms to clean as you want, and the vacuum should go through and clean each of them. Order is determined by either which is turned on first, and then by which is first in the CHOOSE action. Also I can skip/stop cleaning a room by turning it’s switch off

In homekit, I also set up scenes for Siri, so I can say “Hey Siri, ‘Start cleaning room 1’” in addition to the default “Hey Siri, ‘clean room 1’” which should work if your input_boolean is named “clean room 1”.

@xsas if your still interested in this and haven’t found a different solution, this should work for you better than the previous versions

alias: Roborock S7 All-in-one
description: ""
trigger:
  - platform: state
    entity_id: # rooms to set up as input_booleans
      - input_boolean.clean_room_1
      - input_boolean.clean_room_2
      - input_boolean.clean_room_3
    to: "on"
condition:
  - condition: state
    entity_id: # vacuum entity id
    state:
      - docked
      - returning
action:
  - repeat:
      until:
        - condition: state
          entity_id: # vacuum entity id
          state: docked
          for:
            hours: 0
            minutes: 0
            seconds: 0
      sequence:
        - choose:
            - conditions:
                - condition: state
                  entity_id: input_boolean.clean_room_1
                  state: "on"
              sequence:
                - service: xiaomi_miio.vacuum_clean_segment
                  target:
                    device_id: # insert Device ID Here
                  data:
                    segments:
                      - # insert room number here
                - wait_for_trigger:
                    - platform: state
                      entity_id:
                        - # vacuum entity id
                      to: returning
                    - platform: state
                      entity_id:
                        - input_boolean.clean_room_1
                      to: "off"
                  timeout:
                    hours: 2
                    minutes: 0
                    seconds: 0
                    milliseconds: 0
                  continue_on_timeout: true
                - choose:
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '0' }}"
                      sequence:
                        - service: input_boolean.turn_off
                          data: {}
                          target:
                            entity_id: input_boolean.clean_room_1
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '1' }}"
                      sequence:
                        - service: vacuum.return_to_base
                          data: {}
                          target:
                            entity_id: # vacuum entity id
                  default: []
            - conditions:
                - condition: state
                  entity_id: input_boolean.clean_room_2
                  state: "on"
              sequence:
                - service: xiaomi_miio.vacuum_clean_segment
                  data:
                    segments:
                      - # insert room number here
                  target:
                    device_id: # insert Device ID Here
                - wait_for_trigger:
                    - platform: state
                      entity_id:
                        - # vacuum entity id
                      to: returning
                    - platform: state
                      entity_id:
                        - input_boolean.clean_room_2
                      to: "off"
                  timeout: "01:00:00"
                - choose:
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '0' }}"
                      sequence:
                        - service: input_boolean.turn_off
                          data: {}
                          target:
                            entity_id: input_boolean.clean_room_1
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '1' }}"
                      sequence:
                        - service: vacuum.return_to_base
                          data: {}
                          target:
                            entity_id: # vacuum entity id
                  default: []
              - conditions:
                - condition: state
                  entity_id: input_boolean.clean_room_3
                  state: "on"
              sequence:
                - service: xiaomi_miio.vacuum_clean_segment
                  data:
                    segments:
                      - # insert room number here
                  target:
                    device_id: # insert Device ID Here
                - wait_for_trigger:
                    - platform: state
                      entity_id:
                        - # vacuum entity id
                      to: returning
                    - platform: state
                      entity_id:
                        - input_boolean.clean_room_3
                      to: "off"
                  timeout: "01:00:00"
                - choose:
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '0' }}"
                      sequence:
                        - service: input_boolean.turn_off
                          data: {}
                          target:
                            entity_id: input_boolean.clean_room_1
                    - conditions:
                        - condition: template
                          value_template: "{{ wait.trigger.idx == '1' }}"
                      sequence:
                        - service: vacuum.return_to_base
                          data: {}
                          target:
                            entity_id: # vacuum entity id
                  default: []
          default: []
mode: single

Based per room. Or clean all.