Heads up! Upcoming breaking change in the Template integration

Not sure if this is the right thread to post this in. I have an automation to update template sensors that only have the now() function. They would update every hour or so, depending on what I needed. Now I understand they will update every minute due to the now() function, so the automation is obsolete.

The sensor template looks like this (this one adjusts the thermostat in the morning to something more comfortable before we actually get up for coffee):

    prep_hvac_for_wakeup:
      friendly_name: Prep HVAC for wakeup
      value_template: >
        {% set delta_between_now_and_midnight = now().timestamp() - now().replace(hour=0).replace(minute=0).replace(second=0).timestamp() %}
        {% set target_start_timestamp = state_attr('input_datetime.morning_wakeup_workday_start','timestamp') - state_attr('input_datetime.pre_condition_morning_hvac','timestamp') %}
        {% set target_end_timestamp = state_attr('input_datetime.morning_wakeup_workday_start','timestamp') %}
        {{ ((delta_between_now_and_midnight >= target_start_timestamp and delta_between_now_and_midnight < target_end_timestamp)) }}

It checks to see if the current time (now()) is within the times specified by the input_datetime values. If it is, then the {{logic above}} returns true

I have similar sensors to trigger various time frames throughout the day (morning, late_morning, afternoon, etc) to adjust thermostats and other things.

Is there a better way to do this so itā€™s not updating every minute because of now()? Orā€¦ maybe updating a few sensors every minute when they donā€™t need to is not a big deal on the olā€™ CPU.

Thoughts?

And the discussion in this thread is very interesting and helpful!! Thanks, @123 and @petro and @frenck for the helpful discussion!! I hadnā€™t updated since maybe 0.114, and it didnā€™t take long at all the hunt down and eliminate the entity_id statements in my templates.

No (and the workaround is impractical).

When you paste that into the Template Editor, it will report what it listens to for changes. The presence of the now() function ensure the template will be evaluated at least once a minute.

The only way around it would be to replace all instances of now() with some other time-based sensor that only change state every hour. However, that makes the entire template have a coarse resolution (hourly) and that negatively affects your time calculations.

Thanks, @123, for the answer. Kind of what I thought. I do appreciate having the now() function update the sensor/binary_sensor. I donā€™t know how many times I fell into that trap of creating a sensor with now() and then not having it update as I intended. Again, thanks for the effort on this!

1 Like

Right. Donā€™t worry about it.

1 Like

Jedi Mind Trick:

ā€œThese arenā€™t the extra CPU cycles youā€™re looking for ā€¦ā€

1 Like

@amelchio and @123 - you guys are a hoot - Iā€™m not worrying about anymore!! Thanks, again, for the advice and help.

I donā€™t know if this has been covered here or somewhere else (and if it has and/or there is a better way to do it) and if so my apologies butā€¦

I had been struggling to find a way to have a template update on the second aside from needing to rely on the states.DOMAIN listener.

I finally worked out a way to do it. Itā€™s kind of ā€˜hackyā€™ but I believe that this is exactly the way the devs now expect us to do this sort of thing.

you need two things to make it work:

counter:
  one_second_update:
    initial: 0
    step: 1
 
automation:
  - alias: one second update
    trigger:
      platform: time_pattern
      seconds: '/1'
    action:
      - choose:
          - conditions:
              - condition: template
                value_template: "{{ now().second == 0 }}"
            sequence:
              - service: counter.reset
                entity_id: counter.one_second_update
        default:
          service: counter.increment
          data:
            entity_id: counter.one_second_update

This creates a continuously running counter that mimics simulates a one second resolution clock. Once it gets to 59 ā€œsecondsā€ it resets back to 0 like a regular clock would.

The reason why I stress ā€œmimicā€ is that the counter wonā€™t match the seconds of time in the real world.

You can use the state of the counter to force a one second update interval in any template in the same manner as using sensor.time used to do for one minute update intervals.

as an example for its use:

trigger:
    - platform: template
      value_template: >
        {% set update = states('counter.update') %}
        {{ (state_attr('input_datetime.both_date_and_time', 'timestamp') - now().timestamp()) <= 0 }}

