Jinja2: dictionary for automation with helpers

Hi everybody,

I am trying to create a card that will allow me to toggle input_booleans that specify which entities ought to be triggered by an automation. Please stick with my, I’ll try to explain as well as I can…

input_booleans:

  • input_boolean.festlegen_gartenlicht_daslicht
  • input_boolean.festlegen_gartenlicht_fluter
  • input_boolean.festlegen_gartenlicht_lichterkette

I then want these entities to be mapped to actual light / switch entities, so I can include/exclude each one from the automation by toggling them.

However, I cannot figure out the exact jinja2 code for this. The final automation should look something like this

automation:
  - id:  aaaaa
    alias: "Motion activated garden lights"
    trigger:
      - platform: state
# (...)
    action:
      - service: homeassistant.turn_on
         entity_id: > 
            {{ template needs to go here }}

I use homeassistant.turn_on instead of light.turn_on because two of those entities are actual lights, one is a switch.

This is what I came up with in the templates UI so far, but it won’t work properly.

{% set light_dictionary = [{
"input_boolean.festlegen_gartenlicht_daslicht": "light.daslicht", 
"input_boolean.festlegen_gartenlicht_fluter": "light.fluter", 
"input_boolean.festlegen_gartenlicht_lichterkette": "switch.draussen_garten_lichterkette"
 }] -%}

{%- for state in light_dictionary -%}
{% if state.state == "on" -%}
  {{ light_dictionary["state"] }}
{% endif -%}
{%- endfor -%}

Expected behavior:

  1. check, which of those input_booleans is set to on
  2. return each dictionary_value for those entities with that state

So if input_boolean.festlegen_gartenlicht_fluter is set to on, I want to return light.fluter, if it is set to off, I don’t want to return anything. Same goes for those other two input_booleans.

To simplify my tests, I also tried this

{% set myd = [{'1': 'eins'}, {'2': 'zwei'}] %}
{{ myd['1'] }}

But it will only return UndefinedError: 'list object' has no attribute '1'. I then tried other variations, for example

{% set myd = {'1': 'eins'}, {'2': 'zwei'} %}
{{ myd['1'] }}

Which will return UndefinedError: 'tuple object' has no attribute '1'.

What am I doing wrong? I tried researching how to create a dictionary in jinja2, but must have missed something.

Thank you in advance for your ideas :slight_smile:

Remove the outer square brackets []. Otherwise, you are creating a list with a dict inside.

{% set light_dictionary = {
"input_boolean.festlegen_gartenlicht_daslicht": "light.daslicht", 
"input_boolean.festlegen_gartenlicht_fluter": "light.fluter", 
"input_boolean.festlegen_gartenlicht_lichterkette": "switch.draussen_garten_lichterkette"
 } %}

Also, your state.state thing probably won’t work.
Try something like

{%- for state in light_dictionary -%}
{% if is_state(state, "on") -%}
  {{ light_dictionary[state] }}
{% endif -%}
{%- endfor -%}

make it easier on yourself by having the dictionary created by the automation variables.

automation:
  - id:  aaaaa
    alias: "Motion activated garden lights"
    variables:
      config:
        input_boolean.festlegen_gartenlicht_daslicht: light.daslicht
        input_boolean.festlegen_gartenlicht_fluter: light.fluter
        input_boolean.festlegen_gartenlicht_lichterkette: switch.draussen_garten_lichterkette
      lights: >
        {% set booleans = expand(config.keys() | list) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list %}
        {{ config.items() | selectattr('0', 'in', booleans) | map(attribute='1') | list }}
      lights_are_on: >
        {{ lights | count > 0 }}
    trigger:
      - platform: state
# (...)
    condition:
    - condition: template
      value_template: "{{ lights_are_on }}"
    action:
      - service: homeassistant.turn_on
        target:
          entity_id: "{{ lights }}"
3 Likes

Using jinja2 to write these kind of things as compact as possible is of course an option. But you could also use an if statement and a state condition above the action. So you could also write the logic in yaml or use the gui to build it, no code required. And then of course there is the option to turn an automation itself on or of if you want to enable or disable that particular automation. All options will do the trick.

1 Like

Thank you so much, that is incredible!! My entire automation is below, in case anybody can benefit from the code.

I knew about variables, but never used them; they were introduced after my configuration was built, and I never had use for them (or so I thought!).

Where can I learn about things like expand(config.keys()) etc.? This seems to offer so many possibilities that I hadn’t even thought about. I read about variables in the docs, but is there some (ideally detailed) guide on how to use these jinja2 functions combined with variables?

automation:
  - alias: "Motion Gartenlicht"
    variables:
      config:
        input_boolean.festlegen_gartenlicht_daslicht: light.daslicht
        input_boolean.festlegen_gartenlicht_fluter: light.fluter
        input_boolean.festlegen_gartenlicht_lichterkette: switch.draussen_garten_lichterkette
      lights: >
        {% set booleans = expand(config.keys() | list) | selectattr('state', 'eq', 'on') | map(attribute='entity_id')  %}
        {{ config.items() | selectattr('0', 'in', booleans) | map(attribute='1') | list }}
      lichter_einschalten: >
        {{ lights | count > 0 }}
    trigger:
      - platform: state
        entity_id: binary_sensor.draussen_motion_garten_main_occupancy
        to: "on"
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: "{{ states('sensor.draussen_motion_garten_main_illuminance_lux') | int <= states('input_number.lux_fluter') | int }}"
        - condition: state
          entity_id: sun.sun
          state: "below_horizon"
        - condition: template
          value_template: "{{ lichter_einschalten }}"
    action:
      - service: homeassistant.turn_on
        target:
          entity_id: "{{ lights }}"