From ab655f54801e7f03c43bc60085edab04e99ffb47 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Sep 2020 13:27:51 -0500 Subject: [PATCH 1/8] Add explanation of the `rate_limit` directive. --- .../_integrations/binary_sensor.template.markdown | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index 9635fc1af129..b7c7781eab00 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -294,6 +294,19 @@ binary_sensor: {% endraw %} +### Rate limiting updates + +When there are entities present in the template, the template will be re-rendered when one of the entities changes states. + +When `states` is used in a template by itself to iterate all states on the system, the template is re-rendered each +time any state changed event happens if any part of the state is accessed. When merely counting states, the template +is only re-rendered when a state is added or removed from the system. On busy systems with many entities or hundreds of +thousands state changed events per day, templates may re-render more than desirable. + +A `rate_limit` directive can be used to limit how often the template re-renders. + + + ### Working without entities The `template` sensors are not limited to use attributes from other entities but can also work with [Home Assistant's template extensions](/docs/configuration/templating/#home-assistant-template-extensions). If the template includes some non-deterministic property such as time in its calculation, the result will not continually update, but will only update when some entity referenced by the template updates. From d19dad67601187e121c04698ff75998b6bce2675 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Sep 2020 13:41:33 -0500 Subject: [PATCH 2/8] Update binary_sensor.template.markdown --- source/_integrations/binary_sensor.template.markdown | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index b7c7781eab00..ce330ada5640 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -305,7 +305,19 @@ thousands state changed events per day, templates may re-render more than desira A `rate_limit` directive can be used to limit how often the template re-renders. +`rate_limit` accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. +In the below example, re-renders are limited to once per minute: + +{% raw %} +```yaml +binary_sensor: + - platform: template + sensors: + has_unavailable_states: + value_template: '{% set delta = rate_limit(minutes=1) %}{{ states | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}' +``` +{% endraw %} ### Working without entities From 76124f9293fedb1d83b7ae305df882a76d0d7f86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Sep 2020 13:44:21 -0500 Subject: [PATCH 3/8] update templating as well --- source/_docs/configuration/templating.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_docs/configuration/templating.markdown b/source/_docs/configuration/templating.markdown index dce917e3bc72..01ad45b6c2cd 100644 --- a/source/_docs/configuration/templating.markdown +++ b/source/_docs/configuration/templating.markdown @@ -58,7 +58,7 @@ Extensions allow templates to access all of the Home Assistant specific states a - `is_state('device_tracker.paulus', 'home')` will test if the given entity is the specified state. - `state_attr('device_tracker.paulus', 'battery')` will return the value of the attribute or None if it doesn't exist. - `is_state_attr('device_tracker.paulus', 'battery', 40)` will test if the given entity attribute is the specified state (in this case, a numeric value). Note that the attribute can be `None` and you want to check if it is `None`, you need to use `state_attr('sensor.my_sensor', 'attr') == None`. - +- `rate_limit` - limits re-renders of the template. Returns a timedelta object and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks.
Avoid using `states.sensor.temperature.state`, instead use `states('sensor.temperature')`. It is strongly advised to use the `states()`, `is_state()`, `state_attr()` and `is_state_attr()` as much as possible, to avoid errors and error message when the entity isn't ready yet (e.g., during Home Assistant startup). From cf0a59f9ee3790e18e480895ea3f50e895f8e73c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Sep 2020 13:45:06 -0500 Subject: [PATCH 4/8] Update binary_sensor.template.markdown --- source/_integrations/binary_sensor.template.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index ce330ada5640..657ac63abbee 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -305,7 +305,7 @@ thousands state changed events per day, templates may re-render more than desira A `rate_limit` directive can be used to limit how often the template re-renders. -`rate_limit` accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. +`rate_limit` returns a `timedelta` object and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. In the below example, re-renders are limited to once per minute: From c981fc8930d591a0cd2de789be878d2127a359e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 27 Sep 2020 16:13:37 -0500 Subject: [PATCH 5/8] Update binary_sensor.template.markdown --- source/_integrations/binary_sensor.template.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index 657ac63abbee..b6806eebaa34 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -315,7 +315,7 @@ binary_sensor: - platform: template sensors: has_unavailable_states: - value_template: '{% set delta = rate_limit(minutes=1) %}{{ states | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}' + value_template: '{% rate_limit(minutes=1) and states | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}' ``` {% endraw %} From d2d97a535ad6878b3f42562ee7937a6e5156c004 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 1 Oct 2020 08:23:58 -0500 Subject: [PATCH 6/8] Update templating.markdown --- source/_docs/configuration/templating.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_docs/configuration/templating.markdown b/source/_docs/configuration/templating.markdown index 01ad45b6c2cd..832132b5109c 100644 --- a/source/_docs/configuration/templating.markdown +++ b/source/_docs/configuration/templating.markdown @@ -58,7 +58,7 @@ Extensions allow templates to access all of the Home Assistant specific states a - `is_state('device_tracker.paulus', 'home')` will test if the given entity is the specified state. - `state_attr('device_tracker.paulus', 'battery')` will return the value of the attribute or None if it doesn't exist. - `is_state_attr('device_tracker.paulus', 'battery', 40)` will test if the given entity attribute is the specified state (in this case, a numeric value). Note that the attribute can be `None` and you want to check if it is `None`, you need to use `state_attr('sensor.my_sensor', 'attr') == None`. -- `rate_limit` - limits re-renders of the template. Returns a timedelta object and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. +- `rate_limit` - limits re-renders of the template. Returns an empty string and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks.
Avoid using `states.sensor.temperature.state`, instead use `states('sensor.temperature')`. It is strongly advised to use the `states()`, `is_state()`, `state_attr()` and `is_state_attr()` as much as possible, to avoid errors and error message when the entity isn't ready yet (e.g., during Home Assistant startup). From 07dd8aafef36f594ca8965ce0fdc494b3cd6c6fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 1 Oct 2020 08:24:26 -0500 Subject: [PATCH 7/8] Update binary_sensor.template.markdown --- source/_integrations/binary_sensor.template.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index b6806eebaa34..7299134401ca 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -305,7 +305,7 @@ thousands state changed events per day, templates may re-render more than desira A `rate_limit` directive can be used to limit how often the template re-renders. -`rate_limit` returns a `timedelta` object and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. +`rate_limit` returns an empty string and accepts the same arguments as the Python `datetime.timedelta` function -- days, seconds, microseconds, milliseconds, minutes, hours, weeks. In the below example, re-renders are limited to once per minute: From e35a5dd497e7cc39a4ab51348846db5e2e201120 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 1 Oct 2020 08:24:54 -0500 Subject: [PATCH 8/8] Update binary_sensor.template.markdown --- source/_integrations/binary_sensor.template.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/_integrations/binary_sensor.template.markdown b/source/_integrations/binary_sensor.template.markdown index 7299134401ca..a01f176eb327 100644 --- a/source/_integrations/binary_sensor.template.markdown +++ b/source/_integrations/binary_sensor.template.markdown @@ -315,7 +315,7 @@ binary_sensor: - platform: template sensors: has_unavailable_states: - value_template: '{% rate_limit(minutes=1) and states | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}' + value_template: '{{ rate_limit(minutes=1) }}{% states | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}' ``` {% endraw %}