How to template 'long form' states?

Is it possible to template the following if I know what the value for ROOM is?

{% set change_time = states.sensor.heating_[ROOM]_active_schedule_number.last_changed %}

Using the ‘short form’ I can do something like states('sensor.' ~ ROOM ~ '_temperature') but as far as I know last_changed isn’t available that way.

(Obviously I can do it with if...then)

Yes.

Use the set to create a variable that contains the entity Id of the sensor. Not sure how you get “room”, in the example below I assume it comes from a prior set statement.

{% set sensor = “sensor.heating_{{room}}_active_schedule_number” %}
{{ states(sensor) }}
{% set change_time = expand('sensor.heating_'~ROOM~'_active_schedule_number')
| map(attribute='last_changed') | first %}

Yes I know that but I need last_changed
To be fair I think my wish to keep the question brief might have made it less obvious what I meant.

I currently do (something like) this;

{% if trigger.id = 'kitchen' %}
  {% set change_time = states.sensor.heating_kitchen_active_schedule_number.last_changed %}
{% elif trigger.id = 'hall' %}
  {% set change_time = states.sensor.heating_hall_active_schedule_number.last_changed %}
{% endif %}

Lots more stuff goes in each if, elif all of which can be templated using trigger.id
Id like to do something like this, which obviously doesn’t work

{% set change_time = states.sensor.heating_{{ trigger.id }}_active_schedule_number.last_changed %}

@Didgeridrew
That looks great, thanks!

You can also do it using the state object method, by bracketing the object_id (make sure to leave out the . after the domain):

{% set change_time = states.sensor['heating_'~room~'_active_schedule_number'].last_changed %}

Great thanks. I knew about expand, just hadn’t put two and two together to use it here!.
Bracketing this way is new to me.

Thanks again!

You cannot use expressions {{}} inside other expressions or inside statements {%%}. In other words, you cannot nest templates inside other templates.

For future reference:

  • If you need to create a Jinja2 variable, use Didgeridrew’s answer (i.e. bracket notation).

  • If your application provides the opportunity to define your variable as a script variable, you have another possibility.

For example, assume it’s a script and ROOM is a variable passed to the script.

sequence:
  - variables:
      change_time: "states.sensor.heating_{{ ROOM }}_active_schedule_number.last_changed"

Now the script variable change_time can be referenced elsewhere in the script.

1 Like

:heavy_check_mark:

I can’t believe I didn’t think of that it’s so obvious.
But then many genius ideas are obvious once you realise.

Excellent. Thanks to you too!

That leads to a slightly separate question…
Do you know if variables are set strictly in the order they are ‘declared’? e.g.

variables:
  variable_1: >
    {{ trigger.id.split('.')[1] }}
  variable_2: >
    {{ states('sensor.my_sensor_' ~ variable_1) }}

Will variable_2 always have access to a fully resolved variable_1?