Heads up! Upcoming breaking change in the Template integration

Yes, this is why now() is independent from the rate_limits

2 Likes

Thanks for the explanation guys.

I think I might leave sensor.time in. Only as it is easier to spot when things have gone wrong if I know they should change on the minute rather than any time within 60 seconds.

Taras, you actually assisted me with that template ages ago (or maybe it was petro?). We had to add todayā€™s date to the time only input_datetimes to be able to compare the time now to the range defined by them. A lot has changed since then though (time_delta for example). Can you see any improvements I could make?

Or are you being unpredictable today? :wink:

OK, so thereā€™s a subtle difference between sensor.time and now().

  • sensor.time is a clock, triggering every minute regardless of when other entities in the template may or may not be triggering.
  • now() is more of an insurance policy, ensuring the template gets updated at least every minute. It may skip a beat if some other entity has already triggered an update but it ensures the span between one trigger and the next is never longer than one minute.

In other words, from a distance, the two appear to work the same way, the template gets triggered no less than every minute. However, up close, sensor.time triggers on the minute (like a clock) whereas now() is only concerned with the time span between triggers not exceeding one minute.

1 Like

Ok, a slightly different tack on this.

I have followed this thread form the start and have remained pragmatic about what is going on butā€¦

This is happening at a period in my real life where I just canā€™t devote as much time as I did (and want to) to HA. I am up to date with version 116 installed, but have real concerns I am about to be left so far behind with 117 that I will find it very hard to catch up when I am back ā€˜full-timeā€™ on HA.

I do hope this is all going to be well documented because due to severe time constraints I have unfortunately lost the plot a little bit here. I have a fairly big and in part complex setup to keep current (some of which has been shared with a small but significant number of other users).

haha, youā€™ve grown a nice sense of humor :wink: cool.

Honestly, why would anyone want to update more than the actual state changes of the entities give reason to? I can understand ā€˜lessā€™ very much so. Limit updates can be very useful.
But more? If now() takes care of the minute (aside from where in the minute), why would you want to add sensor.time at all? Only to have it update at the top of the minute exactly?

I would think exactly that an unnecessary update to preventā€¦

I gave a reason for wanting it on the minute:

e.g. ā€œHey the heating hasnā€™t turnd on and itā€™s xx oā€™clock. Guess Iā€™ll have to wait up to a minute and see if there is a problemā€.

now() is not exactly on the minute, and itā€™s based on startup/last sensor update. Also, itā€™s 60.35 seconds, not 60. Which means there will be 8 minutes throughout the day where no update occurs on said minute. I.E. 1 minute every 3 hours will be lost. So itā€™s best to use 'sensor.time'. This of course is only if you use now() and no other entity in your template.

Just out of curiosity, why wasnā€™t now() handled like sensor.time and allowed to trigger every minute, on the minute?

There are countless posts in this form where new users have employed now() exclusively in their templates because thereā€™s a reasonable assumption that itā€™s a ā€˜clock-likeā€™ resource. They assume its presence will ensure the template is evaluated periodically. However, as we all know, thatā€™s an incorrect assumption because now() is not an entity so it isnā€™t assigned a listener (ever).

It would be wonderful if now() behaved exactly like the vast majority of new users assume it behaves: it causes the template to be evaluated every minute, on the minute. This would eliminate the age-old practice of including sensor.time for establishing a ā€˜heartbeatā€™.

There was a reason but I canā€™t remember. It was to essentially avoid double updates at the exact same time.

Honestly, it was mostly because this thread had scared me from implementing additional redundant updates. Also, using the delayed update avoids all sensors updating at the same time so it spreads out the load a bit. That is probably insignificant though.

I guess we still have time to change it if there are some good reasons (full YAML templates are good to make a point).

I think the best reason is the one I mentioned earlier: it would behave the way most new users assumes it behaves (every minute, on the minute).

Itā€™s a common complaint: they test their template (containing now()) in the Template Editor then discover it fails to work (fails to update) when used in a Template Sensor.

We can use tom_Iā€™s example from this his post (above):

      value_template: >-
        {% set update = states('sensor.time') %}
        {% set d = now().strftime("%Y-%m-%d ") %}
        {% set t = now().timestamp() %}
        {% set pm_start = strptime(d + states('input_datetime.sp_bedrm_pm_on_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
        {% set pm_end = strptime(d + states('input_datetime.sp_bedrm_pm_off_time'), '%Y-%m-%d %H:%M:%S').timestamp() %}
        {{ pm_start <= t <= pm_end }}

The main goal of this template is to check if the current time is within a desired range. There are two entities but they are input_datetimes, used to set the time-range, and change state so infrequently that they can be ignored as a source of triggering for this template.

Itā€™s the inclusion of sensor.time that ensures a per minute, on the minute ā€˜heartbeatā€™ to check if the current time is within the range. However, most of the actual time calculations use, out of sheer convenience, the now() function. Ideally, we could dispense with including sensor.time and have now() provide the per minute, on the minute ā€˜heartbeatā€™.

There will be an option for legacy_template in 0.117, which will be removed later. See at the end of the breaking changes in the beta release notes here.

1 Like

6 posts were split to a new topic: Does anyone know how to change this template for the upcoming changes in 0.117

Sorry I had just made a new topic myselfā€¦

I read the preliminary release note and I have a question about that specific option.

In 0.117, templates will support types. That means the output of a template is no longer constrained to be a string but can be float, int, list, etc. This new behavior might cause problems for some applications so one can set the legacy_templates option to true in order to preserve the old behavior.

After explaining that, the note proceeds to say that sensor.DOMAIN is now rate-limited to per-second as opposed to per-minute (as it was in 0.116). Does the legacy_templates option influence this modification as well? That appears to be your interpretation of the note. However, the fact that it is mentioned after describing legacy_templates makes me believe it isnā€™t included.

Maybe amelchio can clarify this particular point.

Ah, yeah, you are probably right.

On a sidenote:
Iā€™m on the latest 0.117 beta and have no problems so far with the changes. The python types are quite nice :smiley: and the adaptive lighting integration is amazing!

1 Like

That option only affects the new types. The release notes have breaking changes from two PRs concatenated with no visual separation.

2 Likes

legacy_templates:

1 Like

if I might add:
Another good reason would be to avoid confusion the implementation of sensor.time next to now() causes, as this thread section now proofsā€¦ also, the way Petro explained, about losing 8 minutes per day on using only now() is so theoretical, I cant imagine the core team to prioritize that above the ā€˜easeā€™ of having now() simply update on the minute (and thus void the need to use the extra line with sensor.time)

I do realize now() is supposed to be what it is, now. And it will be. But failing another entity to update, it would be very well accepted to have it update on the minute.

better post the link, cause Petro;s link seems to be incorrect: