Script or automation to run scripts sequentially?

Hi all,

For my robot vacuum, I have individual scripts to clean each room. I have 10 rooms, so I’m trying to figure out a good way to vacuum 1 room, once complete, then call another script to vacuum another room. Any suggestions on how to go about that?

alias: 'Vacuum: Kitchen'
sequence:
  - service: xiaomi_miio.vacuum_clean_zone
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      zone:
        - - 29609
          - 17748
          - 34877
          - 24460
      repeats: 1
mode: single
icon: mdi:countertop-outline

With my Roborock S7, I know I can add up to 5 rooms in a single script like this. But since I have 10 rooms, I’d like to be able to call 6 or 7 scripts asynchronously.

alias: 'Rosie: Vacuum 2 Zones'
sequence:
  - service: xiaomi_miio.vacuum_clean_zone
    target:
      entity_id: vacuum.roborock_vacuum_a15
    data:
      repeats: 1
      zone:
        - - 22474
          - 25558
          - 23025
          - 26115
        - - 23877
          - 25073
          - 24428
          - 25630
mode: single

What I would like to do (and can’t figure out the logic), is something similar to the automation below which does not work. Also, the vacuum returns to dock after each script, which is fine for now, so I’d probably need to add a wait template or delay before running the next script. Any suggestions?

alias: Run 2 Vacuum Zones
description: ''
trigger:
  - platform: device
    device_id: b41f12773105494ba3308f37c48c41bc
    domain: vacuum
    entity_id: vacuum.roborock_vacuum_a15
    type: docked
    for:
      hours: 0
      minutes: 0
      seconds: 30
condition: []
action:
  - service: script.turn_on
    data: {}
    target:
      entity_id: script.vacuum_kitchen
  - wait_template: "{{ is_state('vacuum.roborock_vacuum_a15', 'docked') }}"
  - service: script.turn_on
    data: {}
    target:
      entity_id: script.vacuum_game_room
mode: single

Edit: Of course I would find a solution shortly after posting. I’ve been trying to figure out to do this for months.

alias: Vacuum Multiple Rooms
description: ''
trigger:
  - platform: time
    at: '14:11:00'
condition:
  - condition: state
    entity_id: input_boolean.home
    state: 'on'
action:
  - service: script.vacuum_game_room
    data: {}
  - wait_for_trigger:
      - platform: template
        value_template: '{{ is_state(''vacuum.roborock_vacuum_a15'',''returning'') }}'
  - service: script.vacuum_dining_room
    data: {}
  - wait_for_trigger:
      - platform: template
        value_template: '{{ is_state(''vacuum.roborock_vacuum_a15'',''returning'') }}'
  - service: script.vacuum_son
    data: {}
  - wait_for_trigger:
      - platform: template
        value_template: '{{ is_state(''vacuum.roborock_vacuum_a15'',''returning'') }}'
  - service: script.vacuum_daughter
    data: {}
mode: single

You can define a list of the rooms to be vacuumed (in the order they should be vacuumed) and then use repeat - count to iterate through the list and call each script.

alias: Vacuum Multiple Rooms
description: ''
trigger:
  - platform: time
    at: '14:11:00'
condition:
  - condition: state
    entity_id: input_boolean.home
    state: 'on'
action:
action:
  - variables:
      rooms:
        - 'game_room'
        - 'dining_room'
        - 'son'
        - 'daughter'
  - repeat:
      count: '{{ rooms | count }}'
      sequence:
        - service: 'script.vacuum_{{ rooms[repeat.index - 1] }}'
        - wait_for_trigger:
            - platform: state
              entity_id: vacuum.roborock_vacuum_a15
              to: 'returning'
mode: single

NOTE

Be advised that any automation whose action contains repeat, wait_template, wait_for_trigger, delay or any long chain of actions that cause it remain busy for many minutes, will be interrupted and canceled by the execution of Reload Automations (which is done transparently by Automation Editor when creating/modifying an automation) or by restarting Home Assistant.

2 Likes

Very cool, thanks for sharing! I’ll test it out tomorrow

Thank you again, this works great!

I was wondering if you had any suggestions on how to check if the battery is under a certain threshold before running each script. Reason I need this is because once the robot vac reaches 20% battery, it returns to the dock by itself. But if it’s currently vacuuming room 4 out of 7 and hits 20%, it tries to return home, but this script tells it to go to the next rooms 5, 6, and 7. (i set battery level to 98% (well - just 98 since it’s an integer) for testing)

I thought if I created a binary sensor, I could add that as a state condition to your automation. Here’s my binary sensor - confirmed it reports the state correctly based on the battery level by checking Dev Tools > Templates. If 98, the state is on.

  - platform: template
    sensors:
      rosie_battery: 
        friendly_name: "RosieBatteryLevel"
        value_template: "{{ state_attr('vacuum.roborock_vacuum_a15','battery_level')|int < 98 }}"
        unique_id: sensor.rosie_battery

And then added a condition to your automation like this:

alias: Vacuum Test Two
description: ''
trigger:
  - platform: time
    at: '14:11:00'
condition:
  - condition: state
    entity_id: input_boolean.home
    state: 'on'
  - condition: state
    entity_id: binary_sensor.rosie_battery
    state: 'off'
    for:
      hours: 0
      minutes: 0
      seconds: 1
action:
  - variables:
      rooms:
        - '1'
        - '2'
        - '3'
        - '4'
  - repeat:
      count: '{{ rooms | count }}'
      sequence:
        - service: script.vac_{{ rooms[repeat.index - 1] }}
        - wait_for_trigger:
            - platform: state
              entity_id: vacuum.roborock_vacuum_a15
              to: returning
mode: single

But it doesn’t seem to do anything.

You need to check the battery’s state within the repeat. To do that, we forego the use of repeat - count and use repeat - while.

alias: Vacuum Test Two
trigger:
  - platform: time
    at: '14:11:00'
condition:
  - condition: state
    entity_id: input_boolean.home
    state: 'on'
action:
  - variables:
      rooms:
        - '1'
        - '2'
        - '3'
        - '4'
  - repeat:
      while: "{{ repeat.index <= rooms|count and is_state('binary_sensor.rosie_battery', 'off') }}"
      sequence:
        - service: script.vac_{{ rooms[repeat.index - 1] }}
        - wait_for_trigger:
            - platform: state
              entity_id: vacuum.roborock_vacuum_a15
              to: returning
mode: single

If you have no need to use binary_sensor.rosie_battery anywhere else, you could eliminate it and use its template directly within the while statement’s template.

      while: "{{ repeat.index <= rooms|count and state_attr('vacuum.roborock_vacuum_a15','battery_level')|int(0) > 98 }}"

NOTE

I used shorthand notation for the while's Template Condition with an explicit logical AND so that everything fits onto a single line. However, another way would be to use an implicit logical AND like this (still employing shorthand notation Template Conditions).

      while:
        - "{{ repeat.index <= rooms|count }}"
        - "{{ state_attr('vacuum.roborock_vacuum_a15','battery_level')|int(0) > 98 }}"

It’s functionally identical and, in my opinion, a bit more legible as long as you understand that this notation will logically AND the two conditions.


EDIT

Correction. Change < to > in template.

Thank you so much, that worked out perfectly! The only thing I had to change was from a < to a >. But after that, it worked exactly as I wanted it to. I tested it a bunch of times by creating 5 test scripts with very small vacuuming areas. As long as the battery is higher that 98 - it runs, but if changes to 97, it doesn’t process the next room script which is perfect for what I needed.

I’m glad I didn’t end up needing that binary sensor, it’s one less thing I need to manage to get this automation running.

Sometimes there’s an advantage to having it in a separate Template Binary Sensor. For example, it could be used in a separate automation to notify you if the battery has been low for over an hour (implying that the vacuum has possibly failed to make it back to its dock to recharge and continues to discharge). However, if there’s no need for that kind of application then, I agree, eliminate the Template Binary Sensor.

Great work!
I would like to covert this in a script (instead of automation) since I think automations are not exposed to google assistant (and I would like to use a voice trigger).

I got to troubleshoot on my end, … I only get the first room started

alias: Vacuum Multiple Rooms
description: ''
trigger: []
condition: []
action:
  - variables:
      rooms:
        - bathroom
        - kitchen
        - play_room
        - passage
        - living_room
        - dining_room
        - front_entrance
        - entrance
  - repeat:
      count: '{{ rooms | count }}'
      sequence:
        - service: script.vacuum_{{ rooms[repeat.index - 1] }}
        - wait_for_trigger:
            - platform: state
              entity_id: vacuum.roborock_vacuum_a27
              to: returning
mode: single

1 Like

You don’t need to convert it to a script. Just create a script that calls the automation. New script > call-service> automation.trigger. Then search for the automation.vacuum_multiple_rooms automation. You can then expose that to Google.

Like the way the script is run.

So adding

    - service: notify.alex_media
      data:
        target: media_player.lounge
        data_template:
          type: announce
          method: tts
        message: "Im cleaning the {{ rooms[repeat.index - 1] }} get out"

then you could get alexa call out what room its cleaning

thinking out side the box more

not tested but
if we reformat the variables to

 - roomtoclean,whichalexatotalkoutof
 - kitchen,lounge

change the

        - service: script.vacuum_{{ rooms[repeat.index - 1] }} 

to

        - service: script.vacuum_{{ rooms[repeat.index - 1].split(",")[0] }}

them

        target: media_player.lounge

to

        target: media_player.{{ rooms[repeat.index - 1].split(",")[1] }}

should play the message in a differance

not tested just wrote on the train home LOL

I can’t seem to shake down my issue.
The returning state is not triggered.

I’ve tried adding the attribute ‘state’ and putting ‘Returning to dock’ still nothing.
I got the maxV version (a27) if that makes a difference.

alias: Vacuum Multiple Rooms
description: ''
trigger: []
condition: []
action:
  - variables:
      rooms:
        - bathroom
        - kitchen
        - play_room
        - passage
        - living_room
        - dining_room
        - front_entrance
        - entrance
  - repeat:
      count: '{{ rooms | count }}'
      sequence:
        - service: script.vacuum_{{ rooms[repeat.index - 1] }}
        - wait_for_trigger:
            - platform: state
              entity_id:
                - vacuum.roborock_vacuum_a27
              to: Returning to dock
              attribute: status
mode: single


If you look at the state of your vacuum in Developer Tools, you’ll probably see the actual state name is “returning”, not “Returning to dock”. That’s what I use in my automation with an S7.

Hint: For testing, grab the coordinates of two very small areas and put those in your individual scripts. That way you don’t have to wait for it to actually complete an entire room cleaning.

Originally I used returning but it wouldn’t trigger the second room and it come right back to the dock.

Hey it started to work with my original returning.
Oh well.
That’s one thing done on my list.

trying to do something similar to this.
I have one script for each room and I use the scripts as button on a home floor plan, so everyone in the house can send the room to their room when needed.
is there a way to set up the script so if the robot is cleaning one room and another room/script is pressed it goes into queue?

Any update? I’m trying to do exactly this.