Long Term Duration for Numeric State Trigger (7+ days)

I have salt pool and as soon as the water temperature fell below 62F I removed the salt cell and now I want to prepare for when it gets warm enough again to reinstall it.
I’ll probably do this as soon as the water temperature has been above 61F for 7 (or maybe just 5) days - or something similar.

I know that I can - theoretically - use a numeric state trigger like this:

trigger:
  - platform: numeric_state
    entity_id:
      - sensor.pool_temp
    for:
      hours: 168
      minutes: 0
      seconds: 0
    above: 61

But, if I understand it correctly, this will not work, i.e. the trigger will be reset, if I restart Home Assistant e.g. 2 days after the threshold value has been crossed - or will it?

I’d also like to have a sensor that shows me how far I am into the 7 (or 5) days at any time as soon as the threshold value has been crossed.

Right now I can only come up with a convoluted approach that involves an input_datetime helper that’s reset every time the threshold is crossed and then uses a date/time-diff calculation in a sensor to keep track of the time that has passed since the last reset took place.

Any better/ simpler ideas out there?

Something like this should work but I haven’t tested it:

template:
  - trigger:
      - platform: state
        entity_id:
          - sensor.pool_temp
        not_to:
          - unavailable
          - unknown
        variables:
          above_threshold: "{{ trigger.to_state.state | float(0) > 61 }}"
    binary_sensor:
      - name: "Pool above 61"
        unique_id: e569a857-999f-4022-ae78-adcdaad606e0  
        state: "{{ above_threshold }}"
        attributes:
          since: >
            {% if this.state=='off' and above_threshold %}
              {{ now() }}
            {% elif this.state=='on' and above_threshold %}
              {{ this.attributes.since }}
            {% else %}
              none
            {% endif %}

This will store (in an attribute named since) the datetime when the sensor changed from false to true. To get the time elapsed since that datetime, you can use a card in the frontend that accepts templates and you can use {{ now() - state_attr('binary_sensor.pool_above_61', 'since') }} plus some changes based on however you want to format the result.

The reason I don’t have the attribute calculate the elapsed time directly is because that is a waste of cpu and database space, and I’d have to add a time pattern trigger to this sensor based on however often you want the elapsed time to be updated. It’s better to perform elapsed time calculations in the front end where it’s only calculated when it’s displayed and because calculating it in the backend will result in each update (every second or every minute for example) being stored in the history database.

Edit: forgot to mention the automation trigger you’d use. Use a template trigger with this template:

{{ now() - state_attr('binary_sensor.pool_above_61', 'since')  > timedelta(days=7) }}
1 Like

This sounds really cool - I’ll give it a try.
Thanks!

Hi @mekaneck,
the sensor itself seems to work fine but I can’t get it to work to show the elapsed time since the sensor changed.

When I put the code you gave me ({{ now() - state_attr('binary_sensor.pool_above_61', 'since') }})into the template editor I get this message:
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'str'

Not really sure what to do here, but it seems like the ‘since’ attribute is stored as a string, not a datetime data type - although, in the template editor, it seems to return it in the same format:
{{ state_attr('binary_sensor.pool_above_61', 'since') }} => 2024-02-05 19:47:04.863662-08:00

I played around with changing the values with as_timestamp but that seems to get very complicated and doesn’t work with the trigger code you suggested either :frowning:

Any additional ideas?

What about a two step process… First set up a template binary sensor that is “on” when it is above your threshold, then use a History Stats sensor to monitor how many hours the binary sensor has been “on” over the past x days. Your numeric state trigger is then set to fire when the History Stats reaches y hours.

Definitely an option - I just liked the idea of not having to go with a second sensor and have it all work based on displaying the time in a card and using a trigger based on the same calculation/approach.

Sorry, yes you identified the issue and were close to the solution. But you want to convert the string to a datetime, not a timestamp, because now() is a datetime.

{{ now() - state_attr('binary_sensor.pool_above_61', 'since') | as_datetime }}

Great, thanks - appreciate the quick response.
That fixed it in the template editor, so I assume it will do the same in the dashboard card and for the trigger :+1:

Got to get back to this:
{{ now() - state_attr('binary_sensor.pool_above_61', 'since') | as_datetime }}

It seems to throw an error - at least in the template editor - as long as the binary_sensor itself is off and ‘since’ is none .

Guess I’ll have to address this somehow in this section by entering something different for none:

        attributes:
          since: >
            {% if this.state=='off' and above_threshold %}
              {{ now() }}
            {% elif this.state=='on' and above_threshold %}
              {{ this.attributes.since }}
            {% else %}
              none
            {% endif %}

Not sure what makes sense, though.

Yes the code will return none (which I believe results a sensor state of unknown) when the temp is not above 61.

The template I provided does that, but you haven’t stated what you want the sensor to show when the value has not been crossed. What I provided will result in an error in that case. What would you like the result to be instead?

The template editor will actually show none for the attribute when the temperature is not above 61F.
But it results in an error when trying to display the value for
{{ now() - state_attr('binary_sensor.pool_above_61', 'since') | as_datetime }} in the template editor while it shows nothing at all in the dashboard.

Replacing none with 0 days and playing around with various options got me to this point:

image

with the respective config in an entites card like this:

type: entities
entities:
  - entity: binary_sensor.pool_above_61
    secondary_info: last-changed
  - type: attribute
    entity: binary_sensor.pool_above_61
    attribute: since
    format: datetime
  - type: attribute
    entity: binary_sensor.pool_above_61
    attribute: since
    format: relative
  - type: attribute
    entity: binary_sensor.pool_above_61
    attribute: since
    format: total
    prefix: for
  - type: attribute
    entity: binary_sensor.pool_above_61
    attribute: since
    format: date
  - type: custom:template-entity-row
    name: Pool above 61
    state: >-
      {{ now() - state_attr('binary_sensor.pool_above_61', 'since') |
      as_datetime }}
    entity: binary_sensor.pool_above_61

I don’t think simply displaying nothing is going to work for me, so I’ll probably go for this option:

  - type: attribute
    entity: binary_sensor.pool_above_61
    attribute: since
    format: total
    prefix: for

which will display something like this:
image

Thanks again for your help, @mekaneck