Roborock S7 in Homekit using fan switch to control suction per room (and some extras)

Hi all,

Based on all the good work done by many others previously, I have expanded on the HomeKit implementation for Roborock vacuum cleaners. This has only been tested on my Roborock S7 MaxV, but I assume will work on any others that share these common commands.

You will need both the Roborock and HomeKit integrations installed, and your Roborock integration configured and working through Home Assistant.

These scripts can be added to your configuration.yaml file. It will set up a range of switches that should all be exposed to Apple Home via a single HomeKit bridge that you can add to your Apple Home. These include:

  • A HomeKit bridge for Roborock
  • A ‘fan’ switch for each room configured.
    • This can be used as a simple on/off switch to start cleaning the pre-configured ‘room’. (on = clean, off = pause).
    • The fan setting allows you to set/change the suction used for each ‘room’.
  • An on/off switch that can be used to pause the vacuum (on = pause, off = resume)
  • An on/off switch to return the vacuum to the dock (on = return, off = pause)
  • A ‘fan’ switch that sets the mop mode
  • A ‘fan’ switch that sets the mop intensity

When configured, it should look like this:

I have put comments in the code to help you configure it.

  • You will need to replace “roborock_s7_maxv” (which is my vacuum) with the name used in HA for your vacuum.
  • I have only included a single room (Lounge) and ‘set of rooms’ (All) from my implementation.
  • You will also need to replicate the various routines and rename them per room to suit your needs.
  • Also remember to replace the various ‘room numbers’ with those relevant to your set up.

I hope this is of interest to some!

Macdownunder

## Code to be added to configuration.yaml
## Developed by Macdownunder using Roborock and HomeKit integrations
##
##  NB: You will need to replace "roborock_s7_maxv" (which is my vacuum) with the name used in HA for your vacuum.
##      I have only included a single room (Lounge) and 'set of rooms' (All) from my implementation.
##      You will also need to replicate the various routines and rename them per room to suit your needs.
##      Also remember to replace the various 'room numbers' with those relevant to your set up.


switch:
  - platform: template
    switches:

      # This makes an on/off switch to return the vacuum to the dock (off pauses the return)

      return_vacuum_to_dock:
        friendly_name: "Roborock Return to Dock"
        value_template: >
          {{ states('vacuum.roborock_s7_maxv') in ['returning', 'docking'] }}
        turn_on:
          - service: script.roborock_clear_booleans
          - service: vacuum.return_to_base
            target:
              entity_id: vacuum.roborock_s7_maxv
        turn_off:
          - service: vacuum.pause
            target:
              entity_id: vacuum.roborock_s7_maxv

      # This makes an on/off switch to pause the vacuum (off send the resume command to the vacuum)

      roborock_pause_resume:
        friendly_name: "Roborock Pause/Resume"
        value_template: >
          {{ is_state('vacuum.roborock_s7_maxv', 'paused') }}
        turn_on:
          service: vacuum.pause
          target:
            entity_id: vacuum.roborock_s7_maxv
        turn_off:
          service: vacuum.start
          target:
            entity_id: vacuum.roborock_s7_maxv