Which would work great if the bug found by @123 (and posted to github by him almost 2 weeks ago (link) would be fixed to actually allow using now() in a trigger and have it work.

But you can still use it in template sensors or in dev-tools to test templates with one second update resolution.

EDIT: I updated the automation to reset the counter to 0 at the start of every minute so the counter should always be within 1 second of the actual real world seconds. The only time this wonā€™t be true is after a HA restart (or eventually when we get a counter reload service) until the counter and now().seconds synchronize which will happen in less than a minute after HA restarts or counters get reloaded.

Itā€™s just cleaner that way.

Maybe I am missing your point, but why donā€™t you use the service homeassistant.update_entity in the automation, for the sensors you want to update each second ?

Itā€™s not about updating sensors by using an automation. Of course if there were only a few sensors you wanted to update every second and thatā€™s all you wanted a one second resolution update interval for then I would agree.

But remember you need to first build the sensor and then create an automation to cause the one second update for the sensor.

using this update counter you can use it directly in the sensor template just like we used to need to do when we used sensor.time to update every minute. Then there is no further update automation required. You just have one automation and one counter updating every second in the background.

And it also allows you to use it in automations to compare now() to a date_time down to the second where right now it only works down to the minute without it (as in my example above).

Or it allows you to use it in dev-tools to auto refresh the page every second to test templates at one second resolution.

My point is that there are more than one use for this function aside from just updating sensors and it makes that sensor update functionality easier to do.

AT least, IMO.

What do you do that requires second resolution?

I was just helping someone yesterday with a blueprint that flashed lights at the completion of an echo timer. I tried to use now() to trigger the automation (then found that I got bit by that referenced bug) but then tried to make the condition for the timestamp of the entity state to be <= now(). But I found that the actions could be up to a minute delayed from the actual timer expiring because now() only updates at most every minute.

A one second update resolution would have made it less complicated to do the time calculations and run the actions at the correct time.

Iā€™ve run into this with other things but just accepted the one minute update and moved on because most of the time itā€™s no big deal.

The experience in the other thread made me realize there are times it would be helpful to have that functionality so I made it available if I needed it.

I canā€™t see the downside to having a one second ā€œheartbeatā€ counter available. :slightly_smiling_face:

Ah, got a link to that blueprint?

1 Like

maybe create a template sensor:

second_updater:
  value_template: >
    {{(now() - states.sensor.time.last_changed).total_seconds()|int}}

and use your automation to update that each second:

automation:
  - alias: Second updater
    trigger:
      platform: time_pattern
      seconds: '/1'
    action:
      service: homeassistant.update_entity
      entity_id: sensor.second_updater

with should be usable now for all your demands?

must confess I dont know what the impact on the system would be though.

Iā€™m not sure what you are meaning.

I have already created the functionality I need as I posted above and itā€™s working fine. it mimics a second hand (or the digital equivalent) so you can match the time down the second if needed.

Iā€™m not sure your solution does that.

sorry, but I thought this is what you needed, and the template sensor seems much easier than the timer setup:

seconds

one can use this sensor as trigger in all other configs.

1 Like

It looks like it offers the same functionality. If I had seen yours first I might have actually used it instead :slightly_smiling_face:

But with the last change to the code above for mine it seems to be matching the second exactly the majority of the time (if that is important) but yours seems to be a second off from the real seconds (if that is important :wink:) so Iā€™ll stick with mine for now.

Thanks for posting that tho. Itā€™s always good to have alternatives.

Ha, hadnā€™t even noticed that, and yes that seems logical.
Cool.
of course, I should have simply used

{{now().strftime('%-S')}}

for the template sensor. what was I thinkingā€¦
and fyi, this follows the true seconds of the machine, no lag at all.

1 Like

I think Iā€™ll actually use yours instead now.

It is more simple.

Thanks!

Home Assistant 2021.4 will include trigger-based template sensors. These will disable the template update mechanism discussed here and instead update when a trigger matches. With this, I think some more use cases from this thread are covered; for example to only update at midnight and to never update. It should even be possible to make a trigger that matches state change events for specified entities.

As this is currently in beta, now would be a good time to point out if you see issues with it.

3 Likes