Repeat + Counter in Automation

hi - i’ve been losing my mind trying to create an automation/script that can loop through a dynamic list of entities and run the same service call on all of them. i’ve found several threads explaining the process but i just cannot get past one issue that i assume is something i’m doing wrong with my syntax. hoping someone can help out!

the code is below, but the takeaway is: no matter what i do, the automation seems to be treating my entity_id list as a string and, therefore, list[0] shows up as just the opening “[”

i’ve tried a number of variations - including reading from a sensor and just directly templating within the automation. same results either way. i’ve also tried defining the variable as a comma separated string and then converting to a list item – same thing.

here’s my sensor yaml, which works perfectly:

  - platform: template
    sensors:
      schedule_entities:
        unique_id: schedule_entities
        friendly_name: "Schedule Entities"
        value_template: "{{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list | count }}"
        attribute_templates:
          schedules: >
            {{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list | join(', ') }}
          schedule_list: >
            {{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list }}

and here’s the relevant part of my automation yaml:

  - variables:
      list: "{{ state_attr('sensor.schedule_entities', 'schedules_list') }}"
      counter: "{{ states('sensor.schedule_entities') | int(0) }}"
  - repeat:
      sequence:
        - service: homeassistant.turn_off
          target:
            entity_id: |
              {{ list[repeat.index - 1] }}
      count: "{{ counter | int(0) }}"
    enabled: true

the counter is working correctly, and the list variable is correctly pulling from the sensor, it’s just the individual list elements that i can’t figure out how to pull. like i said - i’ve tried a million different variations, but every time, the automation just treats each individual character as a list item.(“[”, “{” or “s” - depending on the exact variation i am using). i’ve also tried the alternate “from_json” approach – same issue. i’ve also tried quoting the list item index number – both directly/statically – {{ list[‘0’] }} and as an actual variable {{ list[‘repeat.index -1’] }} – also doesn’t help.

every single time it just keeps spitting out a 1 character long entity id. i’ve spent hours spinning my tires on this. anyone have any idea what i’m doing wrong?

last thing – i did notice that if i statically define the variable as a line-by-line list of entities it works, but even statically definining the list using the brackets format does NOT work:

so this works:

  - variables: 
    list: 
      - entity_a
      - entity_b

but this doesn’t work:


  - variables: 
     list: ' [ "entity_a", "entity_b" ]'

the threads i’ve been looking at are all several years old – is there some reason the bracket array format doesn’t work in an automation even though it seems to work to create the underlying sensor itself?

in any case, those are just examples for troubleshooting purpose – but the hyphen-separated list isn’t actually an option because the whole point of this is to create a dynamic list.

clearly i’m losing my mind trying to figure this out. would appreciate any guidance anyone might have!

  1. You don’t need to loop. Service calls accept multiple entities.
  2. There’s no reason to keep anything but a list in your attributes.
  3. Probably best to swap to the new template entity configuration.
template:
- sensor:
  - name: Schedule Entities
    unique_id: d3021212-440f-461f-b224-1b8f1d3f3d91
    state: "{{ states.switch | selectattr('object_id', 'match', 'schedule_') | list | count }}
    attributes:
      entity_id: "{{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list }}"
- service: switch.turn_off
  target:
    entity_id: "{{ state_attr('sensor.schedule_entities', 'entity_id') }}"

If you are dead set on looping…

- repeat:
    for_each: "{{ state_attr('sensor.schedule_entities', 'entity_id') }}"
    sequence:
    - service: switch.turn_off
      target:
        entity_id: "{{ repeat.item }}"

thanks petro! i didn’t thnk to clarify – but for me, using multiple entities for the service call isn’t an option. using the generic “turn off” service isn’t my end game – i was just using it while getting the automation up and running but, ultimately, i plan to use the custom scheduler component’s remove schedule service. weirdly, that particular service doesn’t seem to like multiple entity ids. i tried that first and only fell back to the loop option after not having any luck.

but i’ll give your loop fix a shot tonight – thank you!!

ugh - just tried your solution, but looks like a similar problem to what i was having before. the automation doesn’t seem to be treating “{{ state_attr(‘sensor.schedule_entities’, ‘entity_id’) }}” as a list even though i think it quite clearly is.

i added an initial action to my automation that sends a notification containing the above template, here’s what it spits out:

2024-04-09_18-21-04

as far as i can tell, that notification message looks formatted right. so it seems like the automation is receiving the correct information from the sensor. nonetheless, once i hit step 2 of the automation – your for each loop – i get an error saying “Error: Repeat ‘for_each’ must be a list of items.”

i’m beginning to wonder whether this is just a bug or something, because it seems quite clear that the issue is related to strings vs lists, but i’ve tried multiple different approaches – all of which SHOULD give me a proper list, but none of which have been treated as lists by the automation. the only time i’ve gotten the automation to work is if i just manually type in a standard one-entity-per-line list, but manually typing in the entities defeats the purpose so that’s not much use to me.

related, as to my initial belief that the particular service i’m using doesn’t like multiple entity_ids…i’m now thinking that that’s not actually the issue. rather, the issue is probably the same one i’m facing with the for loop – although i believe i’m passing a proper list to the service, the service things it’s just a string.

so i think you’re probably right that i could avoid using the loop altogether. but i can’t do either approach until i figure out why the automation seems to be treating my list as a string.

any remaining ideas?

How are you confirming it’s not working? It most definitely is a list and it will be treated like a list.

What does the trace show?

When you put this in the template editor, what is the output on the right panel?

{{ state_attr(‘sensor.schedule_entities’, ‘entity_id’) }}

There is no bug, there is something that you are doing to test this that’s causing the problem. I use this method… just about everywhere. Just check out my configuration, I generate lists of dictionaries and iterate the dictionaries as service calls in most of my complex automations and scripts:

the trace shows the error i mentioned in my last post – using the exact configuration you suggested last night, trace says:

2024-04-10_19-02-00

good to know it’s working for you. i think i saw some of your other posts you referenced when i was trying to figure this out on my own before posting here. i certainly believe it’s something i’m doing wrong (occam’s razor and what have you), but i cannot for the life of me figure it out. i’ve tried both the variable + counter approach and this more streamlined for-each approach you suggested, but i hit substantively the same issue every time – i cannot get the list to be treated as a list, even though it appears to be a list.

i literally copied and pasted exactly what you recommended. the sensor works perfectly. action (depending on how i go about it) picks up the correct value from the sensor [i know this because i’ve experimented by adding an action before the loop that simply sends the entire value to a notification – which works nicely and prints what appears to be a correctly formatted list.

and using the variable/counter approach – i can get the loop to run the correct number of times (so long as i just have a dummy action so it doesn’t error out).

yet despite all that, when i try to go the final step and try to iterate through the individual list items from the sensor value, for some reason, it just doesn’t like it and won’t treat it as a proper list. and again, literally the only time i’ve gotten my automation to treat a list as a list is when, just for testing purposes, i defined a variable as a static list of specified entities in a new line separated list with hyphens at the start. but yea, any time i try to make my list dynamic and thus have to rely on a bracket enclosed list/array/dictionary (or as a comma separated list that i convert into an array), no dice even though the automation seems to be receiving a correctly formatted list.

i’ve spent HOURS on this and have tried every minor variation i can think of.

i have to assume it was something to do with single quotes vs double quotes (or using > / | for multi line yaml code) or some other formatting thing like that. but i’ve tried all conceivable variations on that as well, and nothing has made the difference.

this may or may not be related, but my trace does display quotes weirdly – see below. but that has always just seemed to be a quirk of how home assistant auto reformats and displays yaml code after i’ve saved it. because when i originally entered the yaml code, i did it normally as you have it above. and all of my other automations display the same quirks, but they work fine, so i’m not convinced this is actually related.

anyhow, i appreciate your help petro. i’m about ready to give up on it. it’s just not worth my time and it’s certainly not worth even more of your time than you’ve already been nice enough to give – if you have any final suggestions, i’d love it – but after that, i’ll probably just have to live with it because i’ve spent wayyyy too much time on this already.

Post a screenshot of the sensor in developer tools → states page with its attributes.

Also, post the full error in the logs when the trace was executing.

Lastly, post the full template sensor you’re using and the full automation, as yaml.

Finally, can you please just post what I’m requesting? I understand you’ve spent a lot of time on this. I don’t really need a dissertation about what you’ve tried. Your posts are overwhelming with non-information. I can fix your problem if I have all the pieces: Template entity configuration in yaml, Automation in yaml, a screenshot of the sensor.shedule_entities in developer tools → states page with attributes shown, the full exact error from the text logs (Not UI logs), and the most recent trace from the download trace button.

sorry. thanks for your help.


sensor:
  - name: Schedule Entities
    unique_id: schedule_entities
    state: "{{ states.switch | selectattr('object_id', 'match', 'schedule_') | list | count }}"
    attributes:
      entity_id: "{{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list }}"

- id: '1711610952072'
  alias: Scheduler Cleanup - Experimental (Automation)
  description: ''
  trigger: []
  condition: []
  action:
  - repeat:
      for_each: '{{ state_attr(''sensor.schedule_entities'', ''entity_id'') }}'
      sequence:
      - service: switch.turn_off
        target:
          entity_id: '{{ repeat.item }}'
        enabled: true
      - service: notify.pc_agent
        metadata: {}
        data:
          message: '{{ repeat.item }}'
    enabled: true


{
  "trace": {
    "last_step": "action/0",
    "run_id": "82ca06332f0a7c480d4fe843c85094b3",
    "state": "stopped",
    "script_execution": "aborted",
    "timestamp": {
      "start": "2024-04-12T09:47:00.632526+00:00",
      "finish": "2024-04-12T09:47:00.633704+00:00"
    },
    "domain": "automation",
    "item_id": "1711610952072",
    "trigger": null,
    "trace": {
      "trigger": [
        {
          "path": "trigger",
          "timestamp": "2024-04-12T09:47:00.632576+00:00",
          "changed_variables": {
            "this": {
              "entity_id": "automation.scheduler_cleanup_experimental_automation_2",
              "state": "on",
              "attributes": {
                "id": "1711610952072",
                "last_triggered": "2024-04-12T09:40:32.186821+00:00",
                "mode": "single",
                "current": 0,
                "friendly_name": "Scheduler Cleanup - Experimental (Automation)"
              },
              "last_changed": "2024-04-12T09:46:39.590607+00:00",
              "last_reported": "2024-04-12T09:46:39.590607+00:00",
              "last_updated": "2024-04-12T09:46:39.590607+00:00",
              "context": {
                "id": "01HV8V7DK67SRRCK7B7RHXD7H6",
                "parent_id": null,
                "user_id": null
              }
            },
            "trigger": {
              "platform": null
            }
          }
        }
      ],
      "action/0": [
        {
          "path": "action/0",
          "timestamp": "2024-04-12T09:47:00.633137+00:00",
          "changed_variables": {
            "context": {
              "id": "01HV8V824RV4QME7K04KWVPTE4",
              "parent_id": "01HV8V824QE29CNYRS7VYR1CSS",
              "user_id": null
            }
          },
          "error": "Repeat 'for_each' must be a list of items"
        }
      ]
    },
    "config": {
      "id": "1711610952072",
      "alias": "Scheduler Cleanup - Experimental (Automation)",
      "description": "",
      "trigger": [],
      "condition": [],
      "action": [
        {
          "repeat": {
            "for_each": "{{ state_attr('sensor.schedule_entities', 'entity_id') }}",
            "sequence": [
              {
                "service": "switch.turn_off",
                "target": {
                  "entity_id": "{{ repeat.item }}"
                },
                "enabled": true
              },
              {
                "service": "notify.pc_agent",
                "metadata": {},
                "data": {
                  "message": "{{ repeat.item }}"
                }
              }
            ]
          },
          "enabled": true
        }
      ],
      "mode": "single"
    },
    "blueprint_inputs": null,
    "context": {
      "id": "01HV8V824RV4QME7K04KWVPTE4",
      "parent_id": "01HV8V824QE29CNYRS7VYR1CSS",
      "user_id": null
    }
  },
  "logbookEntries": [
    {
      "name": "Scheduler Cleanup - Experimental (Automation)",
      "message": "triggered",
      "source": null,
      "entity_id": "automation.scheduler_cleanup_experimental_automation_2",
      "context_id": "01HV8V824RV4QME7K04KWVPTE4",
      "when": 1712915220.6326218,
      "domain": "automation"
    }
  ]
}

and sorry, i’m not positive i know what you mean about text logs – let me know if this is not it:


2024-04-12 02:47:00.632 INFO (MainThread) [homeassistant.components.automation.scheduler_cleanup_experimental_automation_2] Scheduler Cleanup - Experimental (Automation): Running automation actions
2024-04-12 02:47:00.633 ERROR (MainThread) [homeassistant.components.automation.scheduler_cleanup_experimental_automation_2] Scheduler Cleanup - Experimental (Automation): Repeat 'for_each' must be a list of items in Scheduler Cleanup - Experimental (Automation), got: ['switch.schedule_overnight_tasks', 'switch.schedule_roborock_scheduled_clean', 'switch.schedule_roborock_scheduled_clean_2', 'switch.schedule_mqtt_restart']

thank you.

I’m not sure why your template entity is storing that list as a string, but it is and it’s the source of your problems.

You can attempt to get to the bottom of that issue by altering your entity_id attribute template. Or you can just avoid using the template sensor all together. I’d probably avoid using the template sensor entity_id all together.

- id: '1711610952072'
  alias: Scheduler Cleanup - Experimental (Automation)
  description: ''
  trigger: []
  condition: []
  action:
  - repeat:
      for_each: >
        {{ states.switch | selectattr('object_id', 'match', 'schedule_') | map(attribute='entity_id') | list }}
      sequence:
      - service: switch.turn_off
        target:
          entity_id: '{{ repeat.item }}'
        enabled: true
      - service: notify.pc_agent
        metadata: {}
        data:
          message: '{{ repeat.item }}'
    enabled: true

thanks for your thoughts. yes, avoiding the use of template sensor is one of the first things i’d tried. the automation still treats my list as a string even when i define the for_each directly and avoid the sensor altogether, as you suggest. hence my frustrated ramblings.

it’s ok. i am just going to abort this project. for reasons unknown, my automation won’t recognize my list as a list. as to why, beats me. it’s good to know, at least, that i’m not the only one a bit perplexed.

i’ll try in a few months and maybe i get lucky and whatever very subtle thing that’s making my setup behave differently than it should will have resolved itself.

i very much appreciate the time you took trying to help out, petro.

Are you running the latest version of HA?

Yep –

Are you using the UI editor? If yes, how are you putting in the template?

i’ve tried ui editor and also direct formatting in automations.yaml. when using the ui editor, i generally use it in yaml mode. this is what i see in in the yaml box for that step of the automation:

repeat:
  for_each: >-
    {{ states.switch | selectattr('object_id', 'match', 'schedule_') |
    map(attribute='entity_id') | list }}
  sequence:
    - service: switch.turn_off
      target:
        entity_id: "{{ repeat.item }}"
    - service: notify.pc_agent
      metadata: {}
      data:
        message: "{{ repeat.item }}"
enabled: true

on the ‘for each’ step – i initially added it as a single line enclosed with double quotes ] for each: “{{ states.switch… }}” ], and it reformatted itself automatically as shown above.