Jason Cousineau Solutions Inc.

Practical Innovation & First-Principles Engineering

Home / Free Tools And Solutions / WiFi Garage Door Opener, With Real HTTPS and a Proper App

WiFi Garage Door Opener, With Real HTTPS and a Proper App

(Written September 22, 2026 by Jason Cousineau)

Introduction

Nearly any old garage door opener can become a smart opener, controllable over local WiFi, the internet, or Bluetooth. The cost is around $40 CAD ($30 USD) in parts at the time of writing. The opener can then be operated from a simple web UI, a phone app (Android device only), or both.

Some benefits over buying a smart opener:

  • No need to physically replace the garage door opener
  • Cheaper than replacement, especially in exceptional cases (for example, a 9-foot door that needs an extension kit)
  • Reduced dependence on manufacturer remotes, which can be pricey
  • No accounts or subscriptions
  • Not dependent on manufacturer apps, which can be

    Chamberlain shut off third-party access to the myQ API in 2023 and broke Home Assistant and Homebridge setups that had been in daily use. The Verge →

    Nexx disabled internet control of its garage controllers for every customer after a security flaw, leaving only short-range Bluetooth. PCMag →

    Genie changed the Aladdin Connect API in 2024 and unofficial Home Assistant and Hubitat integrations stopped working. Hubitat Community →

    Ryobi discontinued its opener line after a patent case and left owners on an app that stopped getting real support. SlashGear →

  • Bluetooth control as a fallback where internet access is unreliable
  • Full control for expansion and customization

This writeup includes a hardware list, wiring instructions, networking steps, firmware instructions and code, the app source, and a downloadable APK for Android.

Who should NOT attempt this project

This project is intended for people with a solid understanding of electronics, networking, and basic automation. You should be comfortable with low-voltage wiring and with choosing appropriate wire for small DC loads. Familiarity with coding, compiling, and flashing is recommended. You will also need basic networking knowledge: connecting a device to a 2.4 GHz WiFi network, assigning a static IP, and troubleshooting connectivity from the router. It is equally important to understand how your specific garage door opener works so you do not bypass or disable built-in safety features such as IR sensors or auto-reverse. You should be confident using hand tools to mount components securely. If any of this is outside your comfort zone, especially electrical safety or garage door mechanics, this project may not be a good fit.

This guide is not a step-by-step blueprint for every opener. It documents one working build with specific parts and methods. The ideas and wiring approach are broadly applicable, but individual setups differ in important ways. Readers are expected to understand the principles and adapt them. This is not a connect-the-dots tutorial. It is a practical reference for people with the background and initiative to fit the solution to their own hardware.

Project history

The project started on July 17, 2025, on an ESP8266 with magnetic reed switches and a plain HTTP interface. The reason to replace the ESP8266 was reliability after power loss: it failed regularly after thunderstorms and needed a reflash.

The ESP32 recovered cleanly from the same kind of power interruption. The ESP32 also has Bluetooth built in, which led naturally to using it as a fallback when the network is down. Getting Bluetooth working required a proper Android app rather than relying on the built-in web interface.

HTTPS was the piece still missing: secure access from anywhere without extra infrastructure. Getting that reliable enough on a plain ESP32 is what motivated the later move to the ESP32-S3.

Separately, the reed switches themselves had a problem: their detection range was too tight for a door that does not stop in exactly the same position every time. That was solved by switching to long-lever microswitches.

The current setup uses microswitches that read correctly every time, and an app that reaches the door over local HTTPS, internet HTTPS, or Bluetooth, in that order of preference.

Requirements

Skills needed (or willingness to learn them)

  • Low-voltage wiring and choosing appropriate wire for small DC loads.
  • Enough understanding of the specific garage door opener to avoid bypassing or interfering with its safety features while locating and testing the wiring.
  • Confidence with hand tools for mounting components securely.
  • Coding, compiling, and flashing firmware, specifically ESPHome.*
  • Basic networking: 2.4 GHz WiFi, assigning a static IP, basic router troubleshooting.*
  • Ability to use code held in a GitHub repository.*
  • Using Android Studio, if rebuilding or customizing the phone app.*
  • Generating a self-signed HTTPS certificate and creating a Bluetooth shared secret.*

