Skip to main content

Preface / Alternatives

I wanted to build my own garage door opener / sensor, for the purpose of monitoring my garage, and managing the garage door.

Before you go down this route, I will recommend you look at alternatives which are cheaply available, and will work right out of the box. If your goal is to just put something in, which works- Choose the alternatives and don’t build your own device.


The RE5V1C is a 2.99$ wireless dry-contact relay, which is perfectly suitable for activating your garage door.

Downsides- No easily accessible GPIO for a reed switch.

12/19 – Added Sonoff SV

Shelly 1

The Shelly 1 is a 10-15$ device, capable of triggering a dry-contact relay. It has the bonus, of having another input easily accessible. You can use this to determine if your garage door is open.

Note- The Shelly 1PM is NOT a dry-contact relay, and would be unsuitable for triggering your garage opener.

Zooz Z-Wave Relay

I actually deployed one of these recently to my Fireplace. It works good. It does have provisions which would allow it to trigger a garage door as well. Documentation even includes steps for how to use this to open garage doors.

Added 11/8/2021.

Required Components

Disclaimer- Amazon affiliate links are used in this article. For this site, I choose to not pesture my audience with annoying advertisements, and instead, only rely on affiliate links to support this hobby. By using the affiliate link, you will pay the same price on Amazon, as you would otherwise pay, however, a small percentage will be given to me.. To note- I DID buy all of the seen products with my own money, and did not receive any incentive to feature or utilize them.

Getting Started

The first step, (after testing on a breadboard), was to layout my components onto a piece of prototype board.

The next step, was to start building the traces. It has been a while since I have soldered onto prototype board, and it defiantly shows.

For the wiring of the BME280-

  • NodeMCU Pin D1 -> SCL pin on the BME280
  • NodeMCU Pin D2 -> BME280 SDA Pin
  • For both of the above traces, you will also need to bridge a 1k resistor to +3.3v.
  • NodeMCU GND -> BME280 GND
Hopefully your soldering is better then my first pass.

Test often!

Validating the BME280 does function as expected.

After validating the BME280 is connected as expected- I moved on to testing the reed switch, and relay outputs.

The reed switch connects to the prototype board via the screw terminal connector linked above in the parts list.

Wiring for the reed switch:

  • GPIO14 / D5 -> One side of the terminal connector
  • GND -> The other side of the terminal connector.

Wiring for the relay module:

  • GPIO12 / D6 -> Relay Input “A”
  • GPIO13 / D7 -> Relay Input “B”
  • VIN (bottom left terminal) -> Relay Power
    • Important- this pin typically has 5v power. The relay module requires 5v to work properly!
  • GND -> Relay Ground

After testing again.. I mounted the relay module to the prototype board using nylon standoff connectors. Since- my proper dupoint connectors were “lost in the mail”, I just soldered wires from the proper pins, onto the relay board. I also used a few dabs of hot glue to help protect the terminals.

Mounting everything together, for final assembly.

Next- since this board will be outside in my garage, where flying dust and metal debris is common- I wanted to protect the back-side of the circuitry.

I wanted to use epoxy to make a solid module- however, this is also in the mail still. For the time being- I instead just utilized a layer of hot-glue to protect the back-side of the prototype board.

Its not pretty- but, it will prevent accidental connections and short circuits from being created.

For the mounting of the reed switch, I used a zip-tie, and mounted the reed-switch directly to the chain.

When the garage door is closed- the switch makes good contact. When the garage door is open- the contact is broken, working as expected.

Reed switch mounting. Make sure to mount the bottom piece FLAT, unlike this photo. I did correct the issue after the photo was taken.

Lastly- you will need to mount the device, and connect the final wires up to the garage door opener.

On the back of your garage door opener, there are typically 3 pins.

  • 1. Common terminal, with multiple pairs of wires.
  • 2. “Remote” terminal. (Wire will goto the keypad)
  • 3. “Laser” terminal. (Wire will go to the front of your garage, to the “beam” sensors”)

There will typically be preexisting wires connected to the terminals. For our purpose- you will want to hook the relay up to the “Common” and “Remote” terminals. If you are unsure of which wires to connect to- It is the pair of wires going to your keypad mounted in your garage.


  • Relay 1 COM (Common) terminal -> Common Terminal of Garage Door Opener
  • Relay 1 NC (Normally Closed) -> “Remote” terminal of garage door opener.

Here is an image of my temporary mounting solution using double-sided tape. When I receive my shipment of epoxy, I will be creating a more permanent mounting solution, after cleaning up the hot-glue mess.

