Automation that checks for is doors are open before going to bed

Hi all,

I want to build a simple automation that runs a 10 pm and, if one of my binary sensors (xiaomi doors sensors) are open, trigger a notification on telegram.

I’ve built the trigger and condition part but I’m unable to build the action part.

I “feel” that I have to use the loop function but how can I select only a specific range of sensor and not a generic category (exclude others binary sensors).

Thank you in advace

1 Like

I would use a condition list with the door sensor:

  condition:
    condition: or
    conditions:
      - condition: state
        entity_id: sensor.door_sensor_1
        state: 'on'
      - condition: state
        entity_id: sensor.door_sensor_2
        state: 'on'

And the action is a simple notify event:

  action:
    service: notify.telegram
    data:
      title: "Door is still open"

of course your telegram component need to be configured.

The trigger is a simple time trigger:

automation:
  alias: "Check door status at 10PM"
  initial_state: True
  trigger:
    - platform: time
      at: '22:00:00'

Thank you for your feedback. I’ve already set up the automation this way. What I would like to achieve is the chance to see which one is open without have to check on the frontend.

That can also be done using a data template …

action:
  service: notify.telegram
  data_template:
    message: 'Door states: Door 1 {{ states.sensor.door_sensor_1.state  }} and Door 2: {{ states.sensor.door_sensor_2.state  }}'
    title: 'Whatever title goes here'

@Jokerigno

First make a group with all your door sensors in it. Also, make sure the state of all your door sensors will always be ‘on’ or ‘open’ when the door is ajar.

For this example, i will use the group: group.all_doors. Also, note this will only message you if doors are open at 10pm. Otherwise, you won’t get a message.

