Hope someone here could help me with a contact sensor/ lock automation (all doors in 1 automation if possible)

Hello all,

First of all, I wanted to say thank you to @Hellis81 and @pedolsky for all of the time they have spent helping me with other automations and on other threads. They are each very helpful in their own ways!

So, I’m hoping someone here can help me with the below. My programming skills are pretty sad (I can do simple things but not I don’t think they are at the level for this one I believe) but I’m hoping someone here can help me design an automation/ template sensor (if the sensor is even necessary??). (I think the below are a few things that are helpful to know in creating the automation)

My goal would be for the automation and/ or accompanying template sensor to not have to be updated if a new door or lock is added to the home. I’m also hoping to not have to rename any entities because they are already tied into a bunch of other automations.

Lock entities:
lock.front_door_lock
lock.back_door_lock
lock.garage_entry_door_lock

contact sensor that I have placed on the doors:
binary_sensor.front_door
binary_sensor.back_door
binary_sensor.garage_entry_door

Below is what I am trying to do in paragraph form:

Let’s say my house has 3 doors. At 10 pm, 2 are closed. I would want those 2 to go ahead and lock. Then I would want HA to send me a notification about the 3rd door that is open but I don’t want home assistant to send the lock command to that open door because it would do no good since the door is open.

I would like the same exact concept as above as a second automation but would like it to be when the family group goes from “home” to “not_home”

Thank you all for any guidance you can give. I’ll be honest I hope someone here can show me some examples of the different concepts to get this done, I am more than willing to learn and if you could help with this, I would be very appreciative also if you would be ok with me responding back with a bunch of question about the ideas you have given.

So you can loop through locks by doing this:

repeat:
  for_each: "{{ states.lock | list }}"
  sequence:
    - ...

And inside that loop you can reference the current lock by using repeat.item in templates. There’s a couple ways you can get to the binary sensor from there. The obvious way is from the entity id like so:

variables:
  sensor_for_lock: "{{ repeat.item.entity_id  | replace('lock.', 'binary_sensor.') | replace('_lock', '') }}"

If you prefer you can also use an option not dependent on entity_id. Like by adding an area for each door and then finding the binary sensor in the same area as the lock entity. Or adding the same attribute to both using customization and then finding the binary sensor with the same attribute.

With this you can loop through all doors and find the “is open” sensor for the door. Maybe take this and give a shot at writing the automation yourself so then people can give you tips and feedback? The point of this community is to help people learn how to do things themselves rather then do things for people.

Also don’t feel obligated to do it in yaml. Youll need to drop to yaml a little bit to put in the templates I shared but should be mostly doable in the GUI editor. Start by writing the whole thing for one door. Then try to replace the hardcoded door is with the loop and variable steps.

I’m really not trying to be a butt by saying this- seriously- but I don’t have a clue where to go/ how to start with any of this. I’m not saying, I’m not willing, I’m just saying I’m not knowing and I’m sure everything you are telling me is valid because I’ve seen your post all over the place and they seem to be very helpful for the people that know where to begin.

Obvious for someone that knows what in the world they’re doing. I didn’t even know you could do any of that like you did.

Don’t disagree with you here at all.

Below is my attempt, logically (pseudo code maybe it’s called) at least but I don’t feel like it uses your concepts at all or could even be converted to use your concepts. This is an example of a non coder coding.

But, the most I understand at this point is I have a Trigger area, a Conditions area, and an Actions area.
If I were doing this with my knowledge level. I would do it like below and I would have to create an automation for each door which I think sucks. The problem is my knowledge/ capability level doesn’t line up with the quality of automation I want to start off with right off the bat.

Here is my view at my skill level:

So I’m assuming my trigger is: when time hits 10 pm

Option
condition1: front door is closed

action1: lock front door

condition2: front door is open

action2: Don’t lock door but instead send message about front door being open

Can you give me a little more, ummm, bait/ teaching for your thoughts on how to do this or a little more layout. I don’t feel capable enough to go fishing myself just yet on this one. I don’t even know where to use “repeat”. I have used variables in an automation before. Below is another example of my current skill level. All of these were learned by seeing others use them first.

alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Garage Doors Close when Away
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
condition:
  - condition: template
    value_template: '{{ garagedoorsopen |count > 0 }}'
action:
  - service: cover.close_cover
    data: {}
    target:
      entity_id: '{{ garagedoorsopen }}'
  - service: notify.mobile_app_weston
    data:
      title: GARAGE DOOR WARNING! (AWAY CLOSURE)
      message: The following doors were closed:{{ garagedoorsopenname |join('\n- ') }}
mode: single
variables:
  garagedoorsopen: |
    {{ states.cover
      |selectattr('state', 'eq', 'open') 
      |map(attribute='entity_id')
      |list }}
  garagedoorsopenname: |
    {{ expand([garagedoorsopen])
      |map(attribute='name')
      |list }}

Where do you go to learn any of this? Is this python?, I feel like I don’t even know what all, at least on the programming side, this thing is capable of so then when someone like yourself gives a few ideas of what could be done to complete a task (when you called out using a loop, my head spun, I’ve never used a loop in my life), it feels worthless to me because I don’t even know where to begin with it. I guess I was hoping someone could give me examples of how to use some of the concepts that could get my automation accomplished. I could careless if they do it for me verbatim, but I wouldn’t turn down, “here is an example of how to do this part of it” etc. etc.

1 Like

No worries! So you switched locks to garage doors on me, is this a previous automation you made or did you just put this together now? Either way its actually really close. I actually forgot you don’t really need a loop for this task because you can just pass a list of entity IDs to the service in like you are doing above.

To change what you’re showing to the door lock example we actually just need a few tweaks like this:

alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Doors lock when Away
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
action:
  - choose:
      - alias: Doors are open
        condition: "{{ open_doors | count > 0 }}"
        sequence:
          service: notify.mobile_app_weston
          data:
            title: DOORS ARE OPEN
            message: "The following doors are open: {{ open_doors | join('\n- ') }}"
      - alias: Doors are unlocked and closed
        condition: "{{ unlocked_closed_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE UNLOCKED (AWAY LOCK)
              message: "The following doors were left unlocked: {{ unlocked_closed_doors | join('\n- ') }}"
          - service: lock.lock
            target:
              entity_id: "{{ unlocked_closed_doors }}"
mode: single
variables:
  open_doors: |
    {{ expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | map('replace', 'binary_sensor.', 'lock.')
      | map('regex_replace', '$', '_lock')
      | list
    }}
  unlocked_closed_doors: |
    {{ states.lock
      | selectattr('state', 'eq', 'unlocked') 
      | map(attribute='entity_id')
      | reject('in', open_doors)
      | list }}

This honestly isn’t that different. The few differences are:

  1. There’s two “bad states” now. A door can be unlocked but closed and a door can be flat open. So for that I switched to a choose model instead of a single condition.
  2. The open_doors template is more complicated. This is because you said you wanted to have it flexible so if you add more locks/doors it just works. And it appears the only way to find the binary sensor from the door lock is by parsing the entity ID. So I get a list of all locks, manipulate the entity ID to turn it into the binary sensor, check if its open and then manipulate it back into the lock ID. It works but that’s what I was trying to say from this paragraph

I didn’t mean to say “oh its so obvious”, sorry if it came off that way. More just that looking at your use case the only way to go from the door lock to the binary sensor is by manipulating the strings to turn lock.front_door_lock into binary_sensor.front_door and vice versa. I was suggesting alternative approaches if you didn’t like that it relied on string manipulation and diligence when assigning IDs to your future door entities.

Also feel free to add any other triggers you want. The actual automation actions don’t rely on the trigger information at all. So if you want to be notified about open and unlocked doors at 10PM just add a time trigger in addition to the away from home trigger.

