Heads up! Upcoming breaking change in the Template integration

If the entity_id is no longer defined, how would you know it would still be vacuum.robotrockā€¦? This confuses me a little, since it was referencing the state of the entity_id, which is now not set manually. Maybe someone can explain this for me? I admit Iā€™m not too familiar with template sensors within hass. Thanks.

Thereā€™s a clever function that scans the template for entity ids to monitor. This was the case before too. Itā€™s just that it is much better at it now. So thereā€™s no need to explicitly list them now.

As Tom says: thereā€™s : -

And in this case fabio had : -

In his template so that didnā€™t need the entity_id anyway.

Itā€™s going to be an interesting transition, you could rely on the backward compatibility but to gain the performance advantages bdraco is offeringā€¦
:wink:

1 Like

I have seen in the documentation PR by @bdraco this trick used.

{{ states('sensor.time') and now() }}

states('entity_id') when provided with any entity_id valid or not returns as true so only the expression to the right of the and statement does anything useful. The entity_id in states() is only there for the parser.

sensor.date_time_iso comes pretty close to a python datetime string. Will all date functions work with it?

Doh! :man_facepalming:

Right in front of my nose yet Iā€™ve never seen it!

{% set t = states.sensor.time.last_updated %}

Timestamp: {{ t.timestamp() }}
Date: {{ t.date() }}
CTime: {{ t.ctime() }}
Year: {{ t.year }}
Month: {{ t.month }}
Day: {{ t.day }}
Hour: {{ t.hour }}
Minute: {{ t.minute }}
Second: {{ t.second }}

Yup, states.sensor.time.last_updated has everything needed to do date arithmetic and can easily replace the use of now() in a template.


EDIT

Oops! Thereā€™s a difference: last_updated reports UTC time whereas now() reports local time.

1 Like

Also have to be careful with that timestamp. It has microsecond resolution but the last changed attribute only updates every minute.

1 Like

True, but an int can remedy that whereas converting UTC to local time is messy.
Misunderstood your point about the microseconds.

All this to say that states.sensor.time.lastupdated is more like using utcnow() than now(). The user needs to keep that in mind if they intend to use it in their date calculations.

And as long as they realise itā€™s got a one minute resolution, no good for 30 second comparisons for example.

1 Like

I think the takeaway is that states.sensor.time.last_updated can be useful but should be used judiciously because it isnā€™t the equivalent of either now() or utcnow(). As you mentioned, itā€™s sensor.time after all so it only has 1-minute resolution and last_updated is UTC-based.

Thatā€™s also good advice for existing Template Sensors that use this:

    entity_id: sensor.time

and then proceed to use now() to perform time arithmetic that look for sub 1 minute differences. The darn thing is only going to be evaluated every minute so looking for, as you mentioned, a 30-second difference would be a mistake. Youā€™re obliged to look for differences in whole minutes.

Hopefully, very few people have made that mistake.

1 Like

I counted up my template sensors and binary template sensors. 19 uses of sensor.time and 5 uses of sensor.date.

Not too onerous a change.

In fact I think I could replace the majority of them with the custom scheduler card and significantly less input booleans. Might have to have a bit of an experiment with it at some stage.

Would you mind sharing a link?

Sure, be aware it is still very much in development though:

Do we have a good way to convert last_updated to local time? We could expose as_local to jinja if there isnā€™t:

1 Like

Iā€™m with Bartemā€¦ This is getting pretty hard to follow.
But it is concerning me.

I have (quite a few) templates like this.

      irrigation_cycle1_duration_in_seconds:
        friendly_name: Cycle 1 Duration In Seconds
        entity_id:
          - input_number.irrigation_number_of_zones
          - sensor.irrigation_cycle1_zone1_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone2_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone3_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone4_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone5_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone6_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone7_actual_duration_in_seconds
          - sensor.irrigation_cycle1_zone8_actual_duration_in_seconds
        value_template: >
          {% set ns = namespace(duration = 0) %}
          {% for zone in states.sensor if zone.object_id.startswith('irrigation_cycle1_zone') and 
                                          zone.object_id.endswith('_actual_duration_in_seconds') %}
            {% if loop.index <= states('input_number.irrigation_number_of_zones') | int %}
              {% set ns.duration = ns.duration + (zone.state | int) %}
            {% endif %}
          {% endfor %}
          {{ ns.duration }}

Unless I am mistaken (quite possible of course) this wonā€™t work?

I think you just wipe out all the entity_id section. Done.

Yeah but how will it know what to watch as the entity names are not explicitly stated, only what they startwith and endwith?

But if that works then fantastic!

1 Like

This is exactly what Iā€™m confused about (even sober!). The answer appears to be to shoehorn the entity_id into the template, but I canā€™t see how thatā€™s better than the current approach, and would actually go so far as to say that itā€™s a lot less user friendly :man_shrugging:

It will work. (Oh if it doesnā€™t you can add a dummy time templateā€¦ that has been discussed above) However from what I have read it will parse the template and know what to doā€¦

Worse case is that you move the sensors in the template. When I get on a pc I can rejigger it for ya.

1 Like