Templates inside templates

This might be a stupid question, but I have severe problems to understand how to use templating in YAML code. I want to iterate through a list of climate entities and update all temperature settings with data from list of input helpers. I also want to save current temperature setting to another list of input helpers before I update the temperature setting. My intention is to be able to change temperature settings for a group of thermostates and support multiple settings like at “home”, “away” etc.

I have an automation that loops through a list of items. The items is used to build up strings representing entiies. And I want to read states and attributes and update other entities. However, I end up with templates inside a template and that does not work. I have tried different variants for two days now, but I can’t figure out how to solve this.

    repeat:
      for_each:
        - "a"
        - "b"
        - "c"
       
      sequence:
        - variables:
            current_temperature: "{{states.climate.{{repeat.item}}.attributes.temperature |float(0)}}"
            new_temperature: "{{states('input_select.'{{repeat.item}}_{{trigger.to_state.state}})|float(0)}}"
        - action: input_number.set_value
          target:
            entity_id: "input_number.{{repeat.item}}_{{trigger.from_state.state}}"
          data:
            value: "{{current_temperature}}"
        - action: climate.set_temperature
          target:
            entity_id:
              - "climate.{{repeat.item}}"
          data:
            temperature: "{{new_temperature}}"

Untested, but should work:

    repeat:
      for_each:
        - "a"
        - "b"
        - "c"
       
      sequence:
        - variables:
            current_temperature: "{{ state_attr('climate.'~repeat.item,'temperature')|float(0) }}"
            new_temperature: "{{ states('input_select.'~repeat.item~'_'~trigger.to_state.state)|float(0) }}"
        - action: input_number.set_value
          target:
            entity_id: "input_number.{{ repeat.item }}_{{ trigger.from_state.state }}"
          data:
            value: "{{ current_temperature }}"
        - action: climate.set_temperature
          target:
            entity_id:
              - climate.{{ repeat.item }}
          data:
            temperature: "{{ new_temperature }}"

You can test in Developer Tools / Template Editor to some extent, setting up your own repeat and trigger structures as required:

The key here is to use methods that use strings that you can build up rather than direct references, so states(), state_attr() rather than the dot references to the entities. See the warning box on the Templating page:

@Troon , You made my day!

Yea, i’m aware of the state_attr() and states() functions, but not the use of ~ in templates ! That caused me a lot of pain. Now everything works fine. However, first I had to fix a mistake using input_number instead och input_select…

1 Like

It’s just string concatenation — you could also use + there.

https://jinja.palletsprojects.com/en/latest/templates/#math
https://jinja.palletsprojects.com/en/latest/templates/#other-operators

A tilde (~) is the concatenation operator.

The + symbol is often used to do the same thing but it can produce unexpected results if one or more of the items to be concatenated is a number not a string.

FWIW, here’s another way to do the same thing (without ~ ).

    repeat:
      for_each:
        - "a"
        - "b"
        - "c"
      sequence:
        - variables:
            x: climate.{{ repeat.item }}
            y: input_select.{{ repeat.item }}_{{ trigger.to_state.state }}
            current_temperature: "{{ state_attr(x, 'temperature') | float(0) }}"
            new_temperature: "{{ states(y) | float(0) }}"
        - action: input_number.set_value
          target:
            entity_id: "input_number.{{ repeat.item }}_{{ trigger.from_state.state }}"
          data:
            value: "{{ current_temperature }}"
        - action: climate.set_temperature
          target:
            entity_id: "{{ x }}"
          data:
            temperature: "{{ new_temperature }}"