How to make a real safe "coming home" automation

Hi,
I’m thinking about how to make a secure “coming home” automation for maybe opening the front door with nuki and stuff.

For that, I would like to use the presence detection (Ubiquiti and Fritzbox work quite good for me). My concern is my cell phone losing wifi for a couple of minutes (maybe after an Android update at night), reconnecting to wifi and making hass.io thinking I just came home, opening the front door at night. Not good.

So my plan is placing a button near the front door. Every time I leave the house I would press it, setting the absence state to maybe “really_away” and using that in the automation (from: really_away to: home).

  1. Do you guys have any better idea on how to achieve a really secure presence detection?
  2. (How) can I set a state live “really_away” manually, which will then be updated by presence detection with only “home” and not with any other status?

Thanks!

I won’t comment on the “really safe” part. This is open source stuff with no guarantees.

But I have a suggestion: Use an input_boolean. Have an automation change it to ‘on’ when you push the button, and another automation that changes it to ‘off’ with whatever presence-based triggers you think best. Then, the automation that unlocks the door would be triggered by the input_boolean changing to ‘off’.

Or a slightly different tack on the same theme. Have the input_boolean’s initial state as ‘off’. Then have an automation that turns it ‘on’ when you push the button. Then the automation that unlocks the door will use, again, whatever presence-based triggers you think best, but add a condition that the input_boolean must be ‘on’. Then, in addition to unlocking the door, have it turn the input_boolean ‘off’.

1 Like

I am watching a Reed Sensor on my front door. It’s an Xiaomi Door Sensor like this.
If it changes I am checking the device_tracker component so see if the user really leaves in the next 10 minutes. Same for coming home but in reverse:

import appdaemon.plugins.hass.hassapi as hass
import messages
import globals
import datetime 
#
# App to toggle an input boolean when a person enters or leaves home.
# This is determined based on a combination of a GPS device tracker and the door sensor.
#
# - If the door sensor opens and the device_tracker changed to "home" in the last self.delay minutes this means someone got home
# - If the door sensor opens and the device_tracker changes to "not_home" in the next self.delay minutes this means someone left home
#
# Args:
#
# input_boolean: input_boolean which shows if someone is home e.g. input_boolean.isHome
# device_tracker: device tracker of the user to track e.g. device_tracker.simon
# door_sensor: Door sensor which indicated the frontdoor opened e.g. binary_sensor.door_window_sensor_158d000126a57b
# Release Notes
#
# Version 1.0:
#   Initial Version

class IsUserHomeDeterminer(hass.Hass):

    def initialize(self):
        self.listen_state_handle_list = []
        self.timer_handle_list = []

        self.delay = 600

        self.input_boolean = globals.get_arg("input_boolean")
        self.device_tracker = globals.get_arg("device_tracker")
        self.door_sensor = globals.get_arg("door_sensor")
        
        self.listen_state_handle_list.append(self.listen_state(self.state_change, self.door_sensor))
    
    def state_change(self, entity, attribute, old, new, kwargs):
        if new != "" and new != old:
            self.log("{} changed from {} to {}".format(entity,old,new), level = "DEBUG")
            if new == "off" and old == "on":
                device_tracker_state = self.get_state(self.device_tracker, attribute = "all")
                self.log("device_tracker_state: {}".format(device_tracker_state), level = "DEBUG")
                last_changed = device_tracker_state["last_changed"]
                self.log("last_changed: {}".format(last_changed))
                #User got home: Device tracker changed to home before door sensor triggered
                if device_tracker_state["state"]  == "home" and (datetime.datetime.now(datetime.timezone.utc) - self.convert_utc(last_changed) ) < datetime.timedelta(seconds=self.delay):
                    self.log("User got home")
                    self.turn_on(self.input_boolean)
                #User got home: Device tracker is still not home. Wait if it changes to home in the next self.delay seconds
                elif device_tracker_state["state"]  != "home":
                    self.log("Wait for device tracker to change to 'home'")
                    self.timer_handle_list.append(self.run_in(self.check_if_user_got_home,self.delay))
                #User left home: Device tracker is still home.  Wait if it changes to home in the next self.delay seconds
                elif device_tracker_state["state"]  == "home":
                    self.log("Wait for device tracker to change to 'not_home'")
                    self.timer_handle_list.append(self.run_in(self.check_if_user_left_home,self.delay))

    def check_if_user_left_home(self, *kwargs):
        device_tracker_state = self.get_state(self.device_tracker, attribute = "all")
        self.log("device_tracker_state: {}".format(device_tracker_state), level = "DEBUG")
        if device_tracker_state["state"]  != "home":
            self.log("User left home")
            self.turn_off(self.input_boolean)

    def check_if_user_got_home(self, *kwargs):
        device_tracker_state = self.get_state(self.device_tracker, attribute = "all")
        self.log("device_tracker_state: {}".format(device_tracker_state), level = "DEBUG")
        if device_tracker_state["state"]  == "home":
            self.log("User got home")
            self.turn_on(self.input_boolean)

    def terminate(self):
        for listen_state_handle in self.listen_state_handle_list:
            self.cancel_listen_state(listen_state_handle)

        for timer_handle in self.timer_handle_list:
            self.cancel_timer(timer_handle)
1 Like