Here’s a script I wrote to do the same thing for me. I go into all my various devices and make sure the device class is set properly (i.e., a generic window sensor is set to be a window), then I can use this to summarize all problems with my house. What this does is compile a return value for your calling script or your automation and then you can simply go into each section (locks, windows, doors, etc) and the announcement is already set, you pipe that to Google (which I don’t use and don’t know how to tell it to speak):
snippet_security:
alias: Security TTS Snippet
mode: single
icon: "mdi:account-voice"
sequence:
- variables:
response:
#######################
# LOCKS
#######################
locks: >-
{% set ns = namespace(secure=true, locks='') %}
{% set locks =
states.lock |
rejectattr('state', 'in', ['locked'])
%}
{% for l in locks %}
{% set ns.secure = false %}
{% set ns.locks = ns.locks + 'The ' + l.name.replace(' Lock','').replace(' xx', '') + ' is ' + l.state + '. ' %}
{% endfor %}
{{
{
'secure': ns.secure,
'message': ns.locks
}
}}
#######################
# VIBRATION SENSORS
#######################
vibration: >-
{% set ns = namespace(secure=true, windows='') %}
{% set windows =
states.binary_sensor |
selectattr('attributes.device_class', 'defined') |
selectattr('attributes.device_class', 'eq', 'vibration') |
rejectattr('name', 'search', 'dryer', ignorecase=True) |
rejectattr('state', 'in', ['unavailable', 'unknown', 'off'])
%}
{% for d in windows %}
{% set ns.secure = false %}
{% set ns.windows = ns.windows + 'The ' + d.name + ' is triggered. ' %}
{% endfor %}
{{
{
'secure': ns.secure,
'message': ns.windows
}
}}
#######################
# WINDOW SENSORS
#######################
windows: >-
{% set ns = namespace(secure=true, windows='') %}
{% set windows =
states.binary_sensor |
selectattr('attributes.device_class', 'defined') |
selectattr('attributes.device_class', 'eq', 'window') |
rejectattr('name', 'search', 'lock', ignorecase=True) |
rejectattr('state', 'in', ['unavailable', 'unknown', 'off'])
%}
{% for d in windows %}
{% set ns.secure = false %}
{% set ns.windows = ns.windows + 'The ' + d.name + ' is open. ' %}
{% endfor %}
{{
{
'secure': ns.secure,
'message': ns.windows
}
}}
#######################
# DOOR SENSORS
#######################
doors: >-
{% set ns = namespace(secure=true, doors='') %}
{% set doors =
states.binary_sensor |
selectattr('attributes.device_class', 'defined') |
selectattr('attributes.device_class', 'eq', 'door') |
rejectattr('state', 'in', ['unavailable', 'unknown', 'off'])
%}
{% for d in doors %}
{% set ns.secure = false %}
{% set ns.doors = ns.doors + 'The ' + d.name + ' is open. ' %}
{% endfor %}
{{
{
'secure': ns.secure,
'message': ns.doors
}
}}
- stop:
response_variable: response
So to get that I call the script and parse the result:
# SECURITY SNIPPET
- service: script.snippet_security
data: {}
response_variable: security
{% if security.windows.secure != true %}
... tell your TTS system to say what is in security.windows.message or security.locks.message, etc
{% endif %}
There are ways to shorten the code, but this is very readable to me and it’s been very reliable.
To make filtering easier for this script I went into each various sensor and properly defined it (Show As):