Fair point. It’s not python no but it does definitely have some programming concepts. I am a programmer so I am familiar with a lot of those but still just took a lot of time and practice getting the hang of it. I guess I’d say to really learn it your best friends should be:

  1. Templates tab in dev tools. I basically still punch in every template I use here and use it as a sandbox all the time. I have a lot memorized but there’s a lot of gotchas.
  2. Scripts tab in settings. I make little test scripts all the time just to try out configurations for actions. Run them, see if it works, copy it over to my automation and delete them.
  3. Traces. I can’t link to these but honestly these are incredible. Don’t forget about these, they show exactly what happened and exactly what information was available in variables every step of the way. This addition has completely changed HA for me, it made learning and debugging so much easier.

As for loops, essentially you repeat a series of actions for each item in a list. That’s why I was suggesting it here since you could loop over a list of doors (like you made in your variable) and then call the lock.lock and notify.mobile_app_weston services for each. But tbh you showed a more efficient way to do it then a loop so in this case it wasn’t necessary.

EDIT: Also sorry about this one | map('regex_replace', '$', '_lock'). I really tried to avoid regexes but I couldn’t think of any other way to put _lock on the end of each string in the list. It’s a bit of a frustrating gap. For reference the $ symbol in a regex means “end of the line”. So essentially all that does is add _lock to the end of each item.

Mike,

I’m sorry for coming off like a baby, please do this for me type. That really wasn’t my intent at all but I get how it looked like that for sure. I have edited some of the wording in my first post to better show my true view/ outlook.

I have attempted to review your post and have some added information below so you’ll know where I’m coming from and maybe can add some info where I am lacking.

Well, it’s just I felt comfortable building the automation on the garage door because I only have 1 entity I was dealing with. As soon as I had 2 that I needed to work together (a lock and a door’s contact sensor), I didn’t know what to do. So yeah, this was my attempt at the garage door. It was one that had been built in the last little bit. As I’m sure you can tell, I’m new to home assistant. I moved over from smartthings because I felt like I was missing out on some things, ok, I’ll be honest, many things, that HA was more capable of. I wasn’t expecting such a learning curve but I think it’s like that comment of “With great power, comes great responsibility” haha.

Thank you for helping me with this. Over the next few days, with free time, I will review in totality and come back with any questions if you don’t mind.

I can already think of a few questions but just don’t have the time to type them right at the moment. I’m sure you will be able to answer them in 1 second a piece. haha.

I’m so surprised after looking at your code (what I understand of it at least); there are definitely some pieces I don’t know what they’re doing/ understand. But I’ll admit, I’m surprised you could use so much or my garage door automation as a base.

This makes sense and I understand completely. I luckily have used “choose” and believe it is what I called out in the pseudo code.

This is where you really helped me and I wouldn’t have figured out at my current skill level is what you did within the variables.