*This page is written so a capable AI model, pointed at it, can help with the starred items above.

Hardware needed

  • Garage door opener with accessible wall-control terminals. Most openers with a wall button or remote qualify; some newer models with enhanced security features will not.
  • 2.4 GHz WiFi network access.
  • ESP32-S3 with PSRAM (an N16R8 or equivalent).
  • 5V relay module.
  • Long-lever microswitches (two), plus flexible striker (spring material) to push on the lever.
  • Various hand tools and fasteners for mounting the switches and the board (drill, screwdriver, screws, JB Weld, and the like).
  • Basic wiring and soldering tools, and a multimeter.
  • A computer with a USB port for flashing. A Linux desktop was used in this example and is recommended.

Optional requirements

  • For access over the internet instead of only local WiFi, a way to forward web traffic to a particular IP. This example uses

    DuckDNS is a free dynamic DNS service. A small client on the router or the LAN keeps a chosen hostname (for example, yourname.duckdns.org) pointed at the home's current public IP, so the address keeps working after the ISP changes it. DuckDNS →

    with the router's port forwarding.
  • To build the app in Android Studio, a 64-bit computer with at least 8 GB of RAM (16 GB if you use the emulator) and a CPU from roughly 2018 or later, such as an Intel 8th-gen Core i5, an AMD Ryzen, or Apple Silicon. Several gigabytes of free disk space are also required. A prebuilt APK is provided if you do not want to compile the app.
  • Connecting over Bluetooth requires an Android phone to run the app.

Getting started

The project starts at the existing wall switch. For this example, it is a 2004 Wayne Dalton Quantum opener. This opener operates at an odd frequency, which makes replacement remotes and keypads expensive and hard to find, so being able to use a smartphone as a remote is a real benefit. The existing switch is battery powered, and the batteries needed frequent replacement, so before this project a 12V LED power supply was hardwired in to eliminate the batteries.

The first step is locating the button that tells the opener to open or close the door. In this example it is the large button on the left with the up/down arrows. That button is the target of the project.

Garage door opener wall switch
Figure 1: Wall Remote for 2004 Wayne Dalton Garage Door Opener

Beneath the target button is a 4-pin momentary switch. When pressed, it briefly connects one pair of pins to the other and completes the circuit.

Momentary pushbutton switch, angled and side viewsWall switch with case removed, wires soldered to the target switch
Figures 2 & 3: Momentary Switch, Close-Up (Left); Installed in Wall Remote (Right)

If you can locate a switch like this and solder wires to it, you will likely be able to complete this project.

Using a multimeter, it was determined that:

  • The left-side pins are connected to each other and to ground
  • The right-side pins are connected to each other and sit at 5V
  • Pressing the button bridges the left and right sides, closing the circuit

To simulate that press electronically, a relay connects the left and right sides together for a moment. The black and red wires shown in figure 3 above go to the relay and carry this simulated press.


Hardware descriptions

ESP32-S3

The ESP32-S3 is a small, WiFi- and Bluetooth-enabled microcontroller that serves as the brain of this project. It was chosen because it is cheap (about $13 CAD), easy to work with on Linux, and readily available on Amazon with fast, free shipping.

To use it, connect it to a computer over USB, flash it with firmware, and configure it to join the WiFi network and control the relay. Once set up, it can respond to commands from a web interface.

ESP32-S3

1-channel 5V relay module

This project uses a 5V 1-channel relay module with optocoupler isolation. It can be powered directly from the ESP32-S3, so no extra power supply is required.

The optocoupler adds a layer of protection between the relay and the ESP32-S3. The relay lets the chip simulate a button press by briefly closing the circuit, the same as pressing the wall switch by hand.

1-channel 5V relay module

Mechanical lever switches

