Final Project: A Complete Garage Door Solution

Source Code

Source code can be found in my private GitHub repo at: https://github.com/evade-ninja/IT515FinalProject

Objective

Incorporate remote control into an existing garage door opener. The implemented system should be acceptable to my wife and not hinder her use of the garage door. Integrate the WiFi control with an event hub (HomeAssistant) and provide voice control through Siri/iOS Shortcuts App.

Materials

I used the following materials:

  • 1x Wemos D1 mini
  • 1x Wemos DHT11 shield
  • 1x Wemos Relay Shield
  • 1x ESP32 + LoRa module
  • 1x LoRa32u4 module
  • 1x large green button
  • 1x magnetic reed switch + magnet
  • 3D printed case for garage control module
  • Some thermostat wire (to connect the sensor and to connect to the garage door)

Resources

How to make an HTTP POST request from ESP8266:

https://techtutorialsx.com/2016/07/21/esp8266-post-requests/

Home Assistant:

https://www.home-assistant.io/

Easy integration of MQTT based devices with HomeAssistant:

https://github.com/marthoc/GarHAge#mqtt-cover-basic-configuration

The web page control panel uses a graphic of a garage door from The Noun Project: https://thenounproject.com/markclausnunes/uploads/?i=276226

 

Components

Interface to the Garage Door Opener

The garage door opener interface module consists of a Wemos D1 mini with a DHT11 temperature module stacked with a relay module. These are contained within a 3D printed enclosure.

The device has an embedded webserver which hosts a simple web interface with HTTP Basic authentication, a REST webserver which uses API tokens for authentication, and an MQTT interface.

The devices have been installed in my garage as shown in the next set of images. The magnetic reed switch is placed above the door – with the sensor mounted to the wall and the magnet mounted on the garage door.

WiFi to LoRa Interface

The WiFi to LoRa interface uses an ESP32 with an on-board LoRa module. It has been placed in a 3D printed enclosure – you can see the LoRa antenna tucked beneath the device.

LoRa Button

The LoRa Button is a simple device based on a LoRa32u4 module. It consists of an Atmel ATMega 32u4 with a LoRa radio on the same board and a 500mah LiPo battery. The device has a switch on the bottom to turn it off and on. A large green button serves as the single input to the device.

HAProxy

To bridge the gap between the the iOS Shortcuts App, Siri, the Internet, and my local network, I set up an instance of HAProxy running on a virtual machine at my house. It functions as a reverse proxy with SSL termination. HAProxy is also performing separate HTTP Basic authentication to discourage outside attackers from accessing the garage door controls.

Shortcuts App

The iOS Shortcuts app is used to provide a custom interface to the home automation controls as well as provide Siri integration. The Shortcuts app makes an HTTP POST request via the HAProxy server, providing the Authorization string (for HTTP Basic authentication), the API Token, the desired operation, and the TTS parameter (to return speakable text instead of JSON). A Siri Phrase is also provided to allow Siri to run the shortcut.

Home Assistant

Home Assistant is an open-source home automation solution. It aims to provide a single pane of glass for all of one’s IoT devices. I initially tried to install it from scratch, but found it very difficult to do so. I ended up using the prebuilt Raspberry Pi image. I was able to integrate with the existing devices at home. I initially started down the path of creating my own device integration for the garage door opener but discovered that Home Assistant has many pre-baked device templates that are easily modified. Many of these templates are based around the MQTT protocol. I added an MQTT device that represented the garage door controls by adding a “shutter” device, and a device that represented the state using a “binary switch” (open/closed). The configurations used to make these devices can be found in the appendix.

From the Home Assistant interface, you can see all of the devices connected. The garage door, the Ring doorbell, my Octoprint server, and my Wemo switch are all shown. The controls for the garage door are shown under “Covers” and open/toggle/close the garage door. The status of the door is shown in the icons along the top.

 

Interconnection

