Why won't this template update in jinja (and work just fine in customize JS)

using a few template sensors like this:

      critical_devices_offline:
        friendly_name: Critical devices offline
        entity_id:
          - sensor.cv_garage_state
          - sensor.cv_stookhok_state
          - sensor.cv_zolder_state
          - sensor.zonneboiler_zolder_state
          - sensor.freezer_bijkeuken_state
        value_template: >
          {% set offline = expand('group.critical_devices_state')
           |selectattr('state','eq','off')|list|count %}{{offline}}
        attribute_templates:
          message: >-
            {% set count = states('sensor.critical_devices_offline') %}
            {% set offline = expand('group.critical_devices_state') |
               selectattr('state','eq','off')|map(attribute='name')|list -%}
            {%- if offline|length == 0 -%} Ok, all critical devices are online
            {%- elif offline|length == 1 -%}{{count}} Critical device offline: {{offline[0]}}
            {%- elif offline|length == 2 -%}
              {{count}} Critical devices offline: {{offline[0]}} and {{offline[1]}}
            {%- else -%}
              {{count}} Critical devices are offline:{{offline[:-1]|join(', ')}}, and {{offline[-1]}}
            {%- endif -%}
        icon_template: >
          mdi:numeric-{{states('sensor.critical_devices_offline')}}-box

All is fine, except for the icon which won’t update, and, after one of the triggering entity_id’s changes state, is one state behind…

moving the icon template to the customize section makes the magic happen, and from startup all sensors are showing perfectly.

Ive also tried the template without the expand, and naming all entity_ids verbosely, but that doesn’t make a difference.

this is the custom-ui bit for the sensor:

homeassistant:
  customize:
    sensor.critical_devices_offline:
      templates:
        icon_color: >
          if (state !== '0') return 'red';
          return 'green';
        icon: >
          return 'mdi:numeric-' + state + '-box';

I realize the customize section is evaluated in browser, so maybe after the backend has changed state, and thus is just that bit later, and with the correct new state to calculate the customization.

Still, adding all entity_ids in the sensor itself should take care of the updating shouldn’t it?

maybe you can see/suggest what could be I improved?
thanks

don’t reference itself. change your tmplate to

        icon_template: >
          {% set offline = expand('group.critical_devices_state')
           |selectattr('state','eq','off')|list|count %}
          mdi:numeric-{{offline}}-box

thanks @petro. feared that would be the culprit in this case (do that in many other templates without issue at all).

Ended up using this now, which makes me wonder if I wouldn’t be better off creating an extra template sensor for count only, and reference that in the bigger template sensor:

      critical_devices_offline:
        friendly_name: Critical devices offline
        entity_id:
          - sensor.cv_garage_state
          - sensor.cv_stookhok_state
          - sensor.cv_zolder_state
          - sensor.zonneboiler_zolder_state
          - sensor.freezer_bijkeuken_state
        value_template: >
          {% set offline = expand('group.critical_devices_state')
           |selectattr('state','eq','off')|list|count %}{{offline}}
        attribute_templates:
          message: >-
            {% set count = expand('group.critical_devices_state')
             |selectattr('state','eq','off')|list|count %}
            {% set offline = expand('group.critical_devices_state') |
               selectattr('state','eq','off')|map(attribute='name')|list -%}
            {%- if offline|length == 0 -%} Ok, all critical devices are online
            {%- elif offline|length == 1 -%}{{count}} Critical device offline: {{offline[0]}}
            {%- elif offline|length == 2 -%}
              {{count}} Critical devices offline: {{offline[0]}} and {{offline[1]}}
            {%- else -%}
              {{count}} Critical devices are offline:{{offline[:-1]|join(', ')}}, and {{offline[-1]}}
            {%- endif -%}
        icon_template: >
          {% set count = expand('group.critical_devices_state')
           |selectattr('state','eq','off')|list|count %}
           mdi:numeric-{{count}}-box

I mean, I have to set the count in all template per sensor now, value, attributes and icon template…heck, could even use it in a friendly_name_template :wink:

like:

      count_critical_devices_offline:
        friendly_name: Critical devices offline
        entity_id:
          - sensor.cv_garage_state
          - sensor.cv_stookhok_state
          - sensor.cv_zolder_state
          - sensor.zonneboiler_zolder_state
          - sensor.freezer_bijkeuken_state
        value_template: >
          {% set offline = expand('group.critical_devices_state')
           |selectattr('state','eq','off')|list|count %}{{offline}}

      critical_devices_offline:
#        entity_id: sensor.count_critical_devices_offline # not needed, sensor updates fine without
        value_template: >
          {{states('sensor.count_critical_devices_offline')}}
        friendly_name_template: > # minor tweak using phrase in the name here
          {% set count = states('sensor.count_critical_devices_offline') %}
          {% set phrase = 'device' if count == '1' else 'devices' %}
          {{count}} Critical {{phrase}} offline
        attribute_templates:
          message: >-
            {% set count = states('sensor.count_critical_devices_offline') %}
            {% set offline = expand('group.critical_devices_state') |
               selectattr('state','eq','off')|map(attribute='name')|list -%}
            {%- if offline|length == 0 -%} Ok, all critical devices are online
            {%- elif offline|length == 1 -%}{{count}} Critical device offline: {{offline[0]}}
            {%- elif offline|length == 2 -%}
              {{count}} Critical devices offline: {{offline[0]}} and {{offline[1]}}
            {%- else -%}
              {{count}} Critical devices are offline:{{offline[:-1]|join(', ')}}, and {{offline[-1]}}
            {%- endif -%}
        icon_template: >
          {% set count = states('sensor.count_critical_devices_offline') %}
           mdi:numeric-{{count}}-box

Hi @petro,

found these buttons on your GitHub:

    [[[
      var i;
      var status = entity.state;
      var entities = entity.attributes.entity_id;
      var count = 0;
      for (i = 0; i < entities.length; i++) {
        var state = states[entities[i]].state;
        if (state === 'on') {
          count += 1;
        }
      }
      var phrase = (count === 1 ? ' light ' : ' lights ');
      return (status === 'on' ? count.toString() + phrase + status : status);
    ]]]

and they work wonderfully well.

could you help be rephrase this so the template uses a group, in which it should find the entity_ids?

the jinja syntax is used in the above templates, but I can’t just figure out how to do so in JS.
thanks if you would find a moment.

It uses a group already, is it not working?

well blimey, you’re right!. How utterly silly of me. I even use them that way…

      - type: custom:hui-horizontal-stack-card
        cards:
          - type: custom:button-card
            entity: group.all_inside_lights
            template: counter_lights

          - type: custom:button-card
            template: button_body
            entity: group.ikea_tradfri_lights
            template: counter_lights

          - type: custom:button-card
            template: button_body
            entity: group.philips_hue_lights
            template: counter_lights

please disregard the post and pretend I never wrote it… so sorry.

yes they do, I had simply fixed in my mind they used the domains as base for the entity_id’s

it might be worth the effort to see if the phrase can be deduced from the domains in the group? I was planning to use the template for buttons which only contain entity_ids from the same domain, like switches On, lights on, sensors etc etc, so no worries about mixed groups.

If so the template would need an extra kine or two to find that and set the phrase accordingly…

I could of course copy the template and only change the phrase, but for the fun of it, it would be cool to do so?

some template using var domain = entity.entity_id.split(‘.’)[0] and then use
var phrase = (count === 1 ? domain : domain+'s ');

would that work? It now says groups on :wink:

also, trying this:

    [[[
      var i;
      var status = entity.state;
      var entities = entity.attributes.entity_id;
      var count = 0;
      for (i = 0; i < entities.length; i++) {
        var state = states[entities[i]].state;
        if (state === 'off') {
          count += 1;
        }
      }
      var phrase = (count === 1 ? ' hub ' : ' hubs ');
      return (status === 'off' ? count.toString() + phrase + status : status);
    ]]]

to check for Hubs being Off, the button now shows simply ‘on’, while 1 is Off…

01

when using this as ‘on’ button, it shows correctly, so I know the groups is found correctly, and the counter also. Somehow the logic fails in the bottom template for counting ‘off’ entities?