Today’s story is one of victory and defeat, of mystery and adventure… It’s time to automate the garage door. Connecting the garage door to the internet was a must on my list of smart home features. Our opener has internet connection capabilities built-in. As you might guess, I’m very skeptical of connecting a device to the internet when I have no control over the software running on it.

The garage door is controlled by a button hung on the garage wall. There is only a pair of wires, so a simple relay should be all that is needed to simulate the button press from a Raspberry Pi. I wired a relay module to a GPIO on the Pi mounted in the garage ceiling, and wrote a quick and dirty test program in Python. Sure enough, the little relay was clicking happily– but the garage door wasn’t budging. Time to troubleshoot. Does the push button still work? *raises the garage door* yep. How about the relay now? *click…click* nope.

You may have figured out by now, but this garage door opener isn’t just a simple momentary contact push button. Yes, that’s a microcontroller, in a garage door button. This sort of scenario calls for forensic equipment more capable than a simple multimeter, and so I turned to Amazon for a USB oscilloscope that could do some limited signal analysis. A device with Linux support was a must, and Pico Technology fit the bill nicely.

Searching for a Secret We Don’t Actually Need

My 2 channel Picotech oscilloscope, the 2204A, finally arrived, and it was time to see what sort of alien technology was in this garage door opener. There are two leads to the button, a ground and a five volt line. When the button is pressed, the microcontroller sends data back over that line by pulling the 5 V line to ground. If this isn’t an implementation of Dallas 1-wire, it’s a very similar concept.

The wire protocol appears simple enough to reproduce, ideally with an opto-isolator. I found a suitable chip and got it on order. With the physical interface sorted, it was time to move on to the data itself.

So, what does the request to open look like? “Open Sesame”? The Picoscope software is capable of signal decoding, so some futzing with those settings got reproducible results. UART at 9.6 kbaud. 38 bytes of data were being sent over the wire, and the next step was to capture several of those packets to look for patterns.

Each packet started with a repeatable pattern that Picoscope decoded as 55 01 00. A header of sorts? A source or destination identifier? So far, I just didn’t have enough information to tell. Other than that pattern, the data appeared to be random. So where to from here?

The underside of the switch lists a couple patent numbers. Patent applications often have lots of useful information that is not available anywhere else. Patents also show off legalspeak at its worst. Wading through patents like 7,561,075 does yield the occasional nugget. It describes an encryption (or obfuscation) scheme revolving around a simple transformation. Looking at the patent documentation, I suspected it would be possible to break the encryption scheme and spoof the garage door button being pressed.

A Python script to do the data processing was my next planned move. With a little luck, I thought I could re-create the algorithm, as well as potentially recover the secrets used to generate the data. Many a project have been derailed when the needs of real life have intruded in the life of the hacker, and I’m not immune. For about a month, that’s where the project languished. We’ve moved into the house, my firstborn is a week old, and it’s time to finally get the garage door working.

Spoof the Button, Not the Cryptography

Remember how we started by looking for a simple push button switch? It turns out, there is such a switch built in to the wired opener. Soldering leads onto that small button is the fastest to implement, if not the most elegant. Yes, my solution is a Raspberry Pi running a relay, and that relay bridging the tiny physical button on the wired opener.

Elegant but complicated solutions can be major pitfalls to getting stuff done. Sometimes you have the time to dig in and put together the ideal solution, but sometimes you just have to get the project done. If it’s cheating and it works, it’s not… Ok, it’s still cheating, but it works, which is more important.

We can open the garage door from a command line on the Raspberry Pi. That’s useful, but perhaps a bit clunky. Remember way back in the first article, I mentioned using flask to create a RESTful interface? Here’s where we can really get started.

from flask import Flask import time import RPi.GPIO as GPIO app = Flask(__name__) GPIO.setmode(GPIO.BCM) GPIO.setup(20, GPIO.OUT) GPIO.setup(20, GPIO.LOW) @app.route("/") def hello(): return "Hello!" @app.route("/moment/<pin>") def moment(pin): changePin=int(pin) GPIO.output(changePin, GPIO.HIGH) time.sleep(.5) GPIO.output(changePin, GPIO.LOW) return "OK" if __name__ == "__main__": app.run(host='0.0.0.0', port=80, debug=False)

This runs a rudimentary flask server, listening for http connections. Here the relay is on GPIO20, and so the server is waiting for a request for “/moment/20”, at which point, it flips that GPIO high for a half second, triggering the garage door. In order to run automatically, I’ve saved this to /usr/local/bin/gpio-flask.py, and then defined a systemd service at /lib/systemd/system/gpio-flask.service:

[Unit] Description=Flask Service for GPIO After=multi-user.target [Service] Type=simple ExecStart=/usr/bin/python /usr/local/bin/gpio-flask.py Restart=always [Install] WantedBy=multi-user.target

Telling systemctl to enable and start that service gets us in business. One last piece of the puzzle, let’s build a control page on our PXE server.

<!DOCTYPE html> <html> <body> <div style="text-align:center"> <form method="post"> <input type="submit" name="GDO" value="Cycle Garage" style="padding:25px 15px;"> </form> <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_POST["GDO"]) { $curl_handle = curl_init(); curl_setopt( $curl_handle, CURLOPT_URL, 'http://garage/moment/20' ); curl_exec( $curl_handle ); // Execute the request curl_close( $curl_handle ); } } ?> </body> </html>

We’ll expand on this PHP script more in the future, but for now it has two functions. The first builds and displays the interface page — just a single big button labelled “cycle garage”. The second part of the script only acts when a POST request is received. If the “GDO” value is present in the request, it uses curl to fire off the command to our Raspberry Pi, raising the garage door. It’s been a long road, but it finally works. A button on a web page opens my garage door. Let me relish my small victory for a moment…

Now that we’ve cheated our way past the garage door opener, next time we can work on data logging and HVAC control. Until then, happy hacking!