Is webhooks the right answer for multi-garage door automation?

fwiw, using a trigger based template makes it restore state, and thus survive restarts.

using this myself for the last door (and various other variations)

template:

  - trigger:  #needs fix

      - trigger: state
        entity_id:
          - binary_sensor.achter_deur
          - binary_sensor.gang_deur
          - binary_sensor.voor_deur
          - binary_sensor.garage_binnen_deur
          - binary_sensor.garage_deur
          - etcetc
        from: 'off'
        to: 'on'

    sensor:

      - unique_id: last_time_door_triggered
        state: >
          {{as_local(states[trigger.entity_id].last_changed).strftime('%X')}}
        attributes:
          history: >
            {%- set previous = this.attributes.history|default([]) %}
            {%- set new = [this.attributes.last_area|default('nowhere') ~
              ': ' ~ this.state] %}
            {{previous[-4:] + new}}
          last_area: >
            {{area_name(trigger.entity_id)}}

      - unique_id: last_door_triggered
        state: >
          {{state_attr(trigger.entity_id,'friendly_name').split(' deur')[0]}}
        attributes:
#           history: >
#             {%- set what = states[trigger.entity_id].name %}
#             {%- set at = states[trigger.entity_id].last_changed.strftime('%X') %}
#             {%- set previous = this.attributes.history | default([]) %}
#             {%- set new = [what + ': ' + at] %}
#             {{ new + previous[:4]}}
          last: >
            {% set stamp =
               as_local(states[trigger.entity_id].last_changed).strftime('%X') %}
            {% set id =
               state_attr(trigger.entity_id,'friendly_name').split(' deur')[0] %}
            {{id ~ ': ' ~ stamp}}
          history_1: >
            {{this.attributes.last|default('Nog niet bepaald')}}
          history_2: >
            {{this.attributes.history_1|default('Nog niet bepaald')}}
          history_3: >
            {{this.attributes.history_2|default('Nog niet bepaald')}}
          history_4: >
            {{this.attributes.history_3|default('Nog niet bepaald')}}
          history_5: >
            {{this.attributes.history_4|default('Nog niet bepaald')}}
          entity_id: >
            {{trigger.entity_id}}
          last_triggered: >
            {{trigger.to_state.last_changed.isoformat()}}
          last_area: >
             {{area_name(trigger.entity_id)}}

as you can see there is a history attribute, which if you don’t care about that, you can simply delete. Or are shorter.

Time is recorded too, as is Area :wink:
no need to use an intermediary text helper either.

Maybe you can use it.

I thought i recognized your name @pnbruckner! Your Life360 integration is awesome! I was waiting so long for that to come back around after it stopped working. Thank you so much for the effort there.

As for this topic, I have created the automation and will be testing it tomorrow. I will report back how it goes.

For anyone reading. This is what is in place currently:

Developer Tools → Template

{% set doors = [
  states.cover.ratgdov25i_1be829_door,
  states.cover.ratgdov25i_1be833_door
]
%}
{% set last_door = (doors|sort(attribute="last_changed"))[-1] %}
ratgdov25i_1be829_door: {{ states.cover.ratgdov25i_1be829_door.last_changed|as_local }}
ratgdov25i_1be833_door: {{ states.cover.ratgdov25i_1be833_door.last_changed|as_local }}

last changed: {{ last_door.entity_id }}

Settings → Automations and Scenes

alias: Garage - Save last door used
description: ""
triggers:
  - trigger: state
    entity_id:
      - device_tracker.life360_carmen
      - device_tracker.life360_genevieve
    from: home
    to: not_home
actions:
  - action: input_text.set_value
    target:
      entity_id: >-
        input_text.door_{{
        trigger.entity_id.removeprefix('device_tracker.life360_') }}
    data:
      value: >
        {% set doors = [
            states.cover.ratgdov25i_1be829_door,
            states.cover.ratgdov25i_1be833_door
          ]
        %} {% set last_door = (doors|sort(attribute="last_changed"))[-1] %} {{
        last_door.entity_id }}


alias: Garage - Open saved door
description: ""
triggers:
  - trigger: state
    entity_id:
      - device_tracker.life360_carmen
      - device_tracker.life360_genevieve
    from: not_home
    to: home
    enabled: true
actions:
  - action: cover.open_cover
    target:
      entity_id: >-
        {{ states('input_text.door_' ~
        trigger.entity_id.removeprefix('device_tracker.life360_')) }}

I edited this to show all the automations and templates. I missed the one that stored the info when you “Leave”

1 Like

Well. When my girl came home it triggered and errored.

This was from the log:

Triggered by the state of device_tracker.life360_genevieve at December 10, 2024 at 5:51:14 PM

Perform action 'Cover: Open' on templated entities

Stopped because an error was encountered at December 10, 2024 at 5:51:14 PM (runtime: 0.00 seconds)

Template rendered invalid entity IDs: unknown

Did you create the text helpers, one for each device tracker? Did they leave first so the first automation could set the values of the helpers?

Did not create a text helper. I started reading on the how and then got caught up in the template and automation, that I never went back.

Which makes more sense now as I read through your YAML i kept thinking, how does it “know” which to choose, but was more concerned with getting through the UI errors and getting what we have thus far to just save.

Do I create a text helper for each door? Person? Or is it just one?

name: last_door
EntityID: input_text.last_door

The automation code I provided so far assumes each person is monitored via a Life360 device tracker (i.e., the entity IDs start with “device_tracker.life360_”), and there is a text helper for each, where the helper’s entity ID suffix is the same as the suffix on the corresponding device tracker.

So, e.g., “input_text.door_person1” records the door that “device_tracker.life360_person1” last used, “input_text.door_person2” is for “device_tracker.life360_person2”, etc.

If you use some other types of entities to monitor the people (e.g., person entities), or from some other device tracker integration where the entity ID naming convention is different, then the automations would have to adjust accordingly.

Also, as I said, there is no error checking/handling built into the automations. They assume a perfect world, which of course, never happens.

I added the following helper to test:


name: door_carmen
EntityID: input_text.door_carmen

My life 360 device tracker is:


device_tracker.life360_carmen

Will give this a go today.

1 Like

Holy Shit!

It worked @pnbruckner

I left 4 hours ago, upon returning home it opened the garage door I used when leaving!

This is so badass! I have been wanting this level of automation for years since playing with Smart-things w/ WebCore before it sucked.

I go look at my text helper and it shows the garage door entityid i last triggered when i left. So badass! I need to have it trigger tomorrow morning when my girl leaves and validate her entry is added.

Now from a use case perspective. If we both leave in one car, then both of us would have that as the last door triggered for each of us, so single door will open upon our return. We leave with different doors, each of us would get our doors entry correct unless we left at the exact same time as then whichever was last triggered would appear if i am thinking that correctly.

This is so amazing. I am so stoked!!

1 Like

would be nice if you posted the full yaml for the ‘it’ that made it happen :wink:
dont see myself automating the garage door opening because of security considerations, but I do like to learn the system behind it

1 Like

Post 22(?) has all the code used to make this work

It has the template as well as the two automations.

Post 26(?) has the Text Helper needed to store the variables when someone leaves and then recall them upon returning

1 Like

a right, sorry.
I fguren those were using some pseudo code with the removeprefix('') function, but it’s clear what they do there.

I’ll have a look at them, thanks for posting

Hi @Mariusthvdb everything on the code side is @pnbruckner, i just copied and pasted his stuff.

I am using this to get a better understanding of these more complicated concepts in HA. When i read it is makes perfect sense. I will use this as my baseline for other more complicated tasks leveraging Templates and Helpers.

As for this mornings update, my girl left and her text helper stored the value properly. :+1:

1 Like

That’s valid Python.

1 Like

LOL! I used that before switching to HA over six years ago. WebCore definitely had potential, but also a lot of bugs.

Yep. That’s where this changes from playing/hacking into Software Engineering! :rofl: To make automations/scripts robust, you really have to do a lot of “what if” thinking.

