Template sensor: count number of enabled input_booleans using an IF statement

For my irrigation time calculation I need to have a variable/sensor with the number of days I’ve enabled. For some reason this is not working as I expected. Using a YAML validator the code seems fine. But when I paste the information below in the template builder this error is displayed: Error rendering template: TemplateSyntaxError: expected token ‘end of print statement’, got ‘{’

sensor:
  - platform: template
    sensors:      
      sprinkler_days_enabled:
        friendly_name: "Number of days to irrigate"
        unit_of_measurement: 'days'
        value_template: "{{ 0 
          {% if is_state('input_boolean.sprinkler_monday','on') -%}
            + 1 
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_tuesday','on') -%}
            + 1 
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_wednesday','on') -%}
            + 1
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_thursday','on') -%}
            + 1
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_friday','on') -%}
            + 1
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_saturday','on') -%}
            + 1
          {%- endif %}
          {% if is_state('input_boolean.sprinkler_sunday','on') -%}
            + 1
          {%- endif %} 
          }}"

If someone has a better way of counting these I’m open to suggesions

Put all your input booleans in a group. Then use this template sensor to count how many are on:

sensor:
  - platform: template
    sensors:      
      sprinkler_days_enabled:
        friendly_name: "Number of days to irrigate"
        unit_of_measurement: 'days'
        value_template: "{{ states.group.your_group_of_ipbs|expand|selectattr('state', 'eq', 'on')|list|count|int }}"
1 Like

It’s my understanding that the Template Sensor in your example will not update itself whenever one of the group’s members changes state. It will update itself when the group changes state. Once the group’s state is on, subsequent changes to any of the group members won’t be detected and so the Template Sensor will not be updated. The reason for this is that when a Template Sensor contains a group, Home Assistant creates a single listener for the group and not multiple listeners, one for each member of the group.

Currently, the simplest way around this limitation is to list all the entities that must be monitored.

sensor:
  - platform: template
    sensors:      
      sprinkler_days_enabled:
        friendly_name: "Number of days to irrigate"
        unit_of_measurement: 'days'
        value_template: >
          {{[ states.input_boolean.sprinkler_monday,
              states.input_boolean.sprinkler_tuesday,
              states.input_boolean.sprinkler_wednesday,
              states.input_boolean.sprinkler_thursday,
              states.input_boolean.sprinkler_friday,
              states.input_boolean.sprinkler_saturday,
              states.input_boolean.sprinkler_sunday ]
            | selectattr('state', 'eq', 'on') | list | count}}

EDIT
There was an enhancement introduced in 0.110 that changed the behavior (i.e. when the template contains expand, Home Assistant would expand it first and then create a listener for each member of the group). Unfortunately, it didn’t work and the PR to fix it is still in progress.

2 Likes

Ah yes. Good catch.

Great, thanks, that look promissing :smiley: I will try as soon as I can. I was able to break my HA by doing a reboot with a config file that didn’t pass the Config Validation :unamused: So I will need to fix that first when I get back from work.

I’m guessing they could also be listed under entity_id rather than in the template?

sensor:
  - platform: template
    sensors:      
      sprinkler_days_enabled:
        friendly_name: "Number of days to irrigate"
        unit_of_measurement: 'days'
        entity_id:
          - input_boolean.sprinkler_monday
          - input_boolean.sprinkler_tuesday
          - input_boolean.sprinkler_wednesday
          - input_boolean.sprinkler_thursday
          - input_boolean.sprinkler_friday
          - input_boolean.sprinkler_saturday
          - input_boolean.sprinkler_sunday
        value_template: "{{ states.group.your_group_of_ipbs|expand|selectattr('state', 'eq', 'on')|list|count|int }}"

Absolutely. The sole difference is that in my example there’s no need to create a group. Therefore there’s a little less maintenance when it comes time to add a new input_boolean.

FWIW, if the PR I mentioned is ever implemented it will make your first example the easiest way, with the least maintenance. Add a new input_boolean to the group, restart Home Assistant (so it gets a chance to re-expand the group in the template and assign new listeners to all its members), and done; just add the new member to the group and all Template Sensors that expand that group are good to go.

In a perfect world, restarting would be unnecessary and reloading groups would be sufficient. However, I believe that’s not enough to make Home Assistant re-evaluate all its Template Sensors. We would need a two-step process: reload groups and then reload Template Sensors (unfortunately, that’s not a service that currently exists).

1 Like

I hope it’s something the dev team are thinking / talking about at least.

The following development does not introduce the aforementioned reload service but I think it’s a step in the direction of dynamic Template Sensors.

The following PR was recently merged in the dev branch so it might appear in 0.114 (or later). It lets you assign an optional unique_id to a Template Sensor (Binary Sensor, Light, Cover, etc). That’s needed to allow the entity to be recorded in core.entity_registry and permit the user to edit the entity’s name and icon via the UI.

I may be wrong but I think it lays the groundwork for the (future) ability to define Template Sensors via the UI. For example, since a few versions ago you can define so-called Helpers (input_boolean, input_number, etc) via the UI. They are automatically assigned a unique_id and stored in the entity_registry and are immediately available for use (no restart is required). They also have associated reload services (Reload Input_Boolean, etc).

Admittedly, a Template Sensor is a more complex beast than, say, an Input Boolean because it contains a template that Home Assistant must inspect for entities and assign listeners to them. This would have to happen at the moment the Template Sensor is first defined and upon reload (and, of course, startup which is the only time it happens now).

1 Like

The beta for 0.114 is out: https://rc.home-assistant.io/blog/2020/08/05/release-114/

Thanks guys, I got this to work. Much appreciated :smiley: :smiley: