Open Sesame
Several months ago, we accidentally left our garage door open. A bunch of stuff got stolen and it sucked. I resolved to make sure this never happened again by making our garage door text us if we left it open. The components of this build are very similar to what I wrote about in my DIY nest article, so I’ll skip the nitty gritty and just tell you what to buy and lay out how it works. This article is intended for someone with the required knowledge to do this on their own, but wants to know what parts work well up front and skip painful Squirrel debugging.
The Spec #
Our garage door has the following nice features:
- Semi-secure text endpoint for opening and closing the door
- Secure web endpoint for opening and closing the door
- Door state web endpoint
- Door-open-too-long-detector + texter
Parts List #
- Electric Imp (the brains) ~$25
- Electric Imp breakout board ~$12
- Magnetic contact switch ~$3.75
- Jumper wires, resistors, LEDs. We found this kit to be pretty good~$20
- Soldering Iron
- Solder
- Optoisolator Relay ~$5
- Breakaway Headers ~$1
- Jumper pins
- Optional Proto Board 3 for ~$11
Build Overview #
Your garage door’s control circuitry is very similar to that of your thermostat. There are two wires with a low control voltage, and if you connect them, something cool will happen.
Because garage doors are like heaters, our build will be similar too. An optoisolator relay will act as our switch to trigger the door to open and close (just like in the thermostat). However, in the garage door, we’ll swap out the temperature sensor for a magnetic switch to determine if the door is open or shut. On the whole, this build is much easier to get working because you don’t have to deal with finicky i2c stuff around the temperature sensor.
Reading From the Magnetic Sensor #
The magnetic door sensor acts as a switch. When the contacts are touching, it acts like a wire. When they aren’t, it isn’t. This particular sensor is nice because it has a large enough tolerance to handle garage doors with a little wobble. To read the state from the imp, we connect one of the door inputs to ground and the other directly to an input pin on the imp.
doorState <- hardware.pin2
doorState.configure(DIGITAL_IN_PULLUP, onchange)
Normally, the pin will read 1
since it is being pulled up when the door is open. When the door is closed, the circuit will be complete, and it will be pulled down to 0
.
Some notes on wiring #
- Be sure to wire the optoisolator in a way such that if the power goes out, your garage door doesn’t open. The wiring method I used in the thermostat article should have that property – the most important thing is that you get a relay that is usually open and not usually closed.
- You’ll need to solder wires to the switch to extend them to connect to your imp.
- I started this project on a breadboard, but ended up soldering it to a protoboard and screwing into the wall because it kept getting knocked around. The garage door is a pretty high traffic area.
From a hardware, side, that pretty much covers it.
Some notes on software #
At some point I’ll probably open source the whole project, but at the moment the git repo has some secrets in it and I’m too lazy to rewrite history. Instead, I’ll include the snippets that were annoying to get right and leave the rest to you to figure out.
To trigger my garage door, I found that a 1 second high voltage on the control wire worked fine. My code for toggling the door looks like this:
doorControl <- hardware.pin5
doorControl.configure(DIGITAL_OUT)
function toggle() {
doorControl.write(1);
imp.wakeup(1, function() {
doorControl.write(0);
})
}
To send text messages, I used Twilio. They have a free account that works perfect for this use case (since you don’t care that when your garage texts you it says “Sent from your Twilio Trial Account”). Using Twilio from the Imp is pretty easy once you know the right incantations.
To send a text via twilio (make sure to fill in the variables):
function makeAuthHeader() {
local userPass = "twilio secret"
local b64 = http.base64encode(userPass);
return {"Authorization": "Basic " + b64};
}
local FROM_NUMBER = "+YOUR_TWILIO_NUMBER";
function sendText(message, number) {
local url = "https://api.twilio.com/2010-04-01/Accounts/YOUR TWILIO LINK/Messages.json"
local headers = makeAuthHeader();
local body = http.urlencode({From=FROM_NUMBER, To=number, Body=message});
local request = http.post(url, headers, body);
local response = request.sendsync();
server.log(http.jsonencode(response));
}
Decode a POST body from Twilio (to open with a text):
local requestObj = http.urldecode(request.body);
Validate a password
(to secure your garage door):
local password64 = "SHA512HashOfYourPassword";
function validate_password(password) {
local hashBlob = http.hash.sha512(password);
local hash64 = http.base64encode(hashBlob);
return hash64 == password64;
}
If you actually attempt this project and there are code bits you are hitting your head against, let me know and I can elaborate as needed. Hopefully this gets you started in the right direction!