What is the definition of "last_updated" on template sensors using webhook? Why is it not being updated?

Below is my config. My intention is this:

  • ESP32-C3 collects some sensor data from BT sensors and sends them to HA every 10 seconds
  • If data is not received in (say) 30 seconds, the sensor should become unavailable in HA

This works ok if the ESP32 stops sending data. The sensors indeed becomes unavailable.

Problem: the sensors become unavailable also if ESP32 succesfully sends the SAME value thrice during the 30 second window.

Why is the last_updated not working as expected and does not get updated even if the data is the same? Shouldn't there be a last_changed for that case? Or am I misunderstanding something else here?

(I'm still a n00b so I might've missed something important.)

template:
  - trigger:
      - platform: webhook
        webhook_id: esp32_multi_room_update
        allowed_methods: 
          - POST
        local_only: true
      - platform: time_pattern
        seconds: "/10"
    sensor:
      - name: "Living room Temperature"
        unique_id: living_room_temperature
        device_class: temperature
        state_class: measurement
        unit_of_measurement: "°C"
        state: >
          {% if trigger.platform == 'webhook' %}
            {{ trigger.json.living_room.temp }}
          {% else %}
            {{ this.state }}
          {% endif %}
        availability: >
          {% if trigger.platform == 'webhook' %}
            true
          {% elif this.state is undefined or this.state in ['unknown', 'unavailable'] %}
            false
          {% else %}
            {{ (now() - this.last_updated) <= timedelta(seconds=30) }}
          {% endif %}

Is there any specific reason you are using a webhook and not the HA api or MQTT?

HA ignores equal values to reduce recorder writes. You might want to use last_reported if you want to do things the hard way with webhooks.

You are misunderstanding what those properties mean...

The property last_changed is set when the state changes value. The property last_updated is set when either the state or any attribute value changes.

No! Just learning and trying things out with HA and ESP32. And I definitely would like to know what other and better ways there are and what are their stregths. AFAIK MQTT at least helps to reduce the network (and power) usage. I guess quite easy to implement. What other benefits MQTT or HA api has over webhooks? Would they make it easier to create what I'd like to have? At least it feels nice to be able to know if a device stops sending data and goes offline for prolonged time.

And I guess eventually it would make sense to just use ESPHome on the ESP32. But let's not change all variables at once :slight_smile:

Thansk, totally missed these three properties. last_reported is indeed the one I need in this use case.

But, it does not seem to work. The following also does not display anything for last-reported:

type: entities
entities:
  - entity: sensor.living_room_temperature
    secondary_info: last-updated
  - entity: sensor.living_room_temperature
    secondary_info: last-changed
  - entity: sensor.living_room_temperature
    secondary_info: last-reported

And it is not listed here:

Also, when looging at the state from Developer Tools, I only see Last Updated and Last Changed, not Last Reported.

Ah, if you are not using ESPHome then things are way, way more difficult. I would definitely look into ESPHome because you'd probably need only a few lines of yaml to define the entire firmware and have the sensors in HA the way you want them to. Whatever you are doing is much, much harder.

Last reported does not show in the attributes, but it is definitely there. It was added later, the card whs implemented before and probably did not add support for it later on. Try this in the template tester. It shows last_reported for the sun.sun entity:

{{ states.sun.sun.last_reported }}
2 Likes

Yeah, +1 on ESPHome, it makes almost anything possible to build, and rather easily at that :slight_smile:

FYI, when using trigger-based template sensor, you can store any additional data you need in the sensor itself, as an attribute. The data will survive Home Assistant restarts. So, your template might look something like this (untested):

template:
  - trigger:
      - platform: webhook
        webhook_id: esp32_multi_room_update
        allowed_methods: 
          - POST
        local_only: true
      - platform: time_pattern
        seconds: "/10"
    sensor:
      - name: "Living room Temperature"
        unique_id: living_room_temperature
        device_class: temperature
        state_class: measurement
        unit_of_measurement: "°C"
        state: >
          {% if trigger.platform == 'webhook' %}
            {{ trigger.json.living_room.temp }}
          {% else %}
            {{ this.state }}
          {% endif %}
        attributes:
          updated: "{{ now() if trigger.platform == 'webhook' else this.attributes.get('updated') }}"
        availability: >
          {% if trigger.platform == 'webhook' %}
            true
          {% elif this.state is undefined or this.state in ['unknown', 'unavailable'] %}
            false
          {% else %}
            {% set u = this.attributes.get('updated') %}
            {{ false if u is none else (now() - as_datetime(u)) <= timedelta(seconds=30) }}
          {% endif %}

FYI last reported has not been implemented on template entities. I haven't looked into the system yet, but I don't believe it's a built-in system. I believe I have to add it.

It is documented in the official docs for the state object and the first built in integration I checked had it. But it is of course possible that not all integrations set it.

I think it defaults to just update when last_updated or last_changed updates and integrations need to go out of their way to provide a timestamp when an update was received and the state didn't change. I haven't looked into this at all but @karwosts mentioned something like this in the past. I'm going off memory here and could be completely wrong.