Temporary mounting solution….

ESP Home Configuration

While many people may prefer Tasomota, or EasyESP, or other solutions.. My personal preference is to utilize ESP Home.

I prefer it, because it does not require me to setup MQTT-based switches, and inputs for each and every device I configure in Home Assistant. When you push your firmware out for your ESP Home device- you are also pushing its configuration in Home Assistant with it.

I will not be diving into the basics of ESP Home- However, I will share my configuration, and some basic flashing directions.

# I utilize substitutions, to keep most of my variables at the top, in an easy to inspect/change location.
  devicename: "garage_door"
  friendly_name: "Garage"
  <<: !include secrets.yaml

<<: !include common.yaml

  name: ${devicename}
  platform: ESP8266
  board: nodemcuv2

# The BME280 utilizes the i2c bus.
   - id: bus_a
     sda: D2
     scl: D1
     # If you are adding new i2c devices, you can enable this to assist with identifying their address.
     scan: false

  - platform: bme280
    i2c_id: bus_a
      name: "${friendly_name} Temperature"
      id: bme280_temperature
      name: "${friendly_name} Pressure"
      id: bme280_pressure
    # I somehow managed to break the humidity sensor.... I don't recommend cleaning it with alcohol
    # humidity:
    #   name: "${friendly_name} Relative Humidity"
    #   id: bme280_humidity
    address: 0x76
    update_interval: 60s
  - platform: wifi_signal
    name: "${friendly_name} WiFi Signal"
    update_interval: 60s

  - platform: gpio
    id: relay1
      number: GPIO12
      inverted: true
    restore_mode: ALWAYS_OFF 
  # There is a 2nd relay connected, and wired up, for future expansion.
  # - platform: gpio
  #   name: "${friendly_name} Relay 2"
  #   pin: 
  #     number: GPIO13
  #     inverted: true
  #   id: switch2
  #   restore_mode: ALWAYS_OFF

  # This is the magnetic reed switch, used to determine if the door is closed.
  - platform: gpio
      number: GPIO14
      mode: INPUT_PULLUP
      # During testing- the reed switch was pretty noisy. This cleans up the output.
      - delayed_on: 100ms
      - delayed_off: 100ms
    id: reed_switch
    internal: true

  # This template hides both the functionality to open/close the door, as well as its current state
  # behind a single "cover"
  - platform: template
    device_class: garage
    name: "Garage Door"
    id: template_cov
    lambda: |-
      if (id(reed_switch).state) {
        return COVER_OPEN;
      } else {
        return COVER_CLOSED;
      - switch.turn_on: relay1
      - delay: 0.5s
      - switch.turn_off: relay1
      - switch.turn_on: relay1
      - delay: 0.5s
      - switch.turn_off: relay1

    number: GPIO0
    inverted: yes
# Common.Yaml

  ssid: ${wifi_ssid}
  password: ${wifi_pass}
  domain: ""
  fast_connect: True
  power_save_mode: none
    static_ip: ${ip_address}

  # ap:
  #   ssid: "${devicename} Fallback"
  #   password: ${fallback_pass}

# captive_portal:

# Enable logging

# Enable Home Assistant API
  password: ${api_pass}

# Enable OTA Flashing
  password: ${ota_pass}
api_pass: "Password for home assistant to connect to the device"
ota_pass: "Password for doing over the air updates"
fallback_pass: "IF you have the fallback access point enabled, this is its password."

wifi_ssid: "Your wireless SSID"
wifi_pass: "Your WiFI password."

Do note- I try to abstract common configuration files by utilizing ESPHome’s substitution feature. This allows me to share the common configurations across many devices, for which I have quite a few.

I also utilize static IP addresses for my IoT devices.

For a 10 second tutorial on esphome-

Create your configuration files… save into a folder somewhere.

# First- connect your NodeMCU device to your computer, via USB, or Serial Adapter. Ensure your driver is working properly.

# This will compile, and upload the device.
esphome garage_opener.yaml run

# From this point- the firmware will be uploaded, and should be executing on your device. ESP Home will let you know if you have any errors in your .yaml file.

For a more in-depth tutorial, please check out ESPHome’s official getting started.

The Final Result

If you have made it this far- you only have one step left to perform.

In Home Assistant, go to Integrations. Add “ESPHome”. Specify the IP Address in your configuration, and the API password defined in secrets.yaml.

The device will automatically add, and should be instantly usable.

My testing dashboard for the new device.