E.g., in your use case of two people leaving together, yes, if they also come back together, the same door would be opened … but maybe twice! You may have noticed that it can take some time for the Life360 device trackers to update, and it’s not always consistent. So, let’s say one tracker entity changes, causing the door to open. Then you park the car and close the garage door. Now the other tracker entity updates, and the door opens again! A robust automation would handle that (e.g., only opening the door if it hasn’t recently opened.)

One thing I do with my Life360 tracker entities is to call the life360.update_location service (er, action) when it gets close to home (and is getting closer, as opposed to close but going away.) This should cause the entity to update more quickly (for about a minute), which can make doing things like opening garage doors happen more timely.

Is there a way to change the polling interval generally for the Life360.update.location. I assume that is how it works, HA polls Life360 for changes on a set interval.

Heck yes. That is so nice! I wish I had known about this years ago….

I have heaps of places where these type of id trims are required and always first get to the id by looking for the object_id , split /replace this or that and inject it into another template.

This is way more elegant.
Today I really learned.

Thanks for educating me !

edit: link to the official Python documentation Built-in Types — Python 3.13.1 documentation

Basically, most of the objects/variables in a template are Python objects, and therefore, you can use whatever methods those objects provide. A string is a Python str object, and has all the methods of the str type. Same thing with lists, tuples, etc.

1 Like

The Life360 integration does poll the Life360 server on a regular basis (every five seconds for each entity) and that interval cannot be changed (without modifying the code.)

In theory, though, you can set the integration to not poll and then use the standard homeassistant.update_entity action to force the poll when you want (typically with an automation that triggers at the rate you want.) I say, “in theory”, because that’s how it’s supposed to work, but I haven’t verified that (in a while. But it should work.)

Note that when the HA integration polls the Life360 server, it’s just requesting the latest data available for the device/phone. That is completely independent of how often / when the device/phone updates the Life360 server with its current location. That is controlled by the Life360 app on the device/phone, and it tends to update more frequently when the device is moving, and less frequently when it is relatively stationary. It also updates more frequently when the Life360 app is opened on the phone. In fact, all the Members in the current Circle tend to update more frequently when the app is opened on any of the devices in that Circle.

The life360.update_location action, on the other hand, asks the Life360 server to ask the Life360 device/application (on the phone) to update itself. It is somewhat equivalent to opening the app on the phone. The result of this action is typically that the device updates itself every five seconds for about one minute.

So, to summarize, there are two different things going on.

The first is the Life360 app on the device updating the Life360 server with its location. When and how often that happens depends on a lot of things, and one way to make it happen more frequently is to use the HA integration’s life360.update_location action.

The seconds it the HA Life360 integration polling the Life360 server for the latest available data. That normally happens every five seconds, but by using the homeassistant.update_entity action you can make it happen more or less often (if you also disable polling for the integration), but that is often not necessary.

Didn’t know it polled every 5 seconds, i thought it was 30, so that is more than enough than what I need :slight_smile:

I added this as a catch incase it triggers in an unattended manor.

- delay:
      hours: 0
      minutes: 1
      seconds: 30
      milliseconds: 0
  - action: cover.close_cover
    target:
      entity_id: >-
        {{ states('input_text.door_' ~
        trigger.entity_id.removeprefix('device_tracker.life360_')) }}

Again, HA polls the Life360 server every 5 seconds, but most of the time there is no new data, so the entity does not update. Check the last_seen attribute. That will tell you when the location actually updated last (all the way from the phone.)

Here is an example of how often the Life360 tracker entities update in my system:

image

These are template sensors that indicate the “age” of the update (based on subtracting the value of the last_seen attribute from the current time.)

If you want the location (known to the Life360 server) to update more often than it naturally does, you need to either open the Life360 app on the phone, or use the life360.update_location action.

And if a second person arrives home 1 min and 20 sec after the first person arrives (and they left via the same door, similar to our previous discussion), …

You’re thinking in the right direction, but there are a LOT of possible event sequences to consider. I think you mostly have it from here. Good luck and have fun! Feel free to ask more questions. Happy to help.