Thank you for explaining this so easily. I don’t quite understand why it works (I mean, is it counting the number of “ons” produced by this manipulation? Why do we convert it back? Would it hurt other things if we just stopped after the selectattr line and went to |list? Are these variables only local to this automation? Is there a way to make variables global across HA (or is that what packages and template sensors are for?) but I do understand what you are physically doing.-- Sorry for the 100 questions here, it just got my brain spinnin.

Up until this point, all I have used is “selectattr” and “rejectattr” “list” and “join”, I follow you on ‘replace’ and ‘regex_replace’ but had never used them.

I understand your words on the area idea and agree but don’t feel like I know how to do it, Very similar on your concepts about customization, I follow your words but have never used the customization idea—> do you have any examples of this nearby, this sounds like it could be useful and I would like to see/ understand this one. Yeah, I could tell you don’t like to use regex, is that because it’s kind of “hacky programming”

I follow you. I was giving you a little bit of a hard time. There are alot of developers on the forums here and I have seen you come up in a lot of post utilizing your skill/ talent. Sometimes I feel like I am a fish out of water in HA because I’m not a programmer/ developer and I know some of the most impressive stuff takes that quality of skillset to make HA shine. IT’s the concept of I know what I want to do, logically at least, but it’s the doing it is where I struggle. And yeah, I don’t care much for having to go the string manipulation route but beggars can’t be choosers either and I don’t have the ability to do otherwise just yet so it will have to stay as it is. – But thinking about this a little more and what I understand of your other ideas, they all seem to have pros and cons with regards to manual setup. —>My biggest goal was to make sure I didn’t have to go in and make a bunch of manual changes to files anytime I added a new door lock etc. and the solution you helped me with has done that trick. The only thing I do wander about is what would happen if I add a door lock to another door but not a door sensor? (I don’t expect this to happen, but would it break the whole thing?)

Yeah, this is awesome. The heavy lifting is done! Thank goodness!!

I knew it!!! No chance that you weren’t. haha.

Thank you for this. I would rather learn this way than-- you put this here and you put this here and it works.

I follow, I have used this a little with the selectattr stuff

I’ve never written a script but they seem like they would be useful for pieces of code that you know you will use over and over. So then your actions section of the automation, you just call the script? Can scripts be use in the triggers/ conditions? or does that make no sense?

I tried to use this sections on an automation and thats when I learned that triggers were default as ors and conditions were ands. Drove me nuts.
Are there any plans to be able to use variables in triggers at any point? Or is that another thing that makes no sense?

Not possible, I am still lost. jk.

Thank you for this, also I hope you caught the comment about this subject earlier in this post, I know it is long, sorry… Because I would like to hear your views on that portions.

Hmm. I just copy-pasted the automation you helped me with and when I try to save, I am getting:
Message malformed: extra keys not allowed @ data[‘action’][0][‘choose’][0][‘condition’]
Everything I am reading is saying indentation more than likely but I’m not seeing it.
Here is my paste and screenshot:

alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Doors lock when Away1
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
action:
  - choose:
      - alias: Doors are open
        condition: "{{ open_doors | count > 0 }}"
        sequence:
          service: notify.mobile_app_weston
          data:
            title: DOORS ARE OPEN
            message: "The following doors are open: {{ open_doors | join('\n- ') }}"
      - alias: Doors are unlocked and closed
        condition: "{{ unlocked_closed_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE UNLOCKED (AWAY LOCK)
              message: "The following doors were left unlocked: {{ unlocked_closed_doors | join('\n- ') }}"
          - service: lock.lock
            target:
              entity_id: "{{ unlocked_closed_doors }}"
mode: single
variables:
  open_doors: |
    {{ expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | map('replace', 'binary_sensor.', 'lock.')
      | map('regex_replace', '$', '_lock')
      | list
    }}
  unlocked_closed_doors: |
    {{ states.lock
      | selectattr('state', 'eq', 'unlocked') 
      | map(attribute='entity_id')
      | reject('in', open_doors)
      | list }}

You’re missing a dash.

      - alias: Doors are open
        condition: "{{ open_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE OPEN
              message: "The following doors are open: {{ open_doors | join('\n- ') }}"

the service is a list of the sequence.

The issue still seems to exist even after adding the recommended dash.
Now the code is:

alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Doors lock when Away
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
action:
  - choose:
      - alias: Doors are open
        condition: "{{ open_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE OPEN
              message: "The following doors are open: {{ open_doors | join('\n- ') }}"
      - alias: Doors are unlocked and closed
        condition: "{{ unlocked_closed_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE UNLOCKED (AWAY LOCK)
              message: "The following doors were left unlocked: {{ unlocked_closed_doors | join('\n- ') }}"
          - service: lock.lock
            target:
              entity_id: "{{ unlocked_closed_doors }}"
mode: single
variables:
  open_doors: |
    {{ expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | map('replace', 'binary_sensor.', 'lock.')
      | map('regex_replace', '$', '_lock')
      | list
    }}
  unlocked_closed_doors: |
    {{ states.lock
      | selectattr('state', 'eq', 'unlocked') 
      | map(attribute='entity_id')
      | reject('in', open_doors)
      | list }}
alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Doors lock when Away
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
action:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ open_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE OPEN
              message: "The following doors are open: {{ open_doors | join('\n- ') }}"
      - conditions:
          - condition: template
            value_template:  "{{ unlocked_closed_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE UNLOCKED (AWAY LOCK)
              message: "The following doors were left unlocked: {{ unlocked_closed_doors | join('\n- ') }}"
          - service: lock.lock
            target:
              entity_id: "{{ unlocked_closed_doors }}"
mode: single
variables:
  open_doors: |
    {{ expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | map('replace', 'binary_sensor.', 'lock.')
      | map('regex_replace', '$', '_lock')
      | list
    }}
  unlocked_closed_doors: |
    {{ states.lock
      | selectattr('state', 'eq', 'unlocked') 
      | map(attribute='entity_id')
      | reject('in', open_doors)
      | list }}

Any chance you can have each pair of entities share the same object_id?

binary_sensor.front_door
lock.front_door

binary_sensor.back_door
lock.back_door

binary_sensor.garage_entry_door
lock.garage_entry_door

The additional “_lock” you currently have appearing at the end of each lock’s object_id complicates the template needed to determine which doors are closed but unlocked (determining if a closed door is locked/unlocked means checking the door’s associated lock entity). The template is simplified if the paired entities have the same object_id.

I don’t guess I would mind it because I do see what you are saying but I would ask the question, if I change the entity id of the locks and I already have them in other automations at the entity level, will I have to go into every automation and update the entity? What if I have them already in other automations but tied into the area level instead?

lock.whatever is different from lock.whatever_lock so all existing references to an entity will be broken if you change its entity_id.

If updating all existing references to the three lock entities is too onerous then you’ll have to live with a more complicated template.

Out of curiosity, does every door in your system have an associated lock or only some doors? Because this bit here suggests only some doors have locks (otherwise you would have filtered on device_class instead of using replace to massage the entity_id) :

expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))

