NOTE 2: Guidance for 0.116 and upcoming changes in 0.117
0.116 introduced improvements to mitigate performance problems reported by some users of 0.115 for templates containing states
and states.DOMAIN
. There are now built-in rate-limits that prevent excessive processing.
-
If your template refers to
states
, any entity in your entire system that changes state will cause the template to be evaluated (updated). 0.116 ensures evaluations cannot happen more than once a minute. In 0.117 the rate-limit forstates
will increase to once a second. -
If your template refers to
states.DOMAIN
, any entity within DOMAIN that changes state will cause the template to be evaluated. 0.116 ensures evaluations cannot happen more than once a minute.
A significant improvement will be introduced in 0.117. In all previous versions, if a template contains the now()
function, it doesnāt serve to periodically evaluate the template. In other words, a template with now()
and no other entities, is evaluated once at startup and never again (until the next restart).
In 0.117, the now()
function is promoted to being a first-class citizen and will cause the template to be evaluated once a minute. If your template currently uses a combination of now()
and sensor.time
, you will be able to safely remove the reference to sensor.time
(and the template will continue to function nominally).
In other words, this particular bit of documentation will no longer be true (and is likely to be removed):
Templates without entities using now()
Note that templates that depend on time (
now()
) and do not use any entities will not be updated as it only happens on entity state changes. For more information and examples refer totemplate
sensor documentation
NOTE 1: Revised with actual examples tested in 0.115.
There are many upcoming improvements to the Template integration (likely to be explained in a future releaseās blog post). The improvements will help to simplify the templates you currently use in Template Sensors, Template Binary Sensors, etc. However, there is a breaking change that may complicate a few things.
Letās say you have a Template Sensor with no identifiable entities. Hereās one that determines if the current week number is odd or even.
current_week:
entity_id: sensor.date
value_template: "{{ 'EVEN' if now().isocalendar()[1] % 2 == 0 else 'ODD'}}"
The value_template
contains no entities so Home Assistant cannot assign a ālistenerā to anything in the template. That means the template will never be evaluated after startup. To fix this, we add an identifiable entity in entity_id
like this:
entity_id: sensor.date
On startup, Home Assistant identifies sensor.date
and assigns a listener to it. Whenever sensor.date
changes state, which is at the start of every new day, the value_template
will be evaluated. Perfect; it now works like we want (template is evaluated once a day, at the start of the day).
The breaking change is that you will no longer be able to use entity_id
(EDIT: 0.115 ignores it and reports a warning message). That means we can only do this:
current_week:
value_template: "{{ 'EVEN' if now().isocalendar()[1] % 2 == 0 else 'ODD'}}"
However, we know that wonāt get a listener and will not be evaluated on any periodic basis. How do we fix this?
The suggested workaround is to create an automation with a Time Trigger (or Time Pattern Trigger) that calls homeassistant.update_entity
for the Template Sensor.
- alias: 'Update current_week sensor'
trigger
platform: time
at: '00:00:01'
action:
service: homeassistant.update_entity
entity_id: sensor.current_week
That will work but itās not nearly as convenient as the old way where you simply added entity_id: sensor.date
to the Template Sensor. In defense of this workaround, if you have many Template Sensors of this kind, that must be refreshed once a day, the same automation can be used for that purpose (i.e. you donāt need a separate automation for each sensor).
To avoid using an automation, it seems all one has to do is incorporate sensor.date
into value_template
. It will be identified by Home Assistant and assigned a listener. The trick is how do you include sensor.date
into the template when it isnāt really needed to perform any calculations?
Hereās a simple way to do that:
current_week:
value_template: >
{% set x = states('sensor.date') %}
{{ 'EVEN' if now().isocalendar()[1] % 2 == 0 else 'ODD'}}
Home Assistant can easily identify sensor.date
within the template.
To prove this to yourself (using any version of Home Assistant) you can create this Template Sensor:
test:
value_template: >
{% set x = states('sensor.time') %}
{{ now().timestamp() | timestamp_local }}
It will be refreshed once a minute.
Here is another way to incorporate sensor.time
into your template. Instead of using now()
to get the current time, it uses last_updated
from sensor.time
.
test:
value_template: >
{{ as_local(states.sensor.time.last_updated).timestamp() | timestamp_local }}
However, there is one caveat and thatās last_updated
is UTC time, not local time whereas the now()
function reports local time. Therefore we use a new function introduced in 0.115 called as_local()
. It converts a datetime object from UTC to local time.
EDIT
The original suggested technique was needlessly longer. All examples shown above have been replaced with petroās suggested technique which is more compact: simply insert a line like {% set x = states('sensor.date') %}
into your template.