automation:
  alias: "check all doors at 10PM"
  trigger:
    - platform: time
      at: '22:00:00'
  condition:
    condition: template
    value_template: > 
      # this counts the doors that are open and if we have any that are open, the notify will occur
      {{ states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | list | length >= 1 }}
  action:
    - service: notify.notify
      data_template:
        title: "Doors Open!"
        message: > 
          {% set open_doors = {{ states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | list | map(attribute='name') | join(', ') }}
          The following doors are open: {{ open_doors }}

here’s an example of it working with doors that are closed ( i did this cause my doors are closed atm).

8 Likes

In order to use it with TTS also it is possible to create a message like the door A and the door B are open.

I’ve read somewhere (but I searched in vain) that is possible using loop.first % and loop.last % but I’m unable to replicate it.

So, do you want more than 1 message? Or 1 message with each door saying it’s open?

1 message that says only which door are open. For example: Hi, you left DOOR A and DOOR B open.

I mean, you could always just code it out…

automation:
  alias: "check all doors at 10PM"
  trigger:
    - platform: time
      at: '22:00:00'
  condition:
    condition: template
    value_template: > 
      # this counts the doors that are open and if we have any that are open, the notify will occur
      {{ states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | list | length >= 1 }}
  action:
    - service: notify.notify
      data_template:
        title: "Doors Open!"
        message: > 
          {% set open_doors = states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | map(attribute='name') | list %}
          {% if open_doors | length == 1 %}
            The {{ open_doors[0] }} door is open.
          {% else %}
            The {{ open_doors[:-1] | join(' door, ') }}{{' door,' if open_doors | length > 2 else ' door'}} and {{ open_doors[-1]}} door are open.
          {% endif %}

single door sentance:

The front door is open.

double door sentance:

The front door and side door are open.

more than 2 doors sentance:

The front door, side door, and back door are open.

EDIT: I placed the word door behind the name because “Door Front” doesn’t make sense.

EDIT 2: The reason you can’t use the loop that you keep referencing is because the way jinja works. Jinja can only return 1 result. When iterating around a loop, it would return multiple items. This would cause your message to only output the last loop item instead of segmenting the message together.

5 Likes

You can simplify that - if any member of the group is on then the group is on

Here’s a link to a similar automation of mine. All my exterior doors are in the group group.my_exterior_doors.

1 Like

Found this topic, even if is an old one I thought it would be useful to share my ideas:

what I wanted to achieve was to ask Google if there were open doors/windows and, if yes, which ones.
I decided to go for a python script:

cur_state = hass.states.get('group.aperture')
if (cur_state.state == "off") :
    hass.services.call('tts', 'google_say', {"entity_id":"media_player.spione","message":"all is closed"})
else :
    i = 0
    openings = []
    
    for a in cur_state.attributes["entity_id"]:
        temp_state = hass.states.get(a)
        if (temp_state.state == "on") :
            i = i + 1
            openings.append(a)
    
    if (i == 1) :
        message = "there is one opening that's not closed"
        hass.services.call('tts', 'google_say', {"entity_id":"media_player.spione","message":message})
    
    else :
        message = "there are " + str(i) + " openings not closed"
        hass.services.call('tts', 'google_say', {"entity_id":"media_player.spione","message":message})
    
    for b in openings :
        time.sleep(3)
        temp_state = hass.states.get(b)
        hass.services.call('tts', 'google_say', {"entity_id":"media_player.spione","message":temp_state.attributes["friendly_name"]})

basically, I have a group in which I put all the door sensors, check if off and, if not, cycle all the entities to find how many are open; contextually I put in an array which ones. Later I cycle again to make google say the friendly name of everyone that is open.

1 Like

I cant for the life of me get this working. Both template statements work in the editor, but will not work in my automations. Gives this error

Invalid config for [automation]: invalid template (TemplateSyntaxError: expected token ‘:’, got ‘}’) for dictionary value @ data[‘action’][0][‘data_template’][‘message’]. Got “{% set open_doors = {{ states | selectattr(‘entity_id’, ‘in’, state_attr(‘group.doors’,‘entity_id’)) | selectattr(‘state’,‘in’,[‘on’,‘open’]) | list | map(attribute=‘name’) | join(', ')}} The following doors are open: {{ open_doors }}”.

  • id: ‘1234321234532’
    alias: Door Status
    trigger:
    - platform: time
    at: ‘22:00:00’
    condition:
    condition: template
    value_template: >
    # this counts the doors that are open and if we have any that are open, the notify will occur
    {{ states | selectattr(‘entity_id’, ‘in’, state_attr(‘group.doors’,‘entity_id’)) | selectattr(‘state’,‘in’,[‘on’,‘open’]) | list | length >= 1 }}
    action:
    - service: notify.alexa_media
    data_template:
    title: Doors Open
    message: >
    {% set open_doors = {{ states | selectattr(‘entity_id’, ‘in’, state_attr(‘group.doors’,‘entity_id’)) | selectattr(‘state’,‘in’,[‘on’,‘open’]) | list | map(attribute=‘name’) | join(', ')}}
    The following doors are open: {{ open_doors }}

your last emplate is wrong. you can’t embed templates in templates.

{% set open_doors = ( states | selectattr('entity_id', 'in', state_attr('group.doors','entity_id')) | selectattr('state','in',['on','open']) | list | map(attribute='name') | join(', ') ) %}
The following doors are open: {{ open_doors }}

I haven’t checked it for the right ( ) pairings since there are bunch of them nested so you’ll have to double check those. But it will be close.

1 Like

Thanks finity. Think i have it working. Now to just get alexa to read the output lol

I also just noticed I used the wrong style of quotation marks in the template. I used the “fancy” style instead of the standard text ones because I just did a copy/paste of your post. You probably noticed that if you have it working but I edited the post for the sake of completeness.

Ive got an error to except i get “none” how did you fix?

gotten this to work when manually executing but it wont trigger the automation on its own…

automation:
- id: Door Check 
  alias: Door Check 
  trigger:
  - platform: state
    entity_id: group.life360
    from: home
    to: not_home
  - platform: time
    at: '15:24:00'
  condition:
    condition: template
    value_template: > 
      # this counts the doors that are open and if we have any that are open, the notify will occur
      {{ states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | list | length >= 1 }}
  action:
  - service: notify.ios_marks_iphone_xr
    data_template:
      title: "Caution!"
      message: > 
        {% set open_doors = states | selectattr('entity_id', 'in', state_attr('group.all_doors','entity_id')) | selectattr('state','in',['on','open']) | map(attribute='name') | list %}
        {% if open_doors | length == 1 %}
          The {{ open_doors[0] }} door is open.
        {% else %}
          The {{ open_doors[:-1] | join(', ') }}{{',' if open_doors | length > 2 else ' door'}} and {{ open_doors[-1]}} door are open.
        {% endif %}

The docs recommend home and not_home be in quotes…

even still i change it to a state of a light turning on and it still doesnt trigger it…