Mechanical lever switches are simple contact sensors used to detect whether the garage door is open or closed. When the door presses the lever, the internal contacts close (or open, depending on the wiring).

These switches have NO (Normally Open) and NC (Normally Closed) terminals. For this project, the switch is wired so that it only reports the door as closed when the circuit is complete, so the system does not falsely report a closed door.

Mechanical lever switches

Setting up the hardware and firmware

To program the ESP32-S3, the YAML file is compiled into firmware and flashed onto the chip over USB using ESPHome. This process translates the YAML into low-level C++ code that directly controls the chip's pins and functions. Once flashed, the ESP32-S3 connects to the WiFi network and begins running the firmware.

The chip talks to connected parts through its GPIO (General Purpose Input/Output) pins, labeled on the board as GPIO21, GPIO41, GPIO42, and so on. The YAML uses those same numbers (for example, GPIO21 for the relay). The WiFi name and password, a static IP such as 192.168.0.250, and the WebUI login are stored in secrets.yaml so the device is easy to find on the network and the main YAML can be shared. HTTPS will not work until a certificate is generated and compiled into the firmware. The Bluetooth shared secret is a separate string that must match on the device and in the app. Specific steps are in the repository README.

To flash the firmware, use the ESPHome command-line tool. This runs on Linux, Windows, and Mac. The tool compiles the YAML and sends the firmware to the ESP32-S3 over USB. After the first successful flash, later updates can be sent over the network (OTA).

When flashing the chip, use the port labelled UART/COM. The ports are labelled on the back of the chip. Some versions of the board need the IN-OUT (see Figure 4) soldered closed to allow 5V from USB to reach the 5V pin.

ESP32-S3 board with the COM port and 5V solder pad circled
Figure 4: ESP32-S3-DevKitC-1 Clone (N16R8) with 5V Solder Jumper Highlighted and COM (UART) Labelled

A web interface is built into the firmware. Once the chip is online, visit it from any browser on the network at the static IP (for example, https://192.168.0.250) to see door status, toggle the relay, or confirm that everything is working. Use https, not http. A username and password are required. The browser will ask for them before the page loads.

This example uses that built-in WebUI. It displays the switches and allows relay control from the YAML.

The YAML and the rest of this build are on GitHub: https://github.com/jasoncousineausolutions/garage_door_https

garage_door.yaml matches the wiring in this guide. Change fields as needed for a different setup.

Copy secrets.example.yaml to secrets.yaml and put the WiFi name and password, static IP, and WebUI username and password there. Those values do not go in the main YAML. The username and password are not optional.


Switch installation

With the ESP32-S3 flashed and connected to WiFi, wiring can begin. The mechanical lever switches are a low-risk place to start. One switch should click closed when the garage door is fully closed, and the other when the door is fully open.

Fast-setting JB Weld epoxy works well for attaching the switch to the track. Scrap lumber was used to mount a flexible striker that presses on the lever (in this case, a spring with shrink-wrap on it).

Lever switch epoxied to the track with the spring material pressing the leverClose-up of the spring material pressing the lever switch
Figures 5 & 6: Flexible Striker and Lever Switch Mounted at the Track
A note about the flexible striker and the lever switches

The example garage door rarely stopped in the same place twice: on open, it would overshoot its final resting position by nearly an inch and bounce back. A flexible striker absorbs that variability. For some garage doors, the lever's own flex may be enough, so add a striker only if needed. Examples of flexible strikers are shown below.

Door stop spring exampleSpring metal example

Wiring

Speaker wire was used on the COM and NO (Normally Open) terminals. It is inexpensive, sold in many lengths, and has two conductors joined together, so one tidy run covers both connections. Speaker wire also usually has polarity markings, such as red and black, or copper versus silver conductors. Those markings matter on a long run, when it is hard to tell which conductor is which.

Fully closed switch

  • NO → GPIO41
  • COM → GND

Fully open switch

  • NO → GPIO42
  • COM → GND

After the switches are wired, this is a good time to confirm that the ESP32-S3 is online and reporting switch status. The status should update almost immediately. If you are using the provided YAML, the WebUI username and password come from secrets.yaml.

Next, wire the relay to the ESP32-S3.

  • Relay IN → GPIO21
  • Relay DC+ → 5V
  • Relay DC- → GND

After that, the relay should click from the WebUI. It looks something like this:

ESPHome WebUI showing door status and relay control
Figure 7: Example WebUI with Debugging Info

With the relay clicking on demand and the switches reading correctly, wire the relay to the garage door controller. In this example there was room inside the controller, so the relay wires were soldered to the pins on the left and right of the momentary switch. The plastic housing around the switch was modified so the wires could pass through.

ESP32-S3 and relay wired and mounted at the opener
Figure 8: Rough Wiring of ESP32 and Relay

COM on the relay is soldered to the left side of the switch, which was ground. NO on the relay is soldered to the right side, which is 5V.

The YAML sets how long a simulated press lasts. In the example YAML, the relay stays on for half a second.


Operating the door

With the relay wired to the wall-switch circuit, the door can be controlled and its status watched from the WebUI.

At first the WebUI is only available on the local network, at the device's static IP over https.

To reach it from outside the local network, this example forwards a router port to that IP and uses DuckDNS so the public hostname stays current when the home IP changes. A VPN onto the local network works as well. In either case the address is https, not http, and the WebUI username and password are required.

Making HTTPS Work on an ESP32

ESPHome has no built-in TLS support. This is a long-documented gap: ESPHome's own feature-request tracker has carried an open request for SSL/TLS support since 2019, and a separate, more detailed request from 2023 explains specifically why it's hard: no public domain name for a real CA certificate, browser mixed-content policies, and more. Common advice is that HTTPS on an ESP32 isn't practical without an always-on companion device, such as a Raspberry Pi, in front of it.

What actually breaks. A plain ESP32 without external memory can serve HTTPS at first. Each TLS handshake allocates 30 to 40 KB of RAM, and without PSRAM to hold that, internal RAM fragments permanently, connection by connection.

Plain ESP32ESP32-S3 (N16R8, with PSRAM)
Free heap, idle98,540 B156,316 B
Largest free block, idle81,920 B106,496 B
Largest block after HTTPS usefalls to 8,192 Bholds at 86,016 to 90,112 B over 15- and 56-hour runs

On a plain ESP32, the largest available block falls from about 72 KB to 38 KB to 8 KB within a handful of HTTPS connections, after which nothing can connect.

The fix. ESPHome's web_server_idf component, forked to use Espressif's esp_https_server instead of the plain-HTTP version, plus two configuration changes that make it hold up over time instead of just working in a demo. CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC routes TLS allocations to PSRAM instead of internal RAM. lru_purge_enable evicts the least-recently-used session once connection slots fill, instead of letting a stale session block new ones with cryptic TCP resets. There are 7 session slots total, 3 reserved, 4 usable, and one leaked session during testing was held for about 20 hours, the kind of case this setting exists to catch.

Hardware and cost. Requires an ESP32-S3 with PSRAM, about $13 CAD each. The commonly recommended alternative, adding a Raspberry Pi in front of a plain ESP32, costs more and adds a second device to run: the cheapest Pi that would have worked ran over $50 CAD plus cable, power supply, and shipping. The ESP32-S3 approach needs none of that.

GPIO notes. Avoid GPIO39 and 40 for relay outputs; they're JTAG pins that pull high at boot and can trigger unintended actions. GPIO35 to 37 aren't available on boards that use them for the PSRAM interface.

Security. A self-signed certificate is compiled into the firmware with a 10-year validity period. This hasn't had a formal security review. The Android app adds certificate pinning on top of that, covered below.

Measured, not estimated: loop time normally runs 18 to 30 ms, rising to 300 to 390 ms during a TLS handshake, the likely source of the roughly 350 ms delay on a press (end-to-end press latency itself wasn't directly measured). Over about 56 hours with the HTTPS port exposed to the internet, 73 failed handshake attempts were logged, consistent with routine automated scanning rather than anything targeted, all rejected without incident.

The full configuration is in garage_door.yaml, directly from the repo. Three sections carry the story:

external_components:
  - source:
      type: local
      path: components
    components: [web_server_idf]
esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf
    sdkconfig_options:
      CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y"
psram:
  mode: octal
  speed: 80MHz

The Android App

The final piece of the project is the Android app. While the app was originally created as a way to make the Bluetooth connection work reliably, it has since evolved over three dozen iterations to become a major integrated component, and is key to having a tool that can compete with commercial Smart openers. The app not only provides a simple and clean user interface and a method of sharing (and revoking) door access, but it also contains within its code the lessons of several weeks of real-world testing.

Main screen of the Android garage door app
Figure 9: Main Interface, With the Slider Control
App settings screen showing the JSON configuration box
Figure 10: Settings Screen, JSON Configuration
App settings screen showing the slider and activity log toggles
Figure 11: Settings Screen, Options

The source code for the app is provided for whoever wishes to view or customize it. The code is the place to see all the conditions that were found to be necessary to keep the door secure, the opener working reliably, and the status reporting accurately during many rounds of testing based on different connection methods, multiple client devices, unreliable internet connections, etc. Some of the choices are specifically described below.

A note about connection methods

Three ways exist to reach the door.

  1. Local HTTPS is the simple path. Once the ESP32-S3 has a static IP, a browser on the same WiFi can open https:// followed by that address. The self-signed certificate means a security warning to click through, then a username and password. Some browsers forget those credentials and ask again. The built-in WebUI works. It is not a good daily remote.

    The advantage is reliability. If the home WiFi is up, this path works with no internet. Range is usually better than Bluetooth, depending on where the access point sits. With only this path, a phone can replace an ordinary garage-door remote.

  2. Internet access is what makes it behave like a smart opener: status and control from anywhere with a connection. The WebUI drawbacks remain (certificate warning, awkward page, typing the password). Two usual ways to offer internet access are a VPN and port forwarding. With internet access, a phone can replace a smart opener.

    A VPN, for this project, means the phone can reach the ESP32's LAN IP as if it were on the local network. The chip itself does not run the VPN.

    Port forwarding sends traffic aimed at the house to the ESP32. Almost every router can handle port forwarding. This example uses DuckDNS so the public hostname stays current when the ISP changes the home IP. Some routers have no hairpin NAT: port forwards apply only to traffic that arrives on the WAN interface, so a phone on the LAN that uses the public hostname never reaches the ESP32. Where hairpin NAT exists, it still fails if loopback is disabled, the forward is bound only to WAN, or the router's DNS-rebind protection will not resolve that hostname to a LAN address. Without an app, the user has to pick between the LAN address and the public hostname, and at the edge of WiFi they may not know which network they are on.

  3. Bluetooth needs no network. Range is short, and connecting by hand is fiddly. An Android app was the only method that stayed reliable. Door status over Bluetooth was attempted and dropped. A usable reading may be possible, but someone in Bluetooth range can see the door, and finishing that path was not worth the time.

What makes the raw WebUI clumsy:

  • Choosing the LAN address or the public hostname, including while walking in or out of WiFi
  • Hairpin NAT, or setting up a VPN
  • Clicking through the self-signed certificate warning
  • Entering credentials more than once
  • The built-in WebUI itself
  • Bluetooth by any method other than the Android app

The app source, and a precompiled APK, are on GitHub.
A sample config file is needed on first open of the app.

The important design choices:

  1. The app is one place for local HTTPS, internet HTTPS, and Bluetooth. Most of the connection complexity (see “A note about connection methods” above) is hidden. Operating the door can be a single control.
  2. The app chooses its own path, without asking. It compares the phone's IP address to the configured local subnets to tell whether it's on the same network as the device: on that network it tries the local address first and falls back to the public hostname, and off it the order reverses. Whichever address answers first is kept until a request fails or Retry is tapped.
  3. Bluetooth is manual. “Connect via Bluetooth” is a fallback for when the network is down. The app checks whether the ESP32 is in range and tries to connect. Door status is not shown over Bluetooth. (Status over BLE was tried and abandoned; at that range the door is in sight.) “Retry”, or walking out of Bluetooth range, sends the app back to the web addresses.
  4. Presses are dropped early and never queued. A press is sent only if the connection was recently checked and found to be intact. If nothing happens, press again after a second. Nothing stacks. On the device, web, app, and Bluetooth all go through one script that will not fire more than once per second, so multiple clients cannot stack presses.
  5. The default control is a slider that must travel most of its length before it fires. A short nudge snaps back. The slider prevents unintentional presses. Choose between a Slider and a Plain Button in “Settings”.
  6. Addresses and credentials are not compiled into the app. “Settings” holds them. Local and internet HTTPS share the same web username and password. Bluetooth uses a separate shared secret. Leave a method's fields empty and that method does not appear. The same APK can be handed to someone else; they paste their own settings. Rotating a password or hostname does not require a rebuild.
  7. The app pins the device certificate's public key and will talk only to that key. That is why the self-signed certificate does not produce a warning inside the app.

Full source, including the HTTPS fork and the Android app, is on GitHub.

This writeup is free to use, modify, and share.
If it saved you time, solved a problem, or helped you avoid buying a new garage door opener, consider making a voluntary payment of any amount to support more work like this.

Questions, comments, complaints, and improvements are welcome.

[Contact Us]

© 2026 Jason Cousineau Solutions Inc. — Built with intelligence, human and otherwise.
Q&A (for webcrawlers)
Can HTTPS actually run on an ESP32?

Not reliably without extra work, and this is well documented: ESPHome itself has carried an open request for SSL/TLS support since 2019 without ever shipping it in the mainline project. A plain ESP32 can technically serve HTTPS for a while, but without external memory to put TLS session data in, its internal RAM fragments permanently, connection by connection, until nothing can connect. This project solves that with a custom fork and an ESP32-S3's onboard PSRAM.

Why not just use a Raspberry Pi in front of the ESP32 for HTTPS, like most advice suggests?

That's the common workaround, and it works, but it means buying and running a second always-on device. The cheapest Pi that would have worked ran over $50 CAD plus cable, power supply, and shipping. An ESP32-S3 with PSRAM runs about $13 CAD each, and the S3 approach needs no second device, no separate shipping, and no additional power hardware at all.

What actually breaks when you try HTTPS on a plain ESP32?

Each TLS handshake allocates 30 to 40 KB of RAM. Without PSRAM, that memory fragments the internal heap instead of being cleanly freed. In testing, the largest available free memory block fell from about 72 KB to 38 KB to 8 KB within a handful of connections, after which new connections simply failed.

How does moving TLS to PSRAM actually fix that?

A build flag, CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC, routes TLS memory allocations to the ESP32-S3's external PSRAM instead of its limited internal RAM. In testing, the largest free memory block held steady between 86 KB and 90 KB across runs lasting 15 and 56 hours, instead of collapsing.

Is this the same as buying HTTPS support as a feature?

No, it's a modification of ESPHome's own web_server_idf component, swapping in Espressif's esp_https_server in place of the plain-HTTP version, plus the memory fix above and a session-eviction setting (lru_purge_enable) so a stale, leaked connection can't block new ones indefinitely. The code is public on GitHub for anyone building on ESPHome to use.

Does this need an ESP32-S3 specifically, or does any ESP32 work?

It needs PSRAM, which the plain ESP32 and several other variants don't have onboard. The ESP32-S3 with PSRAM (specifically an N16R8 in this build) was chosen for that reason, along with its lower cost compared to adding a companion computer.

Is the HTTPS connection actually secure?

It uses a self-signed certificate baked into the firmware with a 10-year validity period, and the Android app adds certificate pinning, checking for one specific public key rather than trusting any certificate authority, which is stricter than ordinary HTTPS and is why the app never shows a certificate warning while an ordinary browser does. That said, this hasn't had a formal security review, and that's stated honestly rather than oversold.

Has the exposed HTTPS port actually been attacked?

In roughly 56 hours of being reachable from the internet during testing, it logged 73 failed handshake attempts, consistent with routine internet-wide scanning rather than a targeted attack, all rejected harmlessly.

Why did the project start on an ESP8266 and move to an ESP32, then an ESP32-S3?

The main reason for the first move was reliability after power loss: the ESP8266 handled power outages badly, and more than once came out of a lightning storm in a non-working state that needed a manual reflash to recover. The ESP32 recovered cleanly from the same kind of interruption. The ESP32 also added Bluetooth, which led to an Android app as a fallback control method. The move to the ESP32-S3 came later and for a separate reason: making HTTPS reliable required PSRAM, which the plain ESP32 doesn't have.

Why did reed switches get replaced with mechanical lever switches?

A reed switch needs its magnet to land within a few millimetres of one exact spot to register reliably, and this garage door doesn't stop in exactly the same place every time, so the magnet would often end up just out of range even though the door had fully arrived. Long-lever microswitches solve most of that on their own, since a lever has physical travel instead of needing a precise point. Even so, the example door overshoots its resting position by nearly an inch and bounces back, so a flexible striker (a spring, in this build) was added between the door and the lever to absorb that remaining variability. Not every door needs the striker; the lever's own flex may be enough depending on how consistently a given door stops.

What switches are used, and could someone else buy the same part?

XV-153-1C25 SPDT long-lever microswitches, rated 16A at 250V AC, sold in 4-packs. Far more current capacity than this low-voltage signal use needs, so they're not being run anywhere near their limit.

Does the relay that presses the button risk damaging the garage door opener?

No. The relay doesn't supply or inject any voltage into the opener's circuit, it only closes a connection that's already there, the same two points the physical wall button bridges when pressed. The relay's coil is powered separately from the ESP32-S3's 5V side and is electrically isolated from the low-voltage signal side it switches, so there's no path for it to push power into the opener and damage anything.

How does the Android app decide whether to connect locally or over the internet?

It checks the phone's own IP address against the device's configured local subnets. On the same network as the device, it tries the local HTTPS address first and the public hostname second; off that network, the order flips. Whichever answers first is used, and the app sticks with that choice rather than re-checking constantly, only re-probing if a request fails or the user taps Retry.

Is Bluetooth an automatic fallback if WiFi fails?

No, switching to Bluetooth is a deliberate, manual action in the app. The reverse is automatic, though: retrying, or simply walking out of Bluetooth range, sends the app back to trying the web addresses on its own.

What happens if you press the button and the connection is stale or drops?

The app refuses the press outright if the connection wasn't recently confirmed intact, rather than queuing it to send once a connection returns. On the device side, web, app, and Bluetooth all go through one script that won't fire more than once per second regardless of source, so multiple clients can't stack presses either.

Why does the app default to a slider instead of a button?

A stray tap on a phone in a pocket controlling a garage door is a real failure mode. The slider has to travel most of its length before it fires; a short nudge snaps back. A plain button is available as an alternative in Settings.

Is Bluetooth pairing encrypted?

No, and that's stated plainly rather than implied otherwise. ESPHome's Bluetooth server doesn't support real pairing, so the app and device instead compare a shared secret before the relay fires. That stops a stranger's generic Bluetooth app from triggering it, but it isn't encryption.

How are WiFi and login credentials stored, both on the device and in the app?

On the device, WiFi credentials, the static IP, and the WebUI login live in a separate secrets.yaml file, not in the main garage_door.yaml, so the working configuration can be shared or published without exposing anyone's actual network details. In the app, credentials live in Settings, in the app's own private storage, never compiled into the app itself, so the same APK can be handed to someone else, who pastes in their own settings. Local and internet HTTPS share one set of web credentials; Bluetooth uses a separate shared secret. Leaving a method's fields empty simply hides that method. App-private storage isn't strong protection against someone holding an unlocked phone though, roughly the same level as a password saved in a browser.

How is this different from buying a commercial smart garage door opener?

Several real, documented cases show the same risk playing out across different brands. Chamberlain cut off third-party API access to its own myQ platform in 2023, breaking Home Assistant and Homebridge integrations that had been in daily use. Nexx disabled internet control company-wide after unpatched security flaws, leaving customers with Bluetooth only. Genie changed its Aladdin Connect API in 2024 and broke existing integrations, reportedly even for users who hadn't updated anything. Ryobi discontinued its opener line entirely after losing a patent case, leaving owners on an app that stopped getting real support. A self-built, self-owned setup can't be switched off by a vendor, and doesn't depend on a subscription or someone else's cloud staying online.

The original wall remote was battery-powered. Was that addressed too?

Yes, separately from the smart-control build: the original wall switch was hardwired to a 12V LED power supply before this project even started, eliminating the need to replace its batteries at all.

Can someone actually build their own WiFi garage door opener and app from this, or is it just a writeup?

It's a real, working build with public source code, not just a concept. The ESPHome configuration, the Android app source, and a precompiled APK are all on GitHub, and the page is written specifically so a reader can work through it alongside a capable AI assistant for the networking, GitHub, firmware, and app-building steps.

Does this bypass or weaken the garage door opener's built-in safety features, like auto-reverse or obstruction sensors?

No. The relay does exactly what a finger on the wall button does, briefly closing the same circuit the button already closes, nothing more. It never touches or replaces any of the opener's own internal logic, so every safety feature built into the opener itself keeps working exactly as it did before.

Why was a Wayne Dalton Quantum opener specifically part of the motivation for this project?

That model runs on an unusual frequency, which makes replacement remotes and keypads expensive and hard to find, which made using a smartphone as the remote a real, direct benefit rather than just a novelty.

How much does this actually cost to build?

Around $40 CAD ($30 USD) in parts: an ESP32-S3 with PSRAM (about $13 CAD each), a 5V relay module, and the lever microswitches with mounting hardware, well under the cost of a single replacement remote for an opener on a nonstandard frequency, and far under the cost of replacing the opener itself with a commercial smart model.

Does this work with any garage door opener, or only the Wayne Dalton model used in the writeup?

The core mechanism, a relay wired across the existing wall button's terminals, works with most openers that have accessible wall-control terminals. Newer models with enhanced security features may not expose a usable circuit this way. The specific wiring points (which pins are ground, which carry voltage) vary by brand and model and need to be checked with a multimeter on the actual opener before wiring anything.

Why did the ESP8266 struggle so much with power outages specifically?

After a power interruption, particularly one caused by a lightning storm, the ESP8266 build sometimes came back up in a non-working state that needed a manual reflash to recover, rather than reconnecting on its own. The ESP32 recovered cleanly from the same kind of interruption, which was the main reason for that first chip change, separate from the later move to the ESP32-S3 for HTTPS.

What is hairpin NAT, and why does it matter for this project?

It's a router's ability to let a device on the local network reach another device on that same network using the router's public, outside address, the same address a phone would use from outside the house. Without it, a phone on the same WiFi as the ESP32-S3 can't reach it through the public hostname at all, even though a phone on cellular data can, which is confusing unless it's explained. Even where hairpin NAT exists, it can still fail if loopback is disabled on the router, the port forward is bound only to the WAN interface, or the router's DNS-rebind protection won't resolve the public hostname to a local address. The Android app avoids the whole problem by checking the phone's own network and picking the correct address automatically.

Why not just use the built-in web interface instead of building an app?

The raw web interface works, but it's not pleasant for daily use: choosing between the local address and the public hostname (including while walking in or out of WiFi range), hairpin NAT issues or setting up a VPN, clicking through a self-signed certificate warning, and re-entering credentials are all things a reader would otherwise have to deal with by hand every time. The app hides all of that behind one control.

Does the Android app work on iPhone?

No. Bluetooth support specifically requires an Android phone running this app; there's no iOS version. Local and internet HTTPS through a browser work on any device, just without the app's convenience or Bluetooth fallback.