Template sensor: using this.state in an attribute template

Can anyone help me understand the correct way to refer to the state value of a sensor when setting an attribute? I have been using states('sensor.thing') as part of the attribute template but moved over to using this.state after reading posts to this forum. At least one of my instances is now returning the wrong value (as if this.state does not exist). As an example I’ve got this:

  - trigger:
    - platform: time_pattern
      minutes: "/5"
    sensor:
      - name: rnli_dclass
        unique_id: rnli_dclass
        state: >
          {% if states('sensor.sun_solar_elevation')|float < -6 %}
            {{'ILB in darkness conditions'}}
          {% elif as_timestamp(states('sensor.sun_next_dusk'),0) < as_timestamp(now(),0)+2*3600 %}
            {{+ 'Dark within (h:m) ' ~ (as_timestamp(states('sensor.sun_next_dusk'),0) - as_timestamp(now(),0))|timestamp_custom("%H:%M",true)}}
          {% else %}
            {{"Light OK"}}
          {% endif %}
        attributes:
          wind: >
            {% if this.state == "Light OK" %}
              {% if state_attr('sensor.wind_display','gusts')|float(0) > 21 %}
                {{ 'Wind over F5' }}
              {% else %}
                {{ 'Wind OK' }}
              {% endif %}
            {% else %}
              {% if state_attr('sensor.wind_display','gusts')|float(0) > 16 %}
                {{ 'Wind over F4' }}
              {% else %}
                {{ 'Wind OK' }}
              {% endif %}
            {% endif %}

this.state == "Light OK" is never true.
Of course I can’t test this in Developer Tools as this.state doesn’t exist there. Can anyone help me improve my understanding please?

this.state returns the previous state of the entity. Not the current state. Incorrect. See below. Or maybe not. Keep reading…

this.state is always the previous state, unless you’re in the attribute templates. At that point, this.state will be current.

The order of operations on template sensors (without triggers) is:

  1. availability
  2. state
  3. everything else
2 Likes

Thanks. So I should revert to using states( to get the current value?

The state machine follows the same rules.

You are calculating the current result. If you want it 100% to be the current result, then re-do the calculation.

Blimey. So how do I refer to the sensor’s current state when setting an attribute?

Are you glossing over my response?

Didn’t mean to be rude. My phone didn’t show me you response before I replied. Sorry.
I must admit this is a pain because there are several instances where I do some complex processing in the state value which I reuse in setting attributes. I thought I was clever avoiding repeated code. Ho hum.
Thanks for your help.

TIL.

Now I’m unclear again. If I’m setting an attribute of a trigger sensor, am I “in the attributes templates”? See the code I posted at the start for what I was doing.

Yes you are using this.state under attributes in the template sensor, so it will be the current state.

So my original question stands: as you can see from the code I’m using this.state in setting an attrubute, but it is not returning the current value of the sensor. Am I right in thinking I can’t do any testing using this.state in dev tools?

Yes you are. Just a minute I’m having a closer look at your original post. If I see anything amiss I’ll let you know.

I can’t see anything obviously wrong. You don’t have to put plain string results in templates, but it shouldn’t cause any issues either. Also if the + in the first state template {{+ 'Dark within etc... was supposed to be for concatenation, it isn’t doing anything.

  - trigger:
    - platform: time_pattern
      minutes: "/5"
    sensor:
      - name: rnli_dclass
        unique_id: rnli_dclass
        state: >
          {% if states('sensor.sun_solar_elevation')|float < -6 %}
            ILB in darkness conditions
          {% elif as_timestamp(states('sensor.sun_next_dusk'),0) < as_timestamp(now(),0)+2*3600 %}
            {{ 'Dark within (h:m) ' ~ (as_timestamp(states('sensor.sun_next_dusk'),0) - as_timestamp(now(),0))|timestamp_custom("%H:%M",true)}}
          {% else %}
            Light OK
          {% endif %}
        attributes:
          wind: >
            {% if this.state == "Light OK" %}
              {% if state_attr('sensor.wind_display','gusts')|float(0) > 21 %}
                Wind over F5
              {% else %}
                Wind OK
              {% endif %}
            {% else %}
              {% if state_attr('sensor.wind_display','gusts')|float(0) > 16 %}
                Wind over F4
              {% else %}
                Wind OK
              {% endif %}
            {% endif %}

Thanks for your help again Tom.
I’ll tidy up as you suggest but as this.state isn’t working and in this instance the test I’m avoiding replicating is so simple, I’ll go with the suggestion of repeating states('sensor.sun_solar_elevation')|float < -6. I’ll look at my other instances of referring to the sensor’s value at some time & see if they are misbehaving.

So the sun is well above the horizon now and the state of your sensor is 'Light OK'?

:+1: Yes it is.

That could be a bug then, if it is supposed to work the way petro outlined above.

Try creating a simpler test:

  - trigger:
      - platform: time_pattern
        minutes: "/1"
    sensor:
      - name: Test
        unique_id: testytestytest
        state: "{{ now() }}"
        attributes:
          copy_of_state: "{{ this.state }}"

Does that work as expected?

I’d do it but am on mobile ATM.

Immediately after putting this ino configuration.yaml i get

Test
2023-10-11 16:51:00.186171+01:00	friendly_name: Test
copy_of_state: unknown

A few minutes later:

[sensor.test](http://192.168.0.87:8123/developer-tools/state#)

Test 2023-10-11 16:52:00.187728+01:00 friendly_name: Test copy_of_state: 2023-10-11 16:51:00.186171+01:00

So it does indeed return the previous state despite being in the attributes section…

Ok so it isn’t reporting the current state. It is reporting the previous state. Note the 1 minute difference between the state and the copy.