I successfully tested a similar version of the following automation in my home.

  • It reports if any doors were left open (listing them by their friendly_name) using appropriate grammar (“door is open” or "doors are open’ depending on quantity).
  • For all closed but unlocked doors, it locks their lock.
  • It reports the locks it locked by their friendly name.

It makes the following assumptions:

  1. All lock entities it finds have a corresponding binary_sensor representing a door
  2. The object_id of all lock entities ends with _lock
alias: 'Example of door and lock monitor'
trigger:
- platform: time
  at: '22:00:00'
- platform: state
  entity_id: group.family
  from: 'home'
  to: 'not_home'
  for: '00:00:10'
condition: []
action:
- variables:
    doors: >
      {{ states.lock | map(attribute='object_id')
        | map('regex_replace', '(^.*)_lock$', 'binary_sensor.\\1') | list }}
    open_doors: >
      {{ expand(doors) | selectattr('state', 'eq', 'on')
        | map(attribute='name') | list }}
    closed_doors_unlocked: >
      {{ expand(expand(doors) | selectattr('state', 'eq', 'off')
        | map(attribute='object_id')
        | map('regex_replace', '(^.*$)', 'lock.\\1_lock') | list)
        | selectattr('state', 'eq', 'unlocked')
        | map(attribute='entity_id') | list }}
- if: '{{ open_doors | count > 0 }}'
  then:
  - service: notify.mobile_app_weston
    data:
      title: DOORS ARE OPEN
      message: "The following door{{ iif(open_doors | count > 1, 's are', ' is') }} open: {{ open_doors | join('\n- ') }}"
- if: '{{ closed_doors_unlocked | count > 0 }}'
  then:
  - service: lock.lock
    target:
      entity_id: '{{ closed_doors_unlocked }}'
  - service: notify.mobile_app_weston
    data:
      title: DOORS WERE LEFT UNLOCKED (AWAY LOCK)
      message: "Locked the following: {{ closed_doors_unlocked | map(attribute='name') | list | join('\n- ') }}"

It employs two consecutive if statements because a choose cannot execute more than one of its options (i.e. it only executes the first option that evaluates to true).


EDIT

Correct typo.

This fixed it. Thank you!!

In my instance all doors that have a lock, also have a binary contact sensor on them.
So, I would be lying to you if I said I knew what I was doing. I know very little programming and it’s one of those, I’m doing the best I can do at my ability level.

Could you show me what you mean by this in a short example?

Thank you for showing me this automation as something to learn from. This is the only way I’m going to get better at this stuff. I tend to do well with examples of things. That’s really cool on the proper grammar situation. I have now read the rest of your post, this is great. Thank you so much for showing me this! Thank you again @123

Assuming all the binary_sensors that represent doors have their device_class set to door, you can use the following template to report a list of all entity_id’s of doors.

{{ states.binary_sensor
  | selectattr('attributes.device_class', 'defined')
  | selectattr('attributes.device_class', 'eq', 'door')
  | map(attribute='entity_id') | list }}

This would report only closed doors.

{{ states.binary_sensor
  | selectattr('attributes.device_class', 'defined')
  | selectattr('attributes.device_class', 'eq', 'door')
  | selectattr('state', 'eq', 'off')
  | map(attribute='entity_id') | list }}

I understand these examples, thank you for them.

@123 @calisro

So, I ended up screwing up and got a message this morning which was the first test of the messaging of the below automation (same one we have discussed on this thread)

I endedup up learning that there have been three shadow locks created on my home assistant setup by a integration/ add in called keymaster.-- It helps set door code schedules etc.

Their naming conventions are as below. From my understanding they essentially mirror the actual lock position. They’re entity ids are named as below (I ended up find this out because they got listed in the push notification also). So this is really what my home assistant instance had with regards to locks and door contact sensors.

Lock entities:
lock.front_door_lock
lock.back_door_lock
lock.garage_entry_door_lock
lock.boltchecked_front_door
lock.boltchecked_back_door
lock.boltchecked_garage_entry

**I am willing to change the name of the boltchecked ones if completely necessary.

contact sensor that I have placed on the doors:
binary_sensor.front_door
binary_sensor.back_door
binary_sensor.garage_entry_door

1.) Is there a way to ignore entities with “boltchecked” in the entity id in the below code? I don’t fully understand the below code but I understand most of it. (I think it may be causing duplication in both sides of the choose action.

2.) Additionally is there a way to have the below code send the “friendly name” in the notification rather than the entity ids.

