Hello Cogniscenti,
I have picked up a template to report which of my binary_sensors have triggered my alarm. However it is not working and the automation halts before other services can run. The automation is:
- alias: 'Intruder alarm'
trigger:
platform: state
entity_id: alarm_control_panel.home_alarm
to: "triggered"
action:
- service: notify.paul_pushover
data_template:
message: >-
{%- set ns = namespace(message = "Alarm has been triggered at {{now().strftime ('%H:%M:%S %d/%m/%y')}}.\n The following sensors have been triggered:\n") -%}
{%- for item in states.binary_sensor -%}
{%- if [ "motion", "door", "window" ] in item.name | lower and item.state == "on" -%}
{%- set ns.message = ns.message + " - " + item.name + " (" + item.state | upper + ")\n" -%}
{%- endif -%} {%- endfor -%}
{{ ns.message }}
data:
title: "Intruder Alarm!"
data:
sound: siren
priority: 2
retry: 30
expire: 120
When I run the template through the Template tester in Developer Tools I get: TypeError: 'in <string>' requires string as left operand, not list
Playing around with bits of the template I have also noticed that the line:
{%- set ns = namespace(message = “Alarm has been triggered at {{now().strftime (‘%H:%M:%S %d/%m/%y’)}}.\n The following sensors have been triggered:\n”) -%}
produces the following text:
Alarm has been triggered at {{now().strftime (‘%H:%M:%S %d/%m/%y’)}}.
The following sensors have been triggered:
I am unable to identify where the errors are, and I would be very grateful if you could point out where I am going wrong.
Thank you your help!
You can’t enclose a template within a template. You can use the following:
{% set ns = namespace(message = "Alarm has been triggered at "~ now().strftime ('%H:%M:%S %d/%m/%y.')~"\n The following sensors have been triggered:\n") -%}
message: >-
{%- set ns = namespace(message = "Alarm has been triggered at {{now().strftime ('%H:%M:%S %d/%m/%y')}}.\n The following sensors have been triggered:\n") -%}
{%- for item in states.binary_sensor -%}
{%- if [ "motion", "door", "window" ] in item.name | lower and item.state == "on" -%}
{%- set ns.message = ns.message + " - " + item.name + " (" + item.state | upper + ")\n" -%}
{%- endif -%} {%- endfor -%}
{{ ns.message }}
with this:
message: >
Alarm has been triggered at {{now().strftime('%H:%M:%S %d/%m/%y')}}.
The following sensors have been triggered:
{{ states.binary_sensor
| selectattr('name', 'search', '(door|window|motion)', true)
| selectattr('state', 'eq', 'on')
| map(attribute='name') | list | join(' - (on)\n') }}
It doesn’t contain the nested template like in your version (which has already been pointed out to be invalid) and doesn’t require the use of a namespace or a for-loop.
NOTE
I’m not quite sure why you chose to append each binary_sensor’s state value to its name given that they’re all on (because the template extracts only the ones that are on) but I included it anyway.
Thank you all three for your erudite comments. I have learnt new things from all of you, particularly what the selectattr does.
In the end I went with 123 Tara’s suggestion and left off the state value. I also changed the attribute from ‘name’ to ‘entity_id’ and refined the text strings that were being looked for. Using ‘name’ resulted in all sorts of entities showing up including the motion sensors with their low battery binary_sensor states showing “on”.
Then I realised that I had a carbon monoxide sensor that I could not turn off the motion detection state, and a couple of switches that for some reason had security_motion_detection entities - perhaps some sort of malfunction because their device_class was defined as “motion”.
So I needed to exclude these from the list and found “rejectattr”.
Thanks very much again!
Alarm has been triggered at {{now().strftime(‘%H:%M:%S %d/%m/%y’)}}.
The following sensors have been triggered:
{{ states.binary_sensor
| rejectattr(‘entity_id’, ‘search’, ‘(switch|monoxide)’, true)
| selectattr(‘entity_id’, ‘search’, ‘(door_is_open|security_motion_detection)’, true)
| selectattr(‘state’, ‘eq’, ‘on’)
| map(attribute=‘name’) | list | join(‘\n’) }}