SOLVED Templating states.sensor.time.state=binary_sensor time - input_datetime?

Hey!

I am trying to trigger an automation notification at a “sensor time” minus a “input_datetime” value.
The automation is ok but I cant seem to figure out how to get the time calculation to be correct with a “input_datetime” value.

My current templating is as below and this is working, but the “offset” time is in the code not taken from an input_datetime value:

{{ as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - timedelta( hours = 3, minutes = 20 ), "%H%M")) | timestamp_custom("%H:%M") }}

How can I replace

“timedelta( hours = 3, minutes = 20 ), “%H%M”)) | timestamp_custom(”%H:%M")"

with

“as_timestamp(states.input_datetime.iss_paminnare) | int | timestamp_custom(”%H:%M")"

Below does not work…
{{ as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - as_timestamp(states.input_datetime.iss_paminnare) | int | timestamp_custom("%H:%M") }}

This way I can set a time for the offset trigger from the sensor time to send a notification when ISS is above my position.

Any help would be appreciated

Add .state to states.input_datetime.iss_paminnare. That should to it.

By the way, you can use the Template Designer in the Developer Tools to evaluate.

1 Like

I do Think this is working:
{{ states.sensor.time.state == as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - timedelta( hours = state_attr("input_datetime.iss_paminnare", "hour") | int, minutes = state_attr("input_datetime.iss_paminnare", "minute") ), '%H:%M')) | timestamp_custom("%H:%M") }}

No, I don’t think it will…

What I would do is instead of using input_datetime is use an input_number and the enter the number of seconds that you want to subtract.

so instead of what you have use an input_number of 12000 (3*3600 + 20*60).

{{ (as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - states('input_number.something') | int ) | timestamp_custom("%H:%M") }}

that’s assuming that your strptime conversion works (but I’m pretty sure it won’t because you are missing the format part of the command).

if you really want to use an input_datetime then the template gets a bit more complicated:

{{ as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - ( states('input_datetime.iss_paminnare').split(':')[0] | int * 3600 + states('input_datetime.iss_paminnare').split(':')[1] | int * 60) | timestamp_custom("%H:%M") }}

I couldn’t fully test it (and I didn’t fix the strptime issue) since I don’t have those entities but I think the math is correct.

EDIT:

I cleaned it up a bit so it makes it a bit easier to read:

{% set hours = states('input_datetime.iss_paminnare').split(':')[0] %}
{% set minutes = states('input_datetime.iss_paminnare').split(':')[1] %}
{% set seconds = hours | int * 3600 + minutes | int * 60 %}
{{ as_timestamp(strptime(state_attr("binary_sensor.iss", "next_rise") - seconds | timestamp_custom("%H:%M") }}
1 Like
- alias: example ISS alert
  trigger:
  - platform: template
    value_template: >
      {% set t = state_attr('binary_sensor.iss', 'next_rise') - 
                 timedelta(seconds=state_attr('input_datetime.iss_paminnare', 'timestamp')) %}
      {{ now().hour == t.hour and now().minute == t.minute }}
  action:
  - service: persistent_notification.create
    data:
      title: ISS Alert
      message: "ISS visible in {{ states('input_datetime.iss_paminnare') }}"

I tested it on my system and confirmed it works.

The assumption I have made is that input_datetime.iss_paminnare contains time only (and not date). if that’s incorrect, let me know and I can modify the automation.

1 Like

Thank you @123! This is working great!

Thank you @m0wlheld as well. Did not yet test your code and I dont fully understand it. Really new to Python :crazy_face:

If a date is needed, what do I add?

{{ state_attr('binary_sensor.iss', 'next_rise') }}

Give value : 2021-01-23 21:07:51

This is the states in the ISS sensor.

<template TemplateState(<state input_datetime.iss_paminnare=00:22:00;
 editable=True, has_date=False, has_time=True, hour=0, minute=22, second=0, 
timestamp=1320, friendly_name=ISS Påminnare @ 2021-01-23T20:43:17.549985+01:00>)>

and in states tab
number_of_people_in_space: 7
next_rise: ‘2021-01-23T21:07:51’
long: ‘-48.3718’
lat: ‘38.2882’
friendly_name: ISS
device_class: visible

Hmmm…

I thought that the time only time input_datetime’s didn’t have a timestamp attribute. I could have sworn that I looked for those before to use somewhere else. :man_facepalming: I wonder if that’s something recently added or I completely missed it.

It seems strange to have a time only entity to have a “timestamp” tho.

It looks like that timestamp is based just on seconds since midnight of the current day for that particular time setting.

EDIT:

Maybe it was “sensor.time” that I looked at before so I assumed a time only input_datetime wouldn’t have one either.

Either way it’s good to learn something useful.

1 Like

Here’s the template from the Template Trigger:

      {% set t = state_attr('binary_sensor.iss', 'next_rise') - 
                 timedelta(seconds=state_attr('input_datetime.iss_paminnare', 'timestamp')) %}
      {{ now().hour == t.hour and now().minute == t.minute }}

To calculate the variable called t we subtract the input_datetime from next_rise. To do this, we must convert both of them into another form that allows us to easily perform time-based arithmetic.

We are fortunate because next_rise already happens to be a datetime object so all we need to do is get it with this:

state_attr('binary_sensor.iss', 'next_rise')

In contrast, the input_datetime must be converted into a timedelta object so that it is easy to do arithmetic with a datetime object.

We begin by getting the timestamp value of the input_datetime entity:

state_attr('input_datetime.iss_paminnare', 'timestamp')

The value will be in seconds. In other words, if the input_datetime was set to 01:15 (one hour and 15 minutes) then the timestamp will be 60 minutes + 15 minutes = 75 minutes = 4500 seconds.

Now that we know how to get the value in seconds, we convert it to a timedelta object like this:

timedelta(seconds=state_attr('input_datetime.iss_paminnare', 'timestamp'))

All that’s left is to subtract the timedelta object from the datetime object:

      {% set t = state_attr('binary_sensor.iss', 'next_rise') - 
                 timedelta(seconds=state_attr('input_datetime.iss_paminnare', 'timestamp')) %}

The result, t, is a datetime object. To get the hour of a datetime object you can simply do this:

t.hour

The same principle applies for getting the year, month, hour, and second.

Finally, we compare the current hour and minute to the datetime’s hour and minute. The trigger will occur when the template evaluates to true. Because now() is used in the template, the template will be evaluated (i.e. checked) every minute.

      {{ now().hour == t.hour and now().minute == t.minute }}
1 Like

Very nice explained @123! Its fun to learn😊
Thanks for the help👍

1 Like