Conditional TTS announcement - Alarm wont arm if windows open

So I have a load of xiaomi sensors in the house now and am trying to develop an alarm system.

What I want to do is have a button on the front door that I press in order to arm the alarm system. If all of the windows are closed, the alarm will arm and activate after 30 seconds. Simple enough.

Where I’m having problems is that I’d like it to flag up if I’ve left a window open when trying to arm the alarm. That was easy to do when I had window sensors in just one room, but now theyre in 5 rooms it gets a little tricky and I ultimately want to get a TTS announcement saying which rooms the windows are open in (e.g. you’ve left windows open in the bedroom and front room) so I know where I need to go to close the windows.

I’ve made template sensors to merge all the sensors for each room as below:

- platform: template
      sensors:
    living_room_windows:
      friendly_name: Living Room Windows
      value_template: >-
        {%- if is_state("binary_sensor.xiaomi_living_room_l", "off") and is_state("binary_sensor.xiaomi_living_room_mid", "off") and is_state("binary_sensor.xiaomi_living_room_r", "off") %}
            Windows closed
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "on") and is_state("binary_sensor.xiaomi_living_room_mid", "off") and is_state("binary_sensor.xiaomi_living_room_r", "off") %}
            Left window open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "off") and is_state("binary_sensor.xiaomi_living_room_mid", "off") and is_state("binary_sensor.xiaomi_living_room_r", "on") %}
            Right window open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "off") and is_state("binary_sensor.xiaomi_living_room_mid", "on") and is_state("binary_sensor.xiaomi_living_room_r", "off") %}
            Middle window open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "on") and is_state("binary_sensor.xiaomi_living_room_mid", "on") and is_state("binary_sensor.xiaomi_living_room_r", "off") %}
            Left & middle windows open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "off") and is_state("binary_sensor.xiaomi_living_room_mid", "on") and is_state("binary_sensor.xiaomi_living_room_r", "on") %}
            Right and middle windows open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "on") and is_state("binary_sensor.xiaomi_living_room_mid", "off") and is_state("binary_sensor.xiaomi_living_room_r", "on") %}
            Left and right windows open
        {%- elif is_state("binary_sensor.xiaomi_living_room_l", "on") and is_state("binary_sensor.xiaomi_living_room_mid", "on") and is_state("binary_sensor.xiaomi_living_room_r", "on") %}
            All 3 windows open
        {%- endif %}
      icon_template: '{% if is_state("sensor.living_room_windows", "Windows closed") %}mdi:lock{% else %}mdi:lock-open-outline{% endif %}'

I dont want to do something similar for each template sensor as I want to add more window sensors in the future and dont fancy doing 64 elif’s for every possible combination of rooms with windows open.

Can someone suggest a simple way to get the automation to automatically identify which rooms have a window open (based on a single template sensor for each room) and allow me to combine them in a tts announcement?

You could probably start with some of the info in this post…

Sorry not more helpful but I’m no expert with the templates so I end up finding as many posts as I can with similar things and pieceing them together for my use. Hope that’s enough to get you started

That’s really helpful, thanks!

Now I just need to work out how to put an ‘and’ before the last value, rather than in between each value listed. Im currently getting: “You have left windows open in the Bedroom and Kitchen and Living Room and Loft”

There is a way to get it to word it differently depending if there is one open or multiple I’ll see if I can find a post with it
Edit:
This I think is something like it you would need… I’m not sure exactly without messing around. Maybe post your current code and someone would know if this is the right way to do it

            {% set open_windows = states | selectattr('entity_id', 'in', state_attr('group.all_windows','entity_id')) | selectattr('state','in',['on','open']) | map(attribute='name') | list %}
            {% if open_windows | length == 1 %}
              The window: "{{ trigger.from_state.attributes.friendly_name }}" has been open for 20 mins. 
            {% else %}
              The window: "{{ trigger.from_state.attributes.friendly_name }}" has been open for 20 mins. Currently open windows: {{ open_windows[:-1] | join(', ') }}{{',' if open_windows | length > 2 else ''}} and {{ open_windows[-1]}}.
            {% endif %}
1 Like

You are an absolute star Bartem! :star2:

Ammended slightly to fit what I need but now it works perfectly! I’ll give an overview of my integration below so anyone who wants to do anything similar can.

I have loads of xiaomi door/window sensors, which I have merged into rooms with template binary sensors as below. If any window is open (or ‘on’), the binary sensor will also be on.

- platform: template
  sensors:
    living_room_windows:
      friendly_name: Living Room
      device_class: window
      value_template: "{{ is_state('binary_sensor.xiaomi_living_room_l', 'on') or is_state('binary_sensor.xiaomi_living_room_r', 'on') or is_state('binary_sensor.xiaomi_living_room_mid', 'on') }}"

Then all of the binary sensors are in a group called group.windows. If any binary sensor is on, this results in the group status also being on.

Then finally, the automation for the TTS is below. If the button is pressed, the ‘intruder alarm’ input boolean is off and any window is open, the following automation will run:

#---Single press to arm alarm - window error---
  - alias: Button arm alarm window error
    hide_entity: true
    trigger:
      platform: event
      event_type: xiaomi_aqara.click
      event_data:
        entity_id: binary_sensor.xiaomi_button_1
        click_type: single
    condition:
      condition: and
      conditions:
        - condition: state
          entity_id: input_boolean.intruder_alarm
          state: 'off'
        - condition: state
          entity_id: group.windows
          state: 'on'
    action:
     - service: media_player.sonos_snapshot
       entity_id: media_player.sonos_play_one
     - service: media_player.sonos_unjoin
       entity_id: media_player.sonos_play_one
     - service: media_player.volume_set
       data_template:
         entity_id: media_player.sonos_play_one
         volume_level: '0.7'
     - service: tts.google_say
       data_template:
         entity_id: "media_player.sonos_play_one"
         message: >-
          {% set open_windows = states | selectattr('entity_id','in', state_attr('group.windows','entity_id')) | selectattr('state','eq','on') | map(attribute='name') | list %}
          {% if open_windows | length == 0 %}
              All windows are closed.
          {% elif open_windows | length == 1 %}
              There is a window open in the {{ open_windows | join('') }}.
          {% else %}
              There are windows open in the {{ open_windows[:-1] | join(', ') }}{{',' if open_windows | length > 2 else ''}} and {{ open_windows[-1]}}.
          {% endif %}
     - delay: '00:00:03'
     - service: media_player.sonos_restore
       entity_id: media_player.sonos_play_one

I then have another automation which will look out for the windows being closed and if closed within 5 mins of the button being pressed/prev. automation run, will then automatically start the alarm arm countdown. I could do the announcement here via TTS but I already have one set up to play from the gateway so I’ve just kept that.

  - alias: Arm alarm after window closed
    hide_entity: true
    trigger:
      platform: state
      entity_id: group.windows
      to: 'off'
    condition:
      - condition: template
        value_template: "{%- if (as_timestamp(now()) - as_timestamp(states.automation.button_arm_alarm_window_error.attributes.last_triggered) <300 ) -%}true{%- else -%}false{%- endif -%}"
    action:
      - service: xiaomi_aqara.play_ringtone
        data:
          gw_mac: MACADDRESSHERE
          ringtone_id: 10010
          ringtone_vol: 80
      - delay: 00:00:60
      - service:  input_boolean.turn_on
        data:
          entity_id: input_boolean.intruder_alarm
2 Likes

Hi i’m having the same issue but my logic is in esphome and not home assistant.

I want to be able to create 2 groups arm away and, arm home in arm away all sensors and door contacts will trigger the alarm arm home only only the sensors added to arm home will trigger the alarm. so some sensors will be in both groups. Now the above is challenging for me to do in the first place because i only have about 3 months experience now. The second part of my problem is this. Currently when i arm my alarm it arms find but the problem is if i have a door open or a windows opened it still arms and i don’t have any way of knowing which window or door is opened and i want to be able to add a check to see if contact is opened and if opened notify which ones are opened and then once closed i can continue to arm again or the sequence automatically continues. Can you or anyone here help me with this one