How to pass an array variable to a script

I know this is a little dated, but here’s how you can pass the standard entity list to a script, and then have the script correctly act on that list. This method works with one or more entries in a standard YAML list, such as:

 light_name: 
   - light.training_room
   - light.basement_bathroom

The script wants a simple list, like:

list_of_entities = light.training_room,light.basement_bathroom

Instead, what gets passed is:

list_of_entities = ['light.training_room', 'light.basement_bathroom']

So you can’t use the passed list as a direct, 1-to-1 drop-in for the entity_id list in the script - bummer!

The solution is to recreate the list in the proper format using a Jinja for loop. For example, here’s the entity_id list I want to pass from the script service call in the action portion of an automation to the actual script:

  - service: script.dim_or_brighten_lights
    data:
      action: DIM
      light_name: 
        - light.training_room
        - light.basement_bathroom
      caller: Calling automation name (whatever that is) 

Then in the script, use the following (explanation follows):

dim_or_brighten_lights:
  alias: Dim or brighten lights
  description: 'Dim or brighten lights'
  fields:
    action:
      description: 'Action to execute DIM (100) or BRIGHTEN (255)'
      example: 'DIM or BRIGHTEN'
    light_name:
      description: 'Name of light to act on'
      example: 'light.living_room'
    caller:
      description: 'Name of calling script/automation'
      example: 'shut_down_roku_tv'
  sequence:
    - service: system_log.write
      data_template:
        message: "SCRIPT {{caller}}>dim_or_brighten_lights: Action: {{action}} on {{light_name}}"
        level: warning
    - service: light.turn_on
      data_template:
        entity_id: >
            {% for e in light_name %}
              {% if loop.first %}{% else %}, {% endif %}
            {{ e }}
            {% endfor %}
        brightness: "{% if 'DIM' in action or 'dim' in action %} 100 {% else %} 255 {% endif %}"
        kelvin: "{% if 'DIM' in action or 'dim' in action %} 2000 {% else %} 4000 {% endif %}"

In this script, I have three fields:

  • action: either DIM or BRIGHTEN
  • light_name: a single entity_id or a list of entity ids (refer to the light_name in the action part of the automation
  • caller: I always use this so I know what automation is calling the script (my whole idea of using a script is that it is reusable code that can be called from more than one place). I then use that in a system_log.write service to write to the home-assistant.log. If something goes wrong, I can look at the home-assistant.log file to trace down the error

Under sequence, I first write a message to the log. {{caller}} is the name of the automation that called the script. I also write out the action and the entity id list ({{light_name}})

Finally, we get to the good part. Our goal is to convert the string that is passed by the automation to a list WITHOUT single quotes that can be used in the script.

As stated above, what we need is a list like this:

entity_id: light.training_room,light.basement_bathroom

Under the data_template, I include a for loop. I’ll describe each line because if you’re not used to Jinja syntax (and I’m far from an expert!), it can be a little intimidating:

{% for e in light_name %}

This line cycles through each name in the list of entities you passed to the script. The variable e takes on the value of each item in turn in the light_name list that was passed from the automation. In the case of this example, it first takes on the name light.training_room. Then the second time through, it takes on the name light.basement_bathroom.

{% if loop.first %}{% else %}, {% endif %}

Here’s what’s happening. The {% if loop.first %} checks if this is the first time through the list light_name. If so, then move on to the next line, which is {{ e }}. After the first pass, our entity_id parameter is:

entity_id: light.training_room

Now, each subsequent time through the loop, we need to add a comma as a separator in the list. That’s what the {% else %} statement does.

After going through the second time, entity_id is first changed to:

entity_id: light.training_room,  #<<< Note the comma has been added by the if/else/endif logic

Then the next entity is added so that we finally have:

entity_id: light.training_room,light.basement_bathroom

Now that we’re at the end of the passed list, the for loop stops with the {% endfor %} statement. The entity_id for the script is now complete and correct.

Hope this helps some others. I struggled getting to this point for a while. By adding this feature to my scripts, I was able to clean up a few things (calling the script for each entity id, creating unnecessary groups). As an aside, I use this script to DIM or BRIGHTEN any lights in the house. That way it’s always consistent, which creates a feeling of control for the others in the home.

2 Likes