Sensor availablitiy during previous 24h?

I’m just programming my garden irrigation system relying on ESPhome and the sprinkler component. The system relies on two sensor values:

  • soil moisture
  • max temperature during the last 24h

Both are provided by HA. So far I’m only simulating the sensors using number components as I don’t have meaningful sensor values available (it’s winter).
My soil moisture sensor value is provided by a battery driven ESPhome device which most of the time is in deep sleep but delivers the value every 30 min.

As it might happen that the battery (of the soil moisture sensor) goes low, no further sensor values will be deliverd. Hence no more irrigation. Which might be bad, if I’m on holiday and cannot charge the sensor’s battery.

As I can see from the entity in HA, HA knows that the sensor/device is unavailable. In my case, due to deep sleep, directly checking availability seems to be meaningless. So I would like to have something which tells me if the device/sensor was available during the last 24h. So far, I have only made automations in HA “by clicking”. Therefore, I feel lost here. I guess, I would need to create a helper for that does the job. Still, I have no clue which one might be suitable.

Another possibility might be to get a kind of timestamp when the device/sensor was last available and evaluate this. Perhaps directly in ESPhome.

Any help is appreciated!

Matthias

I progressed a little bit. Playing around in the template editor I found out that

{{ relative_time(states.sensor.feuchtegarten.last_reported) }}

provides me with the information how long ago the last value arrived.

{% if relative_time(states.sensor.feuchtegarten.last_reported) < '24 hours' %}
  True
{% else %}
  False
{% endif %}

is about what I need. But I need to assign the output somehow to a variable, perhaps something like a helper of the type input_boolean.
And then, it needs to be checked regularly, e.g. once per hour.
I tried looking at the YAML editor of automations. This provides me for a start with

description: ""
mode: single
triggers: []
conditions: []
actions: []

This, I simply cannot bring together with the above template code. Sorry, but my mind seems to be blocked, there. To me it seems that only a little step is missing. Could anyone provide me with what I am missing, please?

Use the UI to create an automation, point and click.

Create the input boolean template helper and set the state using your relative time Jinja. Create an automation that runs every hour that checks the state of the boolean and sends a notification or whatever else you would like.

Here is some yaml of a time triggered automation (every 15 mins), but I highly recommend using UI to generate yaml.

alias: Outdoor Lights - Dusk/Dawn Routine
description: >-
  Every hour check if sun is past sunset or in a certain time period to control
  On/Off
triggers:
  - trigger: time_pattern
    minutes: /15
conditions: []
actions:
  - parallel:
      - if:
          - condition: and
            conditions:
              - condition: or
                conditions:
                  - condition: time
                    after: sensor.home_sun_dusk
                  - condition: time
                    before: sensor.sun_next_dawn
        then:
          - if:
              - condition: state
                entity_id: light.cync_lan_769962427_25
                state: "off"
            then:
              - data:
                  transition: 2
                  brightness_pct: 100
                action: light.turn_on
                target:
                  device_id:
                    - 2024ab03a8b21321061c906f182a01cc
          - if:
              - condition: state
                entity_id: light.cync_lan_769962427_24
                state: "off"
            then:
              - data:
                  transition: 2
                action: light.turn_on
                target:
                  device_id:
                    - 030de80e5eaa8fba60915344db79e08a
      - if:
          - condition: time
            after: sensor.home_sun_dawn
            before: sensor.home_sun_dusk
        then:
          - if:
              - condition: state
                entity_id: light.cync_lan_769962427_24
                state: "on"
            then:
              - data:
                  transition: 3
                action: light.turn_off
                target:
                  device_id:
                    - 030de80e5eaa8fba60915344db79e08a
          - if:
              - condition: state
                entity_id: light.cync_lan_769962427_25
                state: "on"
            then:
              - data:
                  transition: 3
                action: light.turn_off
                target:
                  device_id:
                    - 2024ab03a8b21321061c906f182a01cc
mode: single

That’s exactly my problem. I don’t know how I should do this and be sure that it is updated regularly.

The template code “listens” for state changes on the source sensors. So whenever any of the sensor states change, the input bool will be re-evaluated.

Edit: or attrs, whatever you’re listening to, basically.

And that’s the problem here. When the battery fails, there is no state change anymore.

Let me explain. I created a template, which at first seems to do the job:

  - sensor:
    - name: "Feuchte Garten Aktivität"
      unique_id: "FeuchteGartenAktivitaet"
      state: >-
        relative_time(states.sensor.feuchtegarten.last_reported) < '2 hours'

(only 2h instead of 24h for testing; I call this sensor "FGA sensor from no on)

While the battery is in my moisture sensor, which provides a reading every 30 min, the FGA sensor value is true. Which is as desired and expected.

But when I take out the battery and wait for some hours (> 3h), the FGA sensor value remains true instead of going to false. This sounds logic to me as the moisture sensor does not provide any new readings, hence no state change to the “last_reported”.

I think, I need some way to update the calculation of “relative_time” once every hour, but I’ve no clue how to do that, as I’m just doing my first steps in template programming/advanced automations.

I did it also in the template editor and started it yesterday evening (I’m in Europe):

{{states.sensor.feuchtegarten.last_reported }}
{{relative_time(states.sensor.feuchtegarten.last_reported) }}
{{ relative_time(states.sensor.feuchtegarten.last_reported) < '2 hours' }}

The result window shows now in the morning:

2025-02-15 21:24:37.931122+00:00
10 hours
True

This is absolutely strange to me, as the template editor says that it’s updated every minute and the relative time calculation seems to be correct. However, the comparison reports the wrong result. What’s wrong, here?

Using timestamps seems to be a better idea (see How to calculate / subtract two date.time from eachother? - #5 by keatontaylor and the rest of the thread).

{{relative_time(states.sensor.feuchtegarten.last_reported) }}
{{ relative_time(states.sensor.feuchtegarten.last_reported) < '2 hours'}}
{{ as_timestamp(now()) - as_timestamp(states.sensor.feuchtegarten.last_reported) < 7200 }}

results in:

53 seconds
False
True

But I’ll have to wait if it gets updated outside the template editor. Since I’m using “now()”, I assume it will.

I finally managed it:
My template looks like:

  - sensor:
    - name: "Feuchte Garten Aktivität"
      unique_id: "FeuchteGartenAktivitaet"
      state: >
        {{ as_timestamp(now()) - as_timestamp(states.sensor.feuchtegarten.last_reported) < 86400 }}

Most of my “problems” were due to the fact that I hadn’t written a template before. Perhaps I should have practiced more rubber ducking (Dilbert about rubber ducking).

Nevertheless, thanks a lot for your input, @baudneo !

Awesome. I forgot that there needs to be forced “time interval” re-evals. This is the same problem plaguing the derivative integration (derivative never returns to 0). The integral sensor had the same problem that was remedied by a “time sub-interval” that forced the sensor to re-eval it’s state and send an update even with no changes.