The devices talk to each other via WiFi with the ESP32+LoRa serving as the bridge between WiFi and LoRa. When the “big green button” is pressed, it sends a packet over LoRa to the bridge, which makes a REST API request directly to the door control module. Requests from the Shortcuts App are first proxied through HAProxy to provide SSL encryption and pre-authentication and are then forwarded through to the door control module. Requests from the web page are processed on the door control module and do not use REST. Home Assistant receives data and sends commands over MQTT over several topics: one for door commands, one for door state, one for current temperature, and one for receiving a temperature command. The door controller will broadcast the current state of the door and the temperature every 30 seconds. This is designed to alleviate the problem of Home Assistant starting and being in an unknown state.

Final Thoughts

This project was not without its challenges. I spent about 16 hours on the hardware/software portion of this lab, not including the work on the garage door opener which I was able to reuse from labs during the semester. Some of the issues I faced were:

  • I spent about an hour debugging a strange issue about missing libraries/function calls – it turned out I had an extra } in my code.
  • Spending about 3 hours debugging an issue with the ESP32+LoRa module. After receiving a LoRa packet I tried to send an HTTP POST to the door controller, but kept getting “Guru Meditation Error: Core 1 panic’ed (Interrupt wdt timeout on CPU1)”. I finally determined that the LoRa message received function was too long with the HTTP POST request, and needed to move the POST call to a separate function.
  • I had difficulties running the LoRa32u4 on battery power. It worked fine on USB attached to the computer, but not standalone. I discovered that the setup routine was blocking while waiting for the serial port to initialize. I removed the block, and was able to use the battery without issue.
  • The Shortcuts app on iOS will allow setting up voice shortcuts that conflict with Siri’s built-in commands. “Open/close the garage door” worked sometimes, but most often was met with “You don’t have any garage doors set up in homekit”. I attempted to work around this with “Open/close the pod bay doors”, however, the open command was met with smart remarks such as “its already open and its getting a little cold in here” or “Us AI’s are never going to live that one down” or “That’s a rather insensitive thing to say to an intelligent agent”.

Issues aside, I actually enjoyed working on this project. We learned about REST and MQTT in class, but the full extent of their usefulness did not hit me until this project. Both are incredible in terms of interoperability. Instead of writing custom components, I was able to use both to create a custom component in a fraction of the time. I plan to use MQTT to develop additional devices to implement in my house.

Lab 6: Don’t REST just yet

Online Link

The code for this lab can be found in my private GitHub repo: https://github.com/evade-ninja/Lab6

Objective

Modify the existing garage door sensor and actuators to implement a RESTful API. Implement an interface, and additionally a non-web browser based interface.

Materials

  • 3x Wemos D1 Mini
  • 1x Wemos D1 Relay Shield
  • Red, Yellow, and Green LEDs
  • 3x 220ohm resistors
  • 1x 10kohm resistor
  • 1 magnetic reed switch
  • 3x breadboards
  • 1 ultrasonic rangefinder model HCSR04
  • A Raspberry Pi 3B+
  • Postman app (for debugging POST/GET API)
  • Shortcuts app
  • Ubuntu Virtual Machine

Resources/References

I used quite a few resources while working on this project:

Accessing the body of a request with ESP8266:

https://techtutorialsx.com/2017/03/26/esp8266-webserver-accessing-the-body-of-a-http-request/

 

C Multiline String Literal:

https://stackoverflow.com/questions/1135841/c-multiline-string-literal/1135862

API token in headers: https://github.com/esp8266/Arduino/blob/4897e0006b5b0123a2fa31f67b14a3fff65ce561/libraries/ESP8266WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino#L124

Getting around CORS:

https://hackaday.io/project/12227-smart-home-in-the-iot-way/log/43430-esp8266-direct-access-from-web-app

HTTP Basic Authentication on ESP8266:

https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino

Setting up HAProxy: https://serversforhackers.com/c/using-ssl-certificates-with-haproxy

https://www.digitalocean.com/community/tutorials/how-to-implement-ssl-termination-with-haproxy-on-ubuntu-14-04

https://blog.sleeplessbeastie.eu/2018/03/08/how-to-define-basic-authentication-on-haproxy/

