Template sensor was not updated when the only sensor in its template changed

A strange thing - and probably I totally missed smth obvious.

For some tests I needed to make some sensor “unknown”.
Opened Dev tools → set state & set “unknown” at ~18:04:

Here is a sensor’s code:

      - name: ac68u_nvram_usage
        icon: mdi:chip
        unit_of_measurement: '%'
        state_class: measurement
        state: >-
          {% set RAM_USED = states('sensor.ac68u_nvram_used') -%}
          {%- set RAM_TOTAL = '65536' -%}
          {{ ((RAM_USED | float) / (RAM_TOTAL | float) * (100 | float)) | round(1) }}
        availability: >-
          {{ not states('sensor.ac68u_nvram_used') in ['unavailable','unknown'] }}

So it depends only on a “sensor.ac68u_nvram_used”.
This sensor mainly has same value for a long time.
So, the derived “sensor.ac68u_nvram_usage” may stay “unknown” for a looooong time.

After tests I decided to set a “normal” value to the “sensor.ac68u_nvram_usage”.
So I changed a value of the original “sensor.ac68u_nvram_used” & then reverted to the prev. value (61875 → 61874 → 61875).

The “sensor.ac68u_nvram_used” was updated.
But the target “sensor.ac68u_nvram_usage” is still unknown.
I believed that the “sensor.ac68u_nvram_usage” will be re-evaluated - but it did not happen.
Why?

Both “61874” & “61875” give same “94.4” value:

But anyway the “unknown” value should be replaced by this “94.4”, correct?

I think order of operations may be your issue. This

        availability: >-
          {{ not states('sensor.ac68u_nvram_used') in ['unavailable','unknown'] }}

it is evaluating as:

        availability: >-
          {{ (not states('sensor.ac68u_nvram_used'))  in ['unavailable','unknown'] }}

You could try:

        availability: >
          {{ states('sensor.ac68u_nvram_used') not in ['unavailable','unknown'] }}

Or better yet:

        availability: >
          {{ has_value('sensor.ac68u_nvram_used') }}

I am not sure about this. Please check:

{% set VALUE  = 'unavailable' %}
{{ not VALUE in ['unavailable','unknown'] }}
{{ (not VALUE) in ['unavailable','unknown'] }}

{% set VALUE  = '111' %}
{{ not VALUE in ['unavailable','unknown'] }}
{{ (not VALUE) in ['unavailable','unknown'] }}


My guess about a possible reason is this:

      - name: ac68u_nvram_usage
        icon: mdi:chip
        unit_of_measurement: '%' !!!!!!!!!!!!!!!!
        state_class: measurement  !!!!!!!!!!!!!!!!!!!!!!

The “unknown” value is probably not permitted to a numerical value.
Although I did not have any messages in Log - I faced similar messages in cases when similar numerical sensors became “unknown” due to some reasons.
Right after reloading templates the “sensor.ac68u_nvram_usage” started working again.
So, imho finally it was MY error - applying the “unknown” value to a numerical sensor…

As for

{{ VALUE not in ['unavailable','unknown'] }}

It gives same seemingly correct results:

But what I think is:
“in” is an operand like “==”, “>”
you are not supposed to use “not” before an operand.

is this a trigger based template sensor? You shouldn’t ever get unknown with this template sensor.

If it is a trigger based template sensor, there are caveats and I believe you’re hitting them.

If this isn’t, then what you have will work without a problem.

I do suggest you change your availability template to

{{ has_value('sensor.ac68u_nvram_used') }}

Unfortunately, that’s not the case, python will resolve the x in y before the not.

2 Likes

Python is meant to be written like a sentence. I.e. easy to read.

You want to use:

x not in y

but

not x in y also works.

Sorry for not mentioning.
This is not a trigger-based.

I said that I made it “unknown” manually:

This is what I am using since my beginning with HA on 2020.

This has_value() function was added to HA later, I am keep using the “old check” in most places.

My guess (described here) about possible influence of UoM and state_class was not confirmed.
Tested with these sensors:

template:
  - sensor:
      - name: testing_unknown_1
        state: 12

      - name: testing_unknown_2
        <<: &ref_settings
          state: >-
            {{ states('sensor.testing_unknown_1')|float(default=0) *2 }}
          availability: &ref_availability >-
            {{ has_value('sensor.testing_unknown_1') }}

      - name: testing_unknown_3
        unit_of_measurement: '%'
        state_class: measurement
        <<: *ref_settings

Steps:

  1. Assign “unknown” value to “sensor.testing_unknown_2” & “testing_unknown_3” manually via Dev tools → set state.
  2. Change a value of “sensor.testing_unknown_1” to a diff. one (12 → 23).
  3. Both “sensor.testing_unknown_2” & “testing_unknown_3” were re-evaluated properly.

So, have no idea what could cause the glitch from the 1st post.

There’s many reasons set state is not suggested, this is one of them. Technically under the hood, no sensor actually gets the state ‘unknown’ or ‘unavailable’.

Could you tell me where can I get more info about these reasons?

These aren’t documented reasons. The set button on the states page just puts a value into the states machine state object. It’s the only place this is possible and it’s a legacy function. In general, you are not meant to set the state of state objects.

This is called a Dev tools and probably purposed to debugging.
This is what I did - debugging.
And I wonder - not mainly “why I cannot apply an unknown state” - but mainly “why my sensor was not re-evaluated from a manually set unknown state”.

Repeat once again:

  1. Current value:
    изображение

  2. Set it to “unknown”:

  3. It seems to be set to “unknown”:

  4. Now take the sensor from which the changed sensor depends on:

  5. And change a value a bit:

  6. But the target sensor is still unknown:

Why?

So, sensor was not re-evaluated.

ahahaha
Same behaviour if I set a value not to “unknown” but for some number.

Initial:


Set it 95 manually:

It is shown as 95:

Change a sensor a bit - from

to

But the target sensor is not re-evaluated:

Because it’s not actually going into the state machine. It’s like covering a cut with a band aide. Cut still exists even though you only see the bandaide. Same thing is happening when you use set state. The data under the hood isn’t altered, you’re just changing what you see.

FWIW, I have never ever had to use set state in my history with HA. You can debug without it. I’m not sure why so many people rely on it.

This statement raises too many questions.
Set a value manually:
изображение
What I see in Template:

Are you saying that the template in this example returns a not-actual value?

Sorry, but without getting into the details of python and how setting/getting properties works, this is going to be too complicated for me to explain. Just know that when you set the state, you are bypassing many things that you normally wouldn’t bypass.

If you understand it - you should be able to explain.
At least this could be useful for other users who understand Python.
(myself never dealt with it, mainly C/C++)

Without going into the details too much, it’s like a cached value. When you use set state, you’re just changing the cached value, not the actual value.

When I call a “states(xxx)” in Dev tools - does it use an actual or a cached value?

states is a cached_property

This is why I didn’t want to get into this. You need to understand python and random libraries used by HA.

I wouldn’t say random libraries, this is built-in. But it’s still requires a high level of knowledge versed in coding and/or python. I’m sure other languages have equivalent decorators.