3.) Lastly and probably more importantly, will this code work properly if both sides of the choose need to be executed? As is, if I have a door open in the house AND I have a door closed but unlocked. Will this report to me both of those issues?

@123 Am I better off switching to your code? Or do you think the below is fixable without a ton of effort. #3 above concerns me if it is the opposite of what we would prefer.
CODE EDITED 6-9-22 12:30 PM

alias: (ACTION- AUTOMATIC- SECURITY- NOTIFICATION) Doors lock when Away
description: ''
trigger:
  - platform: state
    entity_id:
      - group.family
    from: home
    to: not_home
action:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ open_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE OPEN
              message: "The following doors are open: {{ open_doors | join('\n- ') }}"
      - conditions:
          - condition: template
            value_template:  "{{ unlocked_closed_doors | count > 0 }}"
        sequence:
          - service: notify.mobile_app_weston
            data:
              title: DOORS ARE UNLOCKED (AWAY LOCK)
              message: "The following doors were left unlocked: {{ unlocked_closed_doors | join('\n- ') }}"
          - service: lock.lock
            target:
              entity_id: "{{ unlocked_closed_doors }}"
mode: single
variables:
  open_doors: |
    {{ expand(states.lock
      | map(attribute='entity_id')
      | map('replace', 'lock.', 'binary_sensor.')
      | map('replace', '_lock', ''))
      | selectattr('state', 'eq', 'on')
      | map(attribute='entity_id')
      | map('replace', 'binary_sensor.', 'lock.')
      | map('regex_replace', '$', '_lock')
      | list
    }}
  unlocked_closed_doors: |
    {{ states.lock
      | selectattr('state', 'eq', 'unlocked') 
      | map(attribute='entity_id')
      | reject('in', open_doors)
      | list }}

Like I explained in my previous post, I used two consecutive if to avoid the situation you have encountered with choose. In addition, the version I posted already reports the entity’s friendly name.

Yes, it’s possible to modify the template so it rejects any object_id containing the word “boltchecked”. However, the resulting template increases in complexity so it may be more efficient to use the other technique I mentioned. Do all three binary_sensor entities, representing your doors, have a device_class attribute set to door?

If they don’t, it can be added manually however that might break one of the rules you stipulated in your first post (where newly added doors and locks are automatically handled by the automation).