Please, can you go back to my original response and reread it? I already explained everything you need to do in the first post. End your macro with a join, and split the macros result.
yes, thanks Petro and 123, sometimes one has to go over things oneself to truly grasp.
for the sake of completeness/reference:
wat is your opinion on this final template sensor using the macro in the custom_templates, compared to the version with the this variable, from an efficiency perspective?
I started this whole migration with that in mind after all…
- unique_id: critical_switches_offline
state: >
{% from 'alerts.jinja' import critical_off %}
{{critical_off().split(',')|count}}
name: >
{% from 'alerts.jinja' import critical_off %}
{% set count = critical_off().split(',')|count %}
{% set phrase = 'switch' if count == 1 else 'switches' %}
{{count}} Critical {{phrase}} offline
icon: >
{% from 'alerts.jinja' import critical_off %}
{% set count = critical_off().split(',')|count %}
mdi:numeric-{{count}}-box
attributes:
message: >-
{% from 'alerts.jinja' import critical_off %}
{% set critical = critical_off().split(',') %}
{% set count = critical_off().split(',')|count %}
{%- if count == 0 -%} Ok, all critical switches are online
{%- elif count == 1 -%}{{count}} Critical switch offline: {{critical[0]}}
{%- elif count == 2 -%}
{{count}} Critical switches offline: {{critical[0]}} and {{critical[1]}}
{% else %}
{{count}} Critical switches are offline: {{critical[:-1]|join(', ')}}, and {{critical[-1]}}
{% endif %}
cant it handle an empty list?, and the split there causing the empty list to be [''] which returns 1 when |count that. Note there is NO switch listed after the 1 Critical switch offline: (and that is actually correct)
It seems to be due to the way the split method works If given an empty string and a delimiter, it returns a list with one item containing the empty string.
The first line of this template sets the variable to an empty list if the macro reports an empty string.
{% set alerts = alerts_macro().split(', ') if alerts_macro() != '' else [] %}
{% set count = alerts|count %}
{%- if count == 0 -%} Ok, geen alerts, alles is in orde
{%- else -%}
{{count}} Alert{{iif(count > 1, 's','')}}: {{' en '.join(alerts_macro().rsplit(', ', 1))}}
{%- endif %}
thanks Taras, and yes, that is what is happening, I had been ‘hacking’ this fix, but felt insecure.
It seems to be just that, a hack, and figured I was doing things fundamentally incorrect using/needing that to solve the split method anomaly.
thing is, I now need yet another template evalution in that config. It is becoming increasingly complex using the import method, which started out hoping it would be the easy and efficient way…
I could ofc make it a bit simpler by simply setting a name, and not use the name template (which also uses the count) but really that is besides the issue I am facing here.
just compare these and see the difference, considering the import template still requires the additional custom_template yaml, while the this variant suffices as is. (didn’t yet test whether it updates as trigger template yet, could be another challenge in itself…)
- unique_id: alerts_notifying
state: >
{% from 'alerts.jinja' import alerts %}
{% set alerts = alerts().split(',') if alerts() != '' else [] %}
{% set count = alerts|count %}
{{count}}
name: >
{% from 'alerts.jinja' import alerts %}
{% set alerts = alerts().split(',') if alerts() != '' else [] %}
{% set count = alerts|count %}
{% set phrase = 'Alert' if count == 1 else 'Alerts' %}
{{count}} {{phrase}} actief
icon: >
{% from 'alerts.jinja' import alerts %}
{% set alerts = alerts().split(',') if alerts() != '' else [] %}
{% set count = alerts|count %}
mdi:numeric-{{count}}-box
attributes:
message: >-
{% from 'alerts.jinja' import alerts %}
{% set alerts = alerts().split(',') if alerts() != '' else [] %}
{% set count = alerts|count %}
{%- if count == 0 -%} Ok, geen alerts, alles is in orde
{%- elif count == 1 -%}{{count}} Alert voor: {{alerts[0]}}
{%- elif count == 2 -%}
{{count}} Alerts voor: {{alerts[0]}} en {{alerts[1]}}
{%- else -%}
{{count}} Alerts voor: {{alerts[:-1]|join(', ')}}, en {{alerts[-1]}}
{%- endif %}
- unique_id: alerts_notifying_this
state: >
{{this.attributes.alerts|count}}
name: >
{% set count = this.state|int(default=-1) %}
{% set phrase = 'Alert' if count == 1 else 'Alerts' %}
{{count}} {{phrase}} actief
icon: >
{% set count = this.state|int(default=-1) %}
mdi:numeric-{{count}}-box
attributes:
alerts: >
{{ expand(state_attr('binary_sensor.alerts','entity_id'))
|selectattr('state','eq','on')|map(attribute='name')|list }}
message: >-
{% set alerts = this.attributes.get('alerts') %}
{% set count = alerts|count %}
{/ {% set count = this.state|int(default=-1) %} /}
{%- if count == 0 -%} Ok, geen alerts, alles is in orde
{%- elif count == 1 -%}{{count}} Alert voor: {{alerts[0]}}
{%- elif count == 2 -%}
{{count}} Alerts voor: {{alerts[0]}} en {{alerts[1]}}
{%- else -%}
{{count}} Alerts voor:{{alerts[:-1]|join(', ')}}, en {{alerts[-1]}}
{%- endif %}
In your second example, your templates use this to reference property values that exist in related attributes. For example, the state template references the value of the alerts attribute. Be advised of the following:
this references the entity’s existing property values (i.e. the previously computed values).
The values of state and all attributes are computed sequentially (not concurrently). In other words, some get new values before others do.
That’s correct. But marius is referring to this.state's use inside attribute templates. Which will be the current state because of the resolution order. I’m not sure where he’s getting “sometimes”. It’s pretty straight forward. this.state inside state or availability will always be the last state. this.state inside attributes will always be the current state.
Would you happen to know if (individual) attributes are evaluated in the order presented in the entity’s configuration or in some other order (sorted perhaps)?