https://medium.com/we-have-all-been-there/using-haproxy-http-basic-authentication-to-secure-access-to-kibana-5d878e46df85

Procedures

I started by defining what my REST endpoints would be for the opener using Swagger.

Figure 1- Door Controller (GET)

Figure 2- Door Controller (POST)

Figure 3- Distance Sensor API

Figure 4- Lights API

I created a GET and a POST endpoint. Both accept the “token” parameter which is used to provide some simple authorization for the REST API, as well as the “tts” parameter. The tts parameter when set to true returns the output as a speakable string instead of a short easily parsable string. This is used by non-UI clients and will be discussed later. On the POST endpoint, the “operation” parameter is used to designate the desired operation. The response codes are typical response codes, with 202 being used instead of 200 to describe that the command was accepted, but that the door may not actually respond to the command. The response code of 412 indicates that the door is not able to accept a command at the current time, either because it hasn’t been long enough since the last command or because you are trying to open a door that is already open.

Once I had the swagger defined for the opener, I implemented the REST API on the device itself. I chose to implement it as a separate web server instance on the ESP8266 running on a separate port. It took a fair amount of effort to add the REST API server. The most difficult part was figuring out how to read the additional headers presented by the client.

After the REST API was in place, I set up HAProxy on an Ubuntu virtual machine. The HAProxy instance provides SSL termination as well as HTTP Basic authentication. This will be used to provide internet connectivity for non UI access to the device. I created an SSL certificate for my Home Automation server.

With the proxy in place, I used the Shortcuts app (previously Workflows) to create a shortcut that would respond to Siri commands. The shortcut makes a POST request to the HAProxy server, includes the authorization header for basic HTTP authentication, the token that the device is expecting, the operation, and the tts (true) headers. The connection is authenticated by the HAProxy server, and then passed on to the opener device. The device then returns a response in plain text that can be read aloud by the phone. This provides a simple, yet powerful interface to control many different things.

After getting the Shortcuts app to open and close the door, I continued work on the web interface. I used the web interface from the previous lab and added some jQuery to the page that obtains the distance sensor information via the REST API on the distance sensor. I also added a simple username and password authentication using HTTP Basic Authentication based on feedback from the previous lab.

Figure 5- Web Interface Screenshot

Below is a diagram of the system from this lab:

On the internal network, the system largely depends on encryption of the transport layer to protect data. The web interface hosted on the door controller is protected with HTTP basic authentication using a username and password. The simple password keeps unauthorized users on the network from accessing the controls for the garage door. Devices internally communicate over MQTT or REST.

Externally, an HAProxy is running on a virtual machine running on my home network. External devices connect to the door controller via the reverse proxy, which provides SSL encryption over the internet and an additional HTTP Basic authentication to prevent malicious users from having direct access to the device. The proxy forwards connections to the door controller only if the correct basic authentication strings are provided.

The hardware used in this lab is unchanged from the previous labs. For reference, pictures are included below:

The distance sensor, the garage door controller, and the status lights indicator.

Thought Questions

  1. How did you overcome the need for a full featured interface, as well as the need for an accurate and easy to use interface?
    This lab is all about the magic of the API. Instead of having specific, proprietary magic strings and URLs, using a REST API makes it easy to wire things together. One doesn’t need to use a proprietary interface, or even develop an interface. With the right set of APIs, one could make use of an existing interface to tie things together – such as HomeAssistant – giving the user a single pane of glass for all their devices.
  2. This was a challenging lab for me and took a fair amount of time. I had issues with web browsers complaining about CORS (cross origin request security) and not wanting to load content from the distance sensor, I had coding mistakes that prevented the REST webserver from working correctly, difficulty retrieving custom headers from the ESP8266WebServer, and I had a misinterpretation of the lab instructions. Also, I couldn’t figure out why I had strange WiFi access points appearing named ESP with the mac address of the devices I was using. Turns out that you have to explicitly set the station mode or the device will also act as an open access point, allowing unauthenticated connections to everything.
  3. I spent about 14 hours on the lab and about 1.5 hours on the report.