For_each - create a list for single or multiple entries passed in as parameter

I’m using for_each to iterate over a list of media_players which I feed into the script as a parameter. I needed to work around an issue in not being able to use the same mechanism as I would use for other services where you can pass in either a single entity or a comma separated list of entity_ids e.g.

entity_id: media_player.my_player_1 or
entity_id: media_player.my_player_1, media_player.my_player_2

The second case doesn’t work with for_each as the parameter is a string, not a list.
If I bracket the parameter to be a list

entity_id: [ media_player.my_player_1, media_player.my_player_2 ]

when calling the script then it works.

Here’s how the code looks like, the workaround is to create a group on the fly - which accepts either a single or multiple entity_ids and then use the groups entity_id state_attribute to iterate over.

media_player_speak:
  sequence:
  - service: group.set
    data:
      object_id: media_player_temp_group
      entities: "{{ entity_id }}" # entity_id is the parameter passed intothe script

  - repeat:
      for_each: "{{ state_attr('group.media_player_temp_group', 'entity_id')|list }}"
      #  do something with repeat.item

  - service: group.remove
    data:
    object_id: media_player_tmp_group

# the calling sequence looks like this:

- service: script.media_player_speak
  data: 
    entity_id: media_player.my_player_1, media_player.my_player_2
    message: "hello"

I wonder if this can be done more elegantly - w/o the need of the temporary group.

change to

- service: script.media_player_speak
  data: 
    entity_id:
    - media_player.my_player_1
    - media_player.my_player_2
    message: "hello"

or,

- repeat:
    for_each: "{{ entity_id.split(', ') if entity_id is string else entity_id }}"
2 Likes

thank you very much. Your solution, the second way with the split (the first one I had known but wanted it to function like w/ other services) is great and make we wonder why I didn’t get to that simple solution myself (now that I see it :wink: ).

This solution works for me. But only for entity_id.

I’m trying to control lights using area_id and when I pass a list of area_ids, the script evaluates it as:

- - area1
  - area2
  - area3

Is area_id broken? or is only entity_id capable of taking a list as a script parameter?

Here’s my script code

  - continue_on_error: true
    data: {}
    target:
      entity_id: "{{lights}}"
      area_id: "{{my_areas}}"
    action: light.turn_off

My invoking code looks like this:

              - target:
                  entity_id: script.new_script_3
                data:
                  variables:
                    sonos: media_player.master_bedroom
                    beep_device: light.f2_mb_ceiling_2
                    station_button_id: sensor.f2_mb_kp_g
                    pause_button_id: sensor.f2_mb_kp_g
                    lights: 
                      - light.f2_mb_bryans_lamp_scene
                      - light.f2_mb_jms_lamp
                    my_areas: 
                      - master_bathroom
                      - master_bedroom
                      - hallway
                    fan: switch.f2_mb_fan_scene
                    timer: timer.bedtime_routine
                action: script.turn_on

here’s what the interpreter see:

Error: template value should be a string @ data['area_id'][0]
Result:
params:
  domain: light
  service: turn_off
  service_data: {}
  target:
    entity_id:
      - light.f2_mb_bryans_lamp_scene
      - light.f2_mb_jms_lamp
    area_id:
      - - master_bathroom
        - master_bedroom
        - hallway
running_script: false

By the way, in the developer tool, this action call works fine:

action: light.turn_off
target:
  entity_id:
    - light.f2_mb_bryans_lamp_scene
    - light.f2_mb_jms_lamp
  area_id:
    - master_bathroom
    - master_bedroom
    - hallway
data: {}

Adding more info: I am able to reproduce the problem with a simple script with a hard coded list variable (not taking in a parameter) and I see the same problem. I think it’s an issue with the way area_id is parsed. I’ll raise this issue somewhere else :grinning: