Using template variable for template

Hello,

Im sure Im missing a bracket or something stupid. Im trying to get the current state of a sensor, but using the trigger.entity_id in states(), but it keeps showing unknown. If I use the actual sensor name it works, but I have 4 diffrent triggers and I want to email the state of the one that triggered it.

This doesnt work: {{states(’{{ trigger.entity_id }}’)}} (returns “unknown”)
This does work: {{states(‘sensor.lexmark_cx410e_cyan’)}} (returns the state)
If I just want to see the sensor name and use {{ trigger.entity_id }} the proper name is returned.

Im doing testing from actual sensor device, and not just running from the HA UI.

What am I doing wrong here ?

How about these:

{{ trigger.from_state }}
{{ trigger.to_state }}

That returns way too much info…

<state sensor.lexmark_cx410e_black=10; marker_high_level=100, marker_low_level=21, marker_type=toner-cartridge, unit_of_measurement=%, icon=mdi:water, friendly_name=Lexmark CX410e Black @ 2023-11-02T11:15:04.389310-04:00>

I just need to return the state, like this does {{states(‘sensor.lexmark_cx410e_cyan’)}} .

We cant use the Template Variables with in the states() or states. ? (cuz I did try both ways)

How about:

{{ trigger.from_state.state }}
{{ trigger.to_state.state }}

Ok that did work! Thank you so much!
But my question remains, We cant use the Template Variables with in the states() or states. ?

Can you provide your yaml code for the automation (properly formatted) and indicate where you want the state value inserted?

Here you are:

alias: Ink Lexmark Below 15%
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.lexmark_cx410e_black
    below: 15
  - platform: numeric_state
    entity_id: sensor.lexmark_cx410e_cyan
    below: 15
  - platform: numeric_state
    entity_id: sensor.lexmark_cx410e_magenta
    below: 15
  - platform: numeric_state
    entity_id: sensor.lexmark_cx410e_yellow
    below: 15
condition: []
action:
  - service: notify.XXXXX
    data:
      message: >-
        The {{ (trigger.entity_id.split('.')[1].split('_') |join(' ')).title()
        }} Cartridge went below {{trigger.below}}% and is now at {{
        trigger.to_state.state }}% please change the cartridge. {{"\n"}} Current Cartridge
        Levels are: {{"\n"}} BLACK:{{states('sensor.lexmark_cx410e_black')}}%
        {{"\n"}} CYAN:{{states('sensor.lexmark_cx410e_cyan')}}% {{"\n"}}
        MAGENTA:{{states('sensor.lexmark_cx410e_magenta')}}% {{"\n"}}
        YELLOW:{{states('sensor.lexmark_cx410e_yellow')}}% {{"\n"}}
      title: >-
        The {{ (trigger.entity_id.split('.')[1].split('_') |join(' ')).title()
        }} Priter Cartridge is Low
mode: single

Where I have the {{trigger.to_state.state }}, I wanted to add the {{states(’{{ trigger.entity_id }}’)}, but I`m also thinking for the future to use template variables in actions based on the trigger.

How about

{{ states(trigger.entity_id) }}

I knew it was something stupid. That makes sense now, one last question. Whats the format for using with states. ? OR we shouldnt be using that.

And thank you so much !!!

Sorry, @stev3 , I don’t understand

Can you give an example of what you are trying to do?

Why? You’d just be re-rendering something that has already been rendered.

Sorry I was not clear.

So if we wanted to do something like this:

states.sensor.lexmark_cx410e_cyan.state

but instead with template variable like this:

states.{{trigger.entity_id}}.state

whats the proper format to get this going ?

because this does not work.

{{states.trigger.entity_id.state}}

This is for this example, but I was talking in general on how to properly use that, which was answered thanks to @templeton_nash

But the better answer is to use {{ trigger.to_state.state }}. The only case where you should re-render the state is if the source entity is changing and you absolutely need an up-to-date value. For example if you are waiting for a second threshold to be met.

With the above in mind, you would use bracket notation i.e.
{{ states[trigger.entity_id].state }}

But, as noted in the docs, you should use the states() method whenever possible instead of the state object method.

I think you want:

{{ states(trigger.entity_id) }}

What you wrote implies you aren’t clear about the difference between the trigger variable and an entity’s entity_id.

The states() function expects to receive a string representing an entity’s entity_id. For example:

{{ states('sensor.whatever') }}

The trigger variable is an object containing several properties. One of those properties is the entity_id of whichever entity was responsible for triggering the Numeric State Trigger. So trigger.entity_id contains a string value representing the entity’s entity_id. For example:

{{ states(trigger.entity_id) }}

Notice how that differs from what you tried:

{{states('{{ trigger.entity_id }}')}

Your version contains several errors such nesting one template inside another and wrapping a variable in quotes.

Going back to the trigger variable, one of its other properties is to_state and it has a property called state. In other words, this:

{{ trigger.to_state.state }}

provides the same result as this:

{{ states(trigger.entity_id) }}

Reference

State Objects

There are situations where this won’t be the case, although they are unlikely. If the automation actions take sufficient time to run and the state of the entity changes during this time, then the trigger.to_state may not be the current state. Sorry, I’m being pedantic, but safer to use the trigger.to_state to find the state, if you want to be sure to get the new state at the time the automation triggered.

Yep that is the point, you want to get the value of the sensors state, not what triggered it. In my current automation its not important… but in general I like to know.

And I do see now, where my mistakes were, thank you for all the explanations, this hellped me a lot.

stev3’s automation is the context for the explanation I posted above. The time between when his automation is triggered and when it executes its first action is on the order of microseconds. The odds of the entity changing state yet again during that very short time period are rather small, to say the least.

On the other hand, if the automation included actions that served to stretch the time period between being trigger and evaluating the template {{ states(trigger.entity_id) }} (such as delay, wait_template, wait_for_trigger, repeat, etc) then I agree with you that there’s an increased chance of a possible difference between the template’s value and trigger.to_state.state. But that’s not the case for stev3’s example.

No worries. It’s important to clarify the details so everyone gains a better understanding.

FWIW, I normally use trigger.to_state.state because it seems inefficient to employ an extra step with states() when the trigger object already has the entity’s state in to_state.state.

2 Likes

Try this version. Let me know the result.

action:
  - service: notify.XXXXX
    data:
      message: >
        The {{ trigger.to_state.object_id.replace('_', ' ') | title }} cartridge went below {{ trigger.below }}% and is now at {{ trigger.to_state.state }}%  please change the cartridge.

        Current Cartridge Levels are:
        {% for c in expand('sensor.lexmark_cx410e_black', 'sensor.lexmark_cx410e_cyan',
           'sensor.lexmark_cx410e_magenta', 'sensor.lexmark_cx410e_yellow') -%}
        {{ c.object_id.split('_')[-1] | upper}}: {{ c.state }}
        {% endfor -%}
      title: >
        The {{ trigger.to_state.object_id.replace('_', ' ') | title }} Printer Cartridge is Low
mode: single
  • A template’s line endings are literal so the template shouldn’t require explicit line-breaks {{\n}}.
  • A for-loop is used to iterate through the four ink sensor colors.
  • The entity’s object_id is used directly instead of splitting its entity_id.