Objective

After a local company installed garage doors during contruction of our house, I noticed that the remote had such a weak range that they wouldn’t even work when I was right in front of the garage, let alone from inside my car.

I needed a quicker and more reliable way of opening the garage. In provided documentation I’ve noticed that shorting two pins on connector of the garage motor toggles opening and closing. So, I hooked up a Shelly relay to make this happen, set to briefly short the pins when I hit a button on a wall switch or in Home Assistant, and then disconnect. I also set it up to repeat the closing action after 30 seconds, giving me time to park or leave.

I added a button to the Home Assistant app to replace the old remote with my phone. This was great at first, but it got annoying to unlock my phone and open the app every time I wanted to open the garage. To fix this, I stuck NFC stickers on the dashboards of our cars, making it super easy to just tap as I drove up to the house.

This setup was all good until one time after a vacation, our neighbors let us know our garage had been wide open for days. Turns out, I had accidentally hit the ‘open’ button in Home Assistant and forgot to close it (the other button that doesn’t close it after 30 seconds). To stop this from happening again, I improved the system to alert me if the garage was left open while we were out.

After a few years, it was time for my ultimate goal: fully autonomous garage door. The final setup opens the garage as the car approaches our home and closes when the car turns off. Before I drive off, the garage opens as soon as I unplug the charger and put the car in gear. This automation only works with my newer car, because it supports realtime collection of data via API. For the older one, I’m still using the NFC tag.

Hardware and Integration with Home Assistant

The ESPHome flashed Shelly 1PM WiFi relay is used to short the pins on garage motor for a short period.

The garage door status is monitored using the Mi Window and Door Sensor, though similar sensors that can report both open and closed states can also be used.

Cheap NFC stickers can be bought from Aliexpress.

For full automation of the garage, the data is collected from Tesla using the Home Assistant integration. Although this integration gathers all the necessary data (geolocation, destination in navigation, current gear), it only refreshes every 10 minutes. This is obviously way to slow, therefore I needed to collect the data in real-time. This is achieved using project TeslaMate, which I installed on a home server. I then brought the data from TeslaMate into Home Assistant via the first integration. With this method, data arrives in Home Assistant in three seconds.

Automation Logic - Manual Methods

To operate the garage doors, the following methods are available:

  1. Button in Home Assistant app
  2. NFC sticker in the car
  3. Wall switch

Each method triggers a Home Assistant automation that:

  • Opens the garage if closed, waits 30 seconds, then toggles it again to close.
  • Directly closes the garage if already open, avoiding the unwanted cycle of closing and reopening.

Home Assistant automation for opening a garage for 30 seconds

Notifications are essential for monitoring the garage’s status, especially when away. If the garage remains open for over 10 minutes while all family members are away, a notification is sent via Telegram.

Automation that handles Telegram notification:

Notification example:

Automation Logic - Automatic Mode

For garage to open, the following conditions must be satisfied (function car_got_home()):

  1. The car entered a home zone in Home Assistant.
  2. The carโ€™s navigation set to home as the destination. This conditions prevents opening when just passing by.
  3. The garage door is currently closed.

The automation then waits for the car to shift into park before closing the garage.


For departure, the following must happen or be true to open the garage:

  1. The car is currently at the home location.
  2. The car was disconnected from the charger.
  3. The car’s gear shifted to drive.

The garage then closes 20 seconds after opening.


Full appdaemon app:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import appdaemon.plugins.hass.hassapi as hass
import datetime

class AutoGarage(hass.Hass):
    def initialize(self):
        self.listen_state(self.car_got_home, 'device_tracker.tesla_location_tracker', new='home')
        self.listen_state(self.car_was_unplugged, 'binary_sensor.tesla_charger', old='on', new='off')

    def car_got_home(self, entity, attribute, old, new, kwargs):
        if self.get_state(entity_id='device_tracker.tesla_destination_location_tracker') != 'home':
            return
        if self.get_state(entity_id='binary_sensor.ds_garazna_vrata_opening') == 'on':
            return 
        self.garage_action({'action': 'open'})
        self.listen_state(self.car_was_parked, 'sensor.tesla_shift_state', new='P', oneshot=True)
        
    def car_was_parked(self, entity, attribute, old, new, kwargs):
        self.garage_action({'action': 'close'})
            
    def car_was_unplugged(self, entity, attribute, old, new, kwargs):
        self.log('Car was unplugged')
        if self.get_state(entity_id='device_tracker.tesla_location_tracker') == 'home':
            self.log('Waiting for drive shift')
            self.listen_state(self.open_garage_for_period, 'sensor.tesla_shift_state', new='D', oneshot=True)
    
    def open_garage_for_period(self, entity, attribute, old, new, kwargs):
        self.log('Opening garage!')
        self.garage_action({'action': 'open'})
        self.run_in(self.garage_action, 20, action='close')
    
    def garage_action(self, kwargs):
        action = kwargs['action']
        garage_state = self.pretty_garage_state()
        self.log(f'Requested action is {action}, garage state is {garage_state}')
        if action == 'close' and garage_state == 'closed':
            return
        if action == 'open' and garage_state == 'open':
            return
        self.call_service('switch/toggle', entity_id='switch.sw_rele_garazna_vrata_relay')
        
    def pretty_garage_state(self):
        state = self.get_state(entity_id='binary_sensor.ds_garazna_vrata_opening')
        if state == 'on':
            return 'open'
        if state == 'off':
            return 'closed'
        return 'unknown'