script:

  # Script to commence cleaning a room at the desired suction level (per room)

  roborock_clean_or_resume_lounge:
    alias: "Clean or Resume Lounge"
    sequence:
      - choose:
          - conditions:
              - condition: state
                entity_id: vacuum.roborock_s7_maxv
                state: paused
            sequence:
              - service: vacuum.start
                entity_id: vacuum.roborock_s7_maxv
          - conditions:
              - condition: state
                entity_id: vacuum.roborock_s7_maxv
                state: docked
            sequence:
              - service: vacuum.set_fan_speed
                data:
                  entity_id: vacuum.roborock_s7_maxv
                  fan_speed: >
                    {% set p = (states('input_number.roborock_lounge_suction') | int // 20) * 20 %}
                    {% if p == 20 %} quiet
                    {% elif p == 40 %} balanced
                    {% elif p == 60 %} turbo
                    {% elif p == 80 %} max
                    {% else %} max_plus
                    {% endif %}
              - delay: "00:00:01"
              - service: vacuum.send_command
                data:
                  entity_id: vacuum.roborock_s7_maxv
                  command: app_segment_clean
                  params: [22]      ########### you will need to change this to your required room number(s)

  roborock_clean_or_resume_all:
    alias: "Clean or Resume All"
    sequence:
      - choose:
          - conditions:
              - condition: state
                entity_id: vacuum.roborock_s7_maxv
                state: paused
            sequence:
              - service: vacuum.start
                entity_id: vacuum.roborock_s7_maxv
          - conditions:
              - condition: state
                entity_id: vacuum.roborock_s7_maxv
                state: docked
            sequence:
              - service: vacuum.set_fan_speed
                data:
                  entity_id: vacuum.roborock_s7_maxv
                  fan_speed: >
                    {% set p = (states('input_number.roborock_all_suction') | int // 20) * 20 %}
                    {% if p == 20 %} quiet
                    {% elif p == 40 %} balanced
                    {% elif p == 60 %} turbo
                    {% elif p == 80 %} max
                    {% else %} max_plus
                    {% endif %}
              - delay: "00:00:01"
              - service: vacuum.send_command
                data:
                  entity_id: vacuum.roborock_s7_maxv
                  command: app_segment_clean
                  params: [19, 17, 18, 21, 20, 22, 16, 23]        ########### you will need to change this to your required room number(s)

  # This is a routine to set all the room boolean to off (used to keep track of which room is active). To allow the HomeKit switch logic work.

  roborock_clear_booleans:
    alias: "Clear Roborock Room Flags"
    sequence:
      - service: input_boolean.turn_off
        target:
          entity_id:
            - input_boolean.roborock_lounge_active
            - input_boolean.roborock_all_active


automation:

  # These are required to allow the suction settings to change during operation - per room/fan switch

  - alias: "Update suction while cleaning - Lounge"
    trigger:
      - platform: state
        entity_id: input_number.roborock_lounge_suction
    condition:
      - condition: state
        entity_id: vacuum.roborock_s7_maxv
        state: cleaning
    action:
      - service: vacuum.set_fan_speed
        data:
          entity_id: vacuum.roborock_s7_maxv
          fan_speed: >
            {% set p = (states('input_number.roborock_lounge_suction') | int // 20) * 20 %}
            {% if p == 20 %} quiet
            {% elif p == 40 %} balanced
            {% elif p == 60 %} turbo
            {% elif p == 80 %} max
            {% else %} max_plus
            {% endif %}

  - alias: "Update suction while cleaning - All"
    trigger:
      - platform: state
        entity_id: input_number.roborock_all_suction
    condition:
      - condition: state
        entity_id: vacuum.roborock_s7_maxv
        state: cleaning
    action:
      - service: vacuum.set_fan_speed
        data:
          entity_id: vacuum.roborock_s7_maxv
          fan_speed: >
            {% set p = (states('input_number.roborock_all_suction') | int // 20) * 20 %}
            {% if p == 20 %} quiet
            {% elif p == 40 %} balanced
            {% elif p == 60 %} turbo
            {% elif p == 80 %} max
            {% else %} max_plus
            {% endif %} 


  # This sets all the room boolean to off when the vacuum docks (ie at end of cleaning)

  - alias: Reset Roborock active rooms on stop
    trigger:
      - platform: state
        entity_id: vacuum.roborock_s7_maxv
        to:
          - 'docked'
    action:
      - service: script.roborock_clear_booleans


fan:
  - platform: template
    fans:


      # This sets up a 'fan' switch for each room/group of groups, and calls the suction level input from the fan setting.

      roborock_clean_lounge:
        friendly_name: "Roborock Lounge"
        value_template: "{{ is_state('input_boolean.roborock_lounge_active', 'on') }}"
        percentage_template: "{{ states('input_number.roborock_lounge_suction') | int }}"
        turn_on:
          - service: script.roborock_clear_booleans
          - service: script.roborock_clean_or_resume_lounge
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.roborock_lounge_active
        turn_off:
          - service: vacuum.pause
            target:
              entity_id: vacuum.roborock_s7_maxv
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.roborock_lounge_active
        set_percentage:
          - service: input_number.set_value
            data:
              entity_id: input_number.roborock_lounge_suction
              value: "{{ percentage }}"

      roborock_clean_all:
        friendly_name: "Roborock ALL"
        value_template: "{{ is_state('input_boolean.roborock_all_active', 'on') }}"
        percentage_template: "{{ states('input_number.roborock_all_suction') | int }}"
        turn_on:
          - service: script.roborock_clear_booleans
          - service: script.roborock_clean_or_resume_all
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.roborock_all_active
        turn_off:
          - service: vacuum.pause
            target:
              entity_id: vacuum.roborock_s7_maxv
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.roborock_all_active
        set_percentage:
          - service: input_number.set_value
            data:
              entity_id: input_number.roborock_all_suction
              value: "{{ percentage }}"


      # This sets up a 'fan' switch that allows you to select the mop mode

      roborock_mop_mode:
        friendly_name: "Roborock Mop Mode"
        value_template: "{{ not is_state('select.roborock_s7_maxv_mop_mode', 'off') }}"
        percentage_template: >
          {% set mode = states('select.roborock_s7_maxv_mop_mode') %}
          {% if mode == 'standard' %}
            25
          {% elif mode == 'deep' %}
            50
          {% elif mode == 'custom' %}
            75
          {% elif mode == 'deep_plus' %}
            100
          {% else %}
            0
          {% endif %}
        turn_on:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_mode
              option: standard
        turn_off:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_mode
              option: standard
        set_percentage:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_mode
              option: >
                {% if percentage | int <= 25 %}
                  standard
                {% elif percentage | int <= 50 %}
                  deep
                {% elif percentage | int <= 75 %}
                  custom
                {% else %}
                  deep_plus
                {% endif %}
        speed_count: 4

      # This sets up a 'fan' switch that allows you to select the mop intensity

      roborock_mop_intensity:
        friendly_name: "Roborock Mop Intensity"
        value_template: >
          {{ not is_state('select.roborock_s7_maxv_mop_intensity', 'off') }}
        percentage_template: >
          {% set mode = states('select.roborock_s7_maxv_mop_intensity') %}
          {% if mode == 'mild' %}
            33
          {% elif mode == 'moderate' %}
            66
          {% elif mode == 'intense' %}
            100
          {% else %}
            0
          {% endif %}
        turn_on:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_intensity
              option: mild
        turn_off:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_intensity
              option: off
        set_percentage:
          - service: select.select_option
            data:
              entity_id: select.roborock_s7_maxv_mop_intensity
              option: >
                {% if percentage | int <= 33 %}
                  mild
                {% elif percentage | int <= 66 %}
                  moderate
                {% else %}
                  intense
                {% endif %}
        speed_count: 3


# Set up inputs to hold the fan switch settings

input_number:
  roborock_lounge_suction:
    name: Suction Level Lounge
    min: 20
    max: 100
    step: 20
    mode: slider
    initial: 100

  roborock_all_suction:
    name: Suction Level All
    min: 20
    max: 100
    step: 20
    mode: slider
    initial: 100


# Set up booleans to identify active rooms

input_boolean:
  roborock_lounge_active:
    name: Roborock Lounge Active
    initial: off

  roborock_all_active:
    name: Roborock All Active
    initial: off


# Set up HomeKit integration bridge containing all entities to be exposed to HomeKit 

homekit:
  - name: Roborock
    port: 51828
    filter:
      include_entities:
        - switch.return_vacuum_to_dock
        - switch.roborock_pause_resume
        - fan.roborock_clean_all
        - fan.roborock_clean_lounge
        - fan.roborock_mop_intensity
        - fan.roborock_mop_mode

1 Like