What is the difference between states and state_attr

{{  now()  - states.sensor.helligkeit.last_updated   }}    
{{  now()  - state_attr('sensor.helligkeit','last_updated')   }}

Only the first one works, why is that?

0:01:14.568738
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'NoneType'

states.sensor.helligkeit is a “state” object.

state_attr('sensor.helligkeit','last_updated') is basically equivalent to states.sensor.helligkeit.attributes.last_updated. It is a template extension that accesses the attributes property of the state object.

Therefore, states.sensor.helligkeit.last_updated is not the same as states.sensor.helligkeit.attributes.last_updated.

See state object and state template extension docs.

So, there is nothing similar to states.sensor.helligkeit.last_updated in a state template extension?

I don’t see anything like that in the docs. What do you need one for? If you need to handle an undefined state (state is None), then you can just add on the default filter.

{{ states.sensor.helligkeit.last_updated | default('unknown') }}

Replace “unknown” with your default value.

Or use some if/else template logic.

Since Watchman doesn’t yet monitor state objects, I thought I could convert them. But I guess the plugin needs an update to do that.

Except last_updated is not an attribute it is a property. So that first one wont work.

I just explained it here:

would be interested to see an example of if/else logic for state_attr
as an example:

I have a door attr that is one of 3 things… true(closed), false(open), or unknown
image

Can’t seem to figure out the logic for a template… (also trying to use the template tab in developer tools… my brain just isn’t happening tonight.

- sensors:
  - name: "Sauna Door"
    state: >-
       {% if state_attr('sensor.sauna_status', 'door') %}
         Closed
       {% elif state_attr('sensor.sauna_status', 'door') %}
         Open
       {% else %}
         Unknown
       {% endif %}
template:
  - binary_sensor:
      - name: "Sauna Door"
        state: "{{ is_state_attr('sensor.sauna_status', 'door', 'open') }}"
        device_class: door

Or possibly this if your attribute value is capitalised:

template:
  - binary_sensor:
      - name: "Sauna Door"
        state: "{{ is_state_attr('sensor.sauna_status', 'door', 'Open') }}"
        device_class: door
2 Likes

got this far with your assistant…

- sensor:
  - name: "Sauna Door"
    device_class: door
    state: >
       {% if is_state_attr('sensor.sauna_status', 'door', true) %}Closed
       {% elif is_state_attr('sensor.sauna_status', 'door', false) %}Open
       {% else %}Unknown{% endif %}
    icon: >
       {% if is_state_attr('sensor.sauna_status', 'door', true) %}mdi:door-closed
       {% elif is_state_attr('sensor.sauna_status', 'door', false) %}mdi:door-open
       {% endif %}

did see you put it as a binary sensor, I’m still learning this part, so why not just a sensor?

1 Like

this helps a little more… https://www.home-assistant.io/integrations/binary_sensor/

But having an “Unknown” option, would that still classify as a binary sensor?

No but using the binary sensor device class “door” considerably simplifies things. No need to specify the states or icons. They are all done automatically.

You can add an availability template for the unavailable state.

template:
  - binary_sensor:
      - name: "Sauna Door"
        state: "{{ is_state_attr('sensor.sauna_status', 'door', true) }}"
        availability: "{{ state_attr('sensor.sauna_status') in [ true, false] }}"
        device_class: door
1 Like

that is even better! thanks for the tip

Just updated my post with the unavailable option.

I believe there is a syntax error in your availability line.


2022-05-24 23:11:24 ERROR (MainThread) [homeassistant.components.template.template_entity] TemplateError('TypeError: state_attr() missing 1 required positional argument: 'name'') while processing template 'Template("{{ state_attr('sensor.sauna_status') in [ true, false ] }}")' for attribute '_attr_available' in entity 'binary_sensor.sauna_door'

Updated it to this: (was missing the ‘name’) of the attr.

- binary_sensor:
  - name: "Sauna Door"
    device_class: door
    state: "{{ is_state_attr('sensor.sauna_status', 'door', true) }}"
    availability: "{{ state_attr('sensor.sauna_status', 'door') in [ true, false ] }}"

however… this ended up showing the door as open… when it was really closed, so logic is backwards.
I ended up removing the availability line for now and went with this instead:

- binary_sensor:
  - name: "Sauna Door"
    device_class: door
    state: >
       {% if is_state_attr('sensor.sauna_status', 'door', true) %}Closed
       {% elif is_state_attr('sensor.sauna_status', 'door', false) %}Open
       {% else %}Unknown{% endif %}

It was. Good catch.

That is not valid. Binary sensor templates can only resolve to true or false. If you want to use the binary sensor and want the unavailable state you have to use the availability template.

1 Like

got it to this…


- binary_sensor:
  - name: "Sauna Door"
    device_class: door
    state: >
       {% if is_state_attr('sensor.sauna_status', 'door', true) %}Closed
       {% elif is_state_attr('sensor.sauna_status', 'door', false) %}Open
       {% endif %}
    availability: "{{ state_attr('sensor.sauna_status', 'door') in [ true, false ] }}"
1 Like

Again, no.

Your state template is resloving to Closed or Open, not true or false, as is required for binary sensor templates. The true or false state of the binary sensor template will be converted to on or off by the binary sensor platform, which will then be translated to Open or Closed by the device class. You don’t define the state as Open or Closed in the template. Only true or false.

This will do:

state: "{{ is_state_attr('sensor.sauna_status', 'door', true) }}"
availability: "{{ state_attr('sensor.sauna_status') in [ true, false] }}"
device_class: door

Ideally you could use just:

state: "{{ state_attr('sensor.sauna_status', 'door') }}"
availability: "{{ state_attr('sensor.sauna_status') in [ true, false] }}"
device_class: door

As the attribute has the true/false state already. However the unavailable state will cause an error (as the template should only resolve to true or false for a binary sensor). I think there was talk of not evaluating state templates unless the availability template resolved true first but don’t think this has been implemented yet.

You could do this:

state: "{{ state_attr('sensor.sauna_status', 'door')|bool(0) }}"
availability: "{{ state_attr('sensor.sauna_status') in [ true, false] }}"
device_class: door

The boolean filter with default false (0) will not generate an error for the attribute unavailable state. And the availability template will take over in that case.

1 Like