Script running a repeat action, that should be different for the last run

Hi,

I’m trying to create a script that runs a set number of repeats depending on a helper, but the last run should be different from the others.

I’ve tried to look at the script page for this, but I can’t get it to work.

(Thank you and sorry if I’m doing something wrong, first post and a rookie HA-user)

dammsug_test1:
  alias: Dammsug Test1
  sequence:
  - repeat:
      count: '{{states(''input_number.antal'')|int}}'
      sequence:
      '{% if "{{repeat.index}}" == "{{repeat.last}}" %}'
      - service: vacuum.send_command
        data:
          entity_id: vacuum.rockrobo
          command: zoned_cleanup
          params:
            zone_ids:
            - Test1
        entity_id: vacuum.rockrobo
        
      '{% else %}'  
      - service: vacuum.send_command
        data:
          entity_id: vacuum.rockrobo
          command: zoned_cleanup
          params:
            zone_ids:
            - Test1
        entity_id: vacuum.rockrobo 
      - wait_template: '{{ is_state(''vacuum.rockrobo'', ''returning'') }}'
      - delay: 00:00:02
      - service: vacuum.pause
        data: {}
        entity_id: vacuum.rockrobo
      - delay: 00:00:02
      '{% endif %}'
  mode: single

A template generates a value that is assigned to an option.

 an_option: "{{ template goes here }}"

You are trying to include options inside the template and that’s not permitted.

      sequence:
      '{% if "{{repeat.index}}" == "{{repeat.last}}" %}'
      - service: vacuum.send_command   <------ You cannot put options inside of templates

Is there another way of running the repeat command with a different sequence for the last run?

Should I create different scrips (one for the last run and one for others) and run them depending on which “run” it is? Would that work?

Edit: something like this, but within the repeat? So for repeat.last -> run script.vacuum_test1_last and for the other script.vacuum_test1

Reduce count by one and then put the last service call after repeat.

dammsug_test1:
  alias: Dammsug Test1
  sequence:
  - repeat:
      count: '{{states(''input_number.antal'')|int - 1 }}'
      sequence:
      - service: vacuum.send_command
        data:
          entity_id: vacuum.rockrobo
          command: zoned_cleanup
          params:
            zone_ids:
            - Test1
      - wait_template: '{{ is_state(''vacuum.rockrobo'', ''returning'') }}'
      - delay: 00:00:02
      - service: vacuum.pause
        data:
          entity_id: vacuum.rockrobo
      - delay: 00:00:02
  - service: vacuum.send_command
    data:
      entity_id: vacuum.rockrobo
      command: zoned_cleanup
      params:
        zone_ids:
        - Test1
  mode: single

I tried it, but if the number of runs were set to 1, that would mean 0 for the repeat and that translated to the script no being run at all.

I’ll give it a try with the code you provided.
Maybe I did something wrong.

Edit: ran it with input_number.antal = 1 and nothing happens.
The script is executed, but immediately terminated.

Edit 2: if input_number.antal is set to 2 (or I assume more) it works and runs as expected. Can I make the script skip the repeat step if input_number.antal is set to 1?

I changed the code to the following and now it works.

Thank you for your help @123

dammsug_test1:
  alias: Dammsug Test1
  sequence:
  - choose:
    - conditions:
      - condition: numeric_state
        entity_id: input_number.antal
        above: '1'
      sequence:
      - repeat:
          count: '{{states(''input_number.antal'')|int - 1 }}'
          sequence:
          - service: vacuum.send_command
            data:
              entity_id: vacuum.rockrobo
              command: zoned_cleanup
              params:
                zone_ids:
                - Test1
            entity_id: vacuum.rockrobo
          - wait_template: '{{ is_state(''vacuum.rockrobo'', ''returning'') }}'
          - delay: 00:00:02
          - service: vacuum.pause
            data: {}
            entity_id: vacuum.rockrobo
          - delay: 00:00:02
    default: []
  - service: vacuum.send_command
    data:
      entity_id: vacuum.rockrobo
      command: zoned_cleanup
      params:
        zone_ids:
        - Test1
    entity_id: vacuum.rockrobo
  mode: single

You’re welcome but you should know that marking your own post as the Solution is reserved for when you actually think of the solution yourself.

In this case, your automation was identified to be misusing template syntax and an example was provided demonstrating how to separate the last repetition from repeat.

It would mean no iterations within repeat and a single iteration after it. That equates to a count of 1.


EDIT

There’s something wrong with the automation you posted. It contains needlessly duplicated code.

When I run the script, it doesn’t do anything, when the input_number.antal is set to 1. Why is that then?
Do I have something inbeded somhow, that quites a script if there’s an error (ie the number of repeats being set to 0)?

Where’s the duplication?
I have a repeat and an action afterwards.
How can I reduce the code?

Edit: I see what you mean. I’ve copied it twice by mistake. Updated

There was that copy-paste error plus the duplication of entity_id in service calls. Only one entity_id per service call is required.

          - service: vacuum.send_command
            data:
              entity_id: vacuum.rockrobo <--- First reference to entity_id
              command: zoned_cleanup
              params:
                zone_ids:
                - Test1
            entity_id: vacuum.rockrobo <--- Second reference to entity_id

Here’s another way that uses a Template Condition to determine if the extra actions should be executed. If it’s the last repetition, the extra actions are not executed.

dammsug_test1:
  alias: Dammsug Test1
  sequence:
  - repeat:
      count: '{{states(''input_number.antal'')|int }}'
      sequence:
      - service: vacuum.send_command
        data:
          entity_id: vacuum.rockrobo
          command: zoned_cleanup
          params:
            zone_ids:
            - Test1
      - condition: template
        value_template: '{{ repeat.index != repeat.last}}'
      - wait_template: '{{ is_state(''vacuum.rockrobo'', ''returning'') }}'
      - delay: 00:00:02
      - service: vacuum.pause
        data:
          entity_id: vacuum.rockrobo
      - delay: 00:00:02
  mode: single

Sadly, I’ve seen that this doesn’t work @123

It seems like this isn’t run correctly.

Would it be better to compare the repeat.index to the input_number-helper instead?

Oops! I made a mistake.

repeat.last is not a numeric value but a boolean. It indicates true when it’s the last repetition, otherwise it indicates false.

Try this version:

dammsug_test1:
  alias: Dammsug Test1
  sequence:
  - repeat:
      count: '{{states(''input_number.antal'')|int }}'
      sequence:
      - service: vacuum.send_command
        data:
          entity_id: vacuum.rockrobo
          command: zoned_cleanup
          params:
            zone_ids:
            - Test1
      - condition: template
        value_template: '{{ not repeat.last}}'
      - wait_template: '{{ is_state(''vacuum.rockrobo'', ''returning'') }}'
      - delay: 00:00:02
      - service: vacuum.pause
        data:
          entity_id: vacuum.rockrobo
      - delay: 00:00:02
  mode: single

Thank you @123

It works!

Now I only need to find a way of entering the zone_ids: instead of creating a code per room.
I had a look here, but the solution doesn’t work for me, but I guess I should ask my question in that thread instead.