Automation to check if any windows/doors are open and annouce it via Google Nest speakers

Hey,

I’m seeking advice about how I can achieve an automation that would announce via Google Home speakers which Windows/Doors are open when I press a button on a Zigbee remote. I tried Googling, but couldn’t find anything relevant.

Automation in more description:

Let’s say I have two windows and one door:
binary_sensor.bedroom_window_contact
binary_sensor.office_window_contact
binary_sensor.balcony_door_contact

Two Google Home/Nest speakers:
office_speaker
bedroom speaker

And an IKEA RODRET button:
button.hallway_button

What I want the automation to do:

  1. I press the button.hallway_button
  2. Home Assistant checks if any windows or doors are open.
  3. Home assistant makes Google home speaker say, “A window X and Y are open” or “All windows and doors are closed” depending on the situation.

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):
image