Use templates within action

I have a bunch of shelly dimmers and I’m using the Circadian automation from here: DIY Circadian Lighting. no flux and no custom components - #19 by phsdv

This works great except that the lights need to be on before they are dimmed which can get quite jarring at night. I’ve worked out that, with the shellys, I can use the RESTful API to change the brightness, even when the light is off.

So I’m trying to build a little automation to do that. I think I’ve got the templating right based on the template editor but I cannot get it to work. In essence, I am calling the rest service for each light that is not on and updating the brightness based on the ciracdian brightness sensor. Since the REST service needs an IP address, I have a dict with the IP addresses mapped to the entity_id in HA.

When I try and save this, I get the following error:
message malformed: expected dictionary @ data['action'][0]

This is the code for the automation. Any thoughts welcome!

- id: '1662618812957'
  alias: "[Circadian] Brightness Transition v2"
  description: ""
  trigger:
    - platform: state
      entity_id:
        - sensor.cl_brightness
  condition:
    - condition: state
      entity_id: input_boolean.circadian_on
      state: "on"
    - condition: template
      value_template: >
        {% set lights = ['group.circadian'] %}  {{
        expand(lights)|selectattr('state','eq','off')|list|length> 0 }}
      enabled: true
  action: > 
    {% set ip_add = {
      'light.lights': '192.168.1.xxx', 
      'light.lights_2': '192.168.1.xxx', 
      'light.lights_4': '192.168.1.xxx', 
      'light.lights_5': '192.168.1.xxx', 
      'light.lights_7': '192.168.1.xxx', 
      'light.lights_8': '192.168.1.xxx', 
    %}
    {% set lights = ['group.circadian'] %} 
    {% for lt in expand(lights)|selectattr('state','eq','off')|map(attribute='entity_id')|list %}
    - service: rest_command.shelly_brightness
      data_template:
        ip: "{{ ip_add[lt] }}"
        brightness: "{{ states('sensor.cl_brightness') }}" {% endfor %}
  mode: single
  initial_state: true

I’m guessing it has something to do with having templating within action instead of service / data but not sure how else to do this as I need multiple actions and I won’t know how many until the script runs.

Thanks!

Look at repeat: Script Syntax - Home Assistant.

Thanks - I tried the below:

alias: Set light brightness
mode: single
sequence:
  - repeat:
      for_each: >
        {% set ip_add = {
          'light.gstudylights': '192.168.1.xxx', 
          'light.bathroomlights': '192.168.1.xx', 
          'light.lights': '192.168.1.xxx', 
          'light.lights_2': '192.168.1.xx', 
          'light.lights_4': '192.168.1.xx', 
          'light.lights_5': '192.168.1.xxx', 
          'light.lights_7': '192.168.1.xxx', 
          'light.lights_8': '192.168.1.xxx', 
          'light.walk_in_robe_lights': '192.168.1.xxx'} %} 
        {% set lights = ['group.circadian'] %}   
        {% for entity in expand(lights)|map(attribute='entity_id')|list %}  
        - "{{ip_add[entity]}}" {% endfor %}
      sequence:
        - service: rest_command.shelly_brightness
          data_template: |
            ip: {{ repeat.item }} brightness: "50"

and it gives me the following error when I run it and trace.

Error: Repeat 'for_each' must be a list of items

NB. above is just a test. I want to use the templating so I can filter the list of devices based on their state within the for loop.

Any help appreciated. thanks!

Ever find a way to resolve this? I’m seeing it as well, but haven’t figured out how to resolve.

When you use a for loop, you need to use namespace to extract the returned values out of the loop. The method shown above prints something that looks kind of like a list, but it isn’t one functionally.

For the example above it would look something like the following:

alias: Set light brightness
mode: single
sequence:
  - repeat:
      for_each: >
        {% set ns = namespace( ip=[] ) %}
        {% set ip_add = {
          'light.gstudylights': '192.168.1.xxx', 'light.bathroomlights': '192.168.1.xx', 
          'light.lights': '192.168.1.xxx', 'light.lights_2': '192.168.1.xx', 
          'light.lights_4': '192.168.1.xx', 'light.lights_5': '192.168.1.xxx', 
          'light.lights_7': '192.168.1.xxx', 'light.lights_8': '192.168.1.xxx', 
          'light.walk_in_robe_lights': '192.168.1.xxx' } %} 
        {% set lights = state_attr('group.circadian', 'entity_id') %}   
        {% for entity in lights %}  
          {% set ns.ip = ns.ip + [ip_add.get(entity)] %} 
        {% endfor %}
        {{ ns.ip }}
      sequence:
        - service: rest_command.shelly_brightness
          data:
            ip: "{{ repeat.item }}" 
            brightness: "50"

Something similar to what @Didgeridrew has above

alias: Set light brightness
mode: queued
sequence:
  - repeat:
      for_each:
        - entity_id: light.lights
          ip_add: 192.168.1.144
        - entity_id: light.lights_2
          ip_add: 192.168.1.93
        - entity_id: light.lights_4
          ip_add: 192.168.1.58
        - entity_id: light.lights_5
          ip_add: 192.168.1.254
        - entity_id: light.lights_7
          ip_add: 192.168.1.188
        - entity_id: light.lights_8
          ip_add: 192.168.1.91
      sequence:
        - if:
            - condition: template
              value_template: "{{ is_state(repeat.item.entity_id, 'off') }}"
          then:
            - service: rest_command.shelly_brightness
              data:
                ip: "{{ repeat.item.ip_add }}"
                brightness: "{{ int(states('sensor.cl_brightness'))/255*100 }}"
          else:
            - service: light.turn_on
              data_template:
                entity_id: "{{ repeat.item.entity_id }}"
                brightness: "{{ states('sensor.cl_brightness') }}"
                transition: "30"
max: 10

if you are using the shellys, the if/then/else allows the brightness to be set for the shelly even when they are turned off. Super useful for those bathroom / bedroom lights not coming on too bright at night!

1 Like