Template to report which binary_sensor has triggered

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!

try changing this:

{%- if [ "motion", "door", "window" ] in item.name | lower and item.state == "on" -%}

to this:

{%- if item.name | lower in [ "motion", "door", "window" ] and item.state == "on" -%}

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") -%}

If you want, you can replace this:

        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’) }}