Help with template?

I am trying to create an alexa intent to have her tell us what lights are on. I created two template sensors, one for the count (lights_on_count), and one for the list of lights(lights_on_list). They are working and the states show just fine in the dev tools.

Here is the intent yaml:

  LightsOnIntent:
    speech:
      text: >
        {%- if states('sensor.lights_on_count') > 0  -%}
          {%- if states('sensor.lights_on_count') = 1  -%}
            The {{states.sensor.lights_on_list.state}} is on.
          {%- else -%}
            Currently, the {{states.sensor.lights_on_list.state}} are on.
          {%- endif -%}
        {%- else -%}
          There are currently no lights on.
        {%- endif -%}

whenever i try to validate this or any combination of this, i get the following error:

Invalid config for [intent_script]: invalid template (TemplateSyntaxError: expected token ‘end of statement block’, got ‘=’) for dictionary value @ data[‘intent_script’][‘LightsOnIntent’][‘speech’][‘text’]. Got “{%- if states(‘sensor.lights_on_count’) > 0 -%}\n {%- if states(‘sensor.lights_on_count’) = 1 -%}\n The {{states.sensor.lights_on_list.state}} is on.\n {%- else -%}\n Currently, the {{states.sensor.lights_on_list.state}} are on.\n {%- endif -%}\n{%- else -%}\n There are currently no lights on.\n{%- endif -%}\n”. (See /config/configuration.yaml, line 149).

i have no idea where it is going wrong, i’ve tried every combination that i can possibly think of, but it always fails. any ideas?

A single ‘=’ is for assigning a variable a value. For an if, you need to use ==. So:

{%- if states('sensor.lights_on_count') == 1  -%}
1 Like

Wow, I can’t believe I overlooked that… Thank you!!!

states are stings, you need to convert the value to an int in order to compare it. You’re going to run into problems if your light list is long. You’re storing it in a state, but states are limited to 255 characters. You should store it as an attribute of sensor.lights_on_count instead.

  LightsOnIntent:
    speech:
      text: >
        {% set count = states('sensor.lights_on_count') | int(0) %}
        {%- if count > 0  -%}
          {%- if count == 1 -%}
            The {{ states('sensor.lights_on_list') }} is on.
          {%- else -%}
            Currently, the {{state('sensor.lights_on_list')}} are on.
          {%- endif -%}
        {%- else -%}
          There are currently no lights on.
        {%- endif -%}
1 Like

good point. the only reason i had created template sensors out of them was because i was having problems validating the yaml. I’ve modified as shown below. do variables also have a 255 character limit?

  LightsOnIntent:
    speech:
      text: >
        {% set count = states.light | selectattr('state', 'eq', 'on') | rejectattr('attributes.entity_id', 'defined') | list | count | int(0) %}
        {% set lights_on = states.light | selectattr('state', 'eq', 'on') | rejectattr('attributes.entity_id', 'defined') | map(attribute='name') | list | join(', ')  %}
        {%- if count > 0  -%}
          {%- if count == 1  -%}
            The {{lights_on}} is on.
          {%- else -%}
            Currently, the {{lights_on}} are on.
          {%- endif -%}
        {%- else -%}
          There are currently no lights on.
        {%- endif -%}

no point in filtering twice

  LightsOnIntent:
    speech:
      text: >
        {% set lights_on = states.light | selectattr('state', 'eq', 'on') | rejectattr('attributes.entity_id', 'defined') | map(attribute='name') | list  %}
        {% set count = lights_on | count %}
        {%- if count > 0  -%}
          {%- if count == 1  -%}
            The {{ lights_on[0] }} is on.
          {%- else -%}
            Currently, the {{ lights_on | join(', ') }} are on.
          {%- endif -%}
        {%- else -%}
          There are currently no lights on.
        {%- endif -%}
1 Like

brilliant!

Another option is an Area-based approach. I find it easier to understand/act on compared to having Alexa read off a long list of entities. It does require that all your light entities have an area assigned to them.

{% set lights_on = states.light | selectattr('state','eq','on')  | map(attribute='entity_id') 
| map('area_name') | unique | reject('eq',None) | list %} 
{% set qty = lights_on | count %} 
{% if qty != 0 %} 
Currently, there are lights on in the {{' and '.join((lights_on|join(', ')).rsplit(', ', 1)) }}.
{% else %} 
All lights are currently off. 
{% endif %}
1 Like

thanks for that, i implemented it and works great.