OpenBSD Journal

Opening a Garage Door Using OpenBSD on a Raspberry Pi

Contributed by Sven G on from the who let the dogs out dept.

Sven G is back with another tale of using a Raspberry Pi in his garage:

OpenBSD lets one control the GPIO pins on a Raspberry Pi. Controlling a garage door is simple: connect the GPIO output pin to one side of a relay's coil, connect the 5 volt output of the Pi to the other side of the relay's coil, and connect wires from your garage's wall console to the relay's common and "normally closed" ports. Running the program below opens or closes the door. Since the Pi will be connected to the garage wall console, you'll want to enable sshd. I've named my Pi "garage" and my program "og," so I can open the door remotely with

ssh garage /home/sven/bin/og

Raspberry Pi and breadboardThe first step is to install OpenBSD on a Raspberry Pi. There are a couple of articles on https://www.undeadly.org that walk one through this procedure. I'd only like to repeat here that you need a USB to TTL Serial cable such as the one available at https://www.adafruit.com/product/954. Connect black, white, and green on the cable to pins 6, 8, and 10 respectively (i.e. ground, GPIO 14 or UART TXD, and GPIO 15 or UART RXD) on the Raspberry Pi. From your OpenBSD computer, access the Pi's serial console with cu -l /dev/cuaU0 -s 115200. The disklabel(8) trick I mention in the other article will enable you to install everything, even if the Pi doesn't have internet access.

The supplies you'll need are two M/F jumper wires to go from the Pi's pins to a breadboard's sockets, a breadboard, a relay (DPDT or SPDT available from Jameco, Bitsbox, and many others), a cheap access point to use as a wireless client, and a USB to Ethernet adapter (TP-Link and Anker adapters both worked for me.)

If there's some distance between your garage and home, you may need either a Yagi WiFi antenna to point at the garage from your home's access point, or an outdoor WiFi Antenna. You'll also need RP-SMA male to N type male extension coax cable to attach to the antenna and to your access point. Newer access points have fixed antennas. Luckily, I had an old one. The old ways are the best ways.Console with Raspberry Pi and circuitry

Oh, you'll also need a garage. We will solder two leads (I made two 2 ft leads from indoor electrical wire) to the garage's wall console contacts. You can tell which contacts need leads soldered to them if the door opens when you briefly connect them. These leads will connect to the relay's COM and NC ("common" and "normally closed").

On the Raspberry Pi, we will run our program as a regular user, but we need access to the GPIO pin. As root, add

/usr/sbin/gpioctl gpio0 23 set out door_pin

to /etc/rc.securelevel.

To enable ssh and start, type

rcctl enable sshd && rcctl restart sshd

and add this line to /etc/pf.conf if you want the Pi accessible via SSH from your local network:

pass in log from egress:network to port ssh modulate state

Our user needs to be in the group that /dev/gpio0 is in, and we need read-write permissions. So root should do something like groupadd gpiousers; chown root.gpiousers /dev/gpio0; chmod 660 /dev/gpio0. Now reboot. If our source code is in ~/src/og.c, then as your regular user on the Pi do mkdir ~/bin/; clang -o ~/bin/og ~/src/og.c and chmod 700 ~/bin/og.c.

Here is the source code:

/*
 * Copyright(c) 2021 Sven G
 *
 * Permission to use, copy, modify, and/or distribute this software
 * for any purpose with or without fee is hereby granted, provided
 * that the above copyright notice and this permission notice appear
 * in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
#include <sys/gpio.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define DOOR_PIN 23
#define NANOSLEEP 500000000	/* half a second */

int main() {
	struct gpio_pin_op op;
	struct timespec timeout;
	timeout.tv_nsec = NANOSLEEP;
	timeout.tv_sec = 0;
	int devfd = open("/dev/gpio0", O_RDWR);

	/* Trick garage wall console into thinking
	 * button was pressed.
	 */
	memset(&op, 0, sizeof(op));
	op.gp_pin = DOOR_PIN;
	op.gp_value = GPIO_PIN_HIGH;
	ioctl(devfd, GPIOPINWRITE, &op):

	/* Let time elapse. */
	nanosleep(&timeout, NULL);

	/* Trick garage wall console into thinking
	 * button was released.
	 */
	memset(&op, 0, sizeof(op));
	op.gp_pin = DOOR_PIN;
	op.gp_value = GPIO_PIN_LOW;
	ioctl(devfd, GPIOPINWRITE, &op);

        return 0;
}

For me, this is another example of how OpenBSD really shines. I knew from a web search that I would need to wait for less than a full second. I knew about the sleep function, but had no idea how to sleep less. So I went to man 3 sleep, and saw nanosleep(2). I didn't know anything about timespec, so apropos timespec led me to man timespec_get, which led me to clock_gettime(2). A lot of other operating systems really skimp on examples, but OpenBSD always has clear, helpful ones. The examples for measuring elapsed time showed me exactly what I needed to do.

The code is at https://github.com/sdkie3802dhsdkh3ioiuz/openbsd_garage_boost.

You might ask, why would I want to be able to open my garage door from my computer? I was inspired by the article at https://www.sparkfun.com about secure garage door openers. I also recently bought a very cheap software-defined radio, and it occurred to me that anyone could remotely monitor the frequency any garage door opener uses, so that they could know my garage door was about to open even before I step out of my house. That meant that I could also monitor the signals so that I would know whenever anyone else -- such as my dog -- decided to open my garage door and take my car.

As far as I know, using WiFI and SSH prevents this telltale radio spike.

What would have happened to me without this solution? I imagine the movie of my life would be called "Gone in 420 Seconds" (you know, 60 seconds, one human year is seven dog years) and the opening scene would have me in my basement all day with my headphones on, watching the waterfall from my software-defined radio, itching to see the signal from my garage door opener, notifying me that my dog Multimeter (a dog is man's best friend, and he's named after my second best friend) is stealing my car.

I'd hear my wife in the background mumbling something about fixing the dishwasher and painting the door and mowing the yard and "What is this bucket of diesel and a soldering iron doing on my grandmother's antique ramekin hutch?!"

The movie would end with me asking myself: "What? Is that my wife opening the garage door opening now? Why does she have suitcases in her hands? Why does her GPS say 'en route to Mother's?'"


Comments
  1. By Axe Xae (axeXae) axo@tango.lu on http://localhost

    I don't know why is this article even "worthy" for this site. Don't you have something better to write about? It's like a 6 years old kid can put this circuit together. How about go write a damn touchscreen driver for the rpi cause there is no working one for any BSDs while it works out of the box with Raspberry OS. You are just so behind Linux on so many fields...

    Comments
    1. By Peter J. Philipp (pjp) nospam@delphinusdns.org on

      Did you have anything to do with getting the linux touch screen driver for raspberry pi working? If not then you haven't done the hard work to report what hard work it was. If not then you're just holding forward someone elses hard work and rubbing their work under the OpenBSD community's noses. Maybe if you understood the wrong in this you'd like to be pro-active and bring a raspberry pi touch screen driver to OpenBSD, and do the hard work in order to secure your bragging rights.

    2. By John McCue (jmcunx) jmcq66@comcast.net on

      Maybe easy for you, but not for me. I think what he did is amazing and helps show how OpenBSD can work in an embedded space.

  2. By Nick H (Nick_H) on

    In contrast to the first poster I'd like to say thanks for the post, Sven. Anything that gets people experimenting with new things, playing with different use cases for OpenBSD, and levelling up their skills is a great thing in my book. Cheers!

  3. By Tom Van Looy (tvlooy) tom@ctors.net on http://twitter.com/tvlooy

    An issue I had with this solution was that on a reboot the pin received an "up" so my garage would open on a reboot ... The rest worked perfectly.

    Any clue what went wrong there? Maybe I needed a different pin http://wiki.soekris.info/Net5501_JP5_GPIO_Mappings

    Comments
    1. By Sven G (sveng2021) on

      Thanks for trying it! I think I can borrow a Soekris to try it on and I'll see what happens. I might try a different GPIO pin also. After enabling the pin in rc.securelevel, maybe setting its state to zero on the next line would help (if the pin was not already on). I will add another comment here as soon as I find anything out. Thanks!

    2. By Sven G (sveng2021) on

      I think you've identified an important issue that I hadn't considered. Since the only thing needed to trigger the door to open is a momentary short, I believe any reboot or power loss with the current setup will open the door. I'm not sure if a UPS would kick in quickly enough to prevent opening in the power loss scenario. I will work on a solution.

      Comments
      1. By Consus (consus) consus@ftml.net on

        > I think you've identified an important issue that I hadn't considered. Since the only thing needed to trigger the door to open is a momentary short, I believe any reboot or power loss with the current setup will open the door.

        All you need to known about OpenBSD "innovations" and "security".

      2. By Peter J. Philipp (pjp) nospam@delphinusdns.org on

        I haven't dealt with circuits since 1997, then as a 2nd year COMPENG student. We never dealt with such scenarios but I think if you have a hardware that sets all pins to HI upon reboot perhaps you need to test more pins, in a sort of dead-mans switch scenario? ie. Perhaps use a transistor or a small chip that has transistors built in to test if GPIO #A is high and #B is LO and only then act on the HI. However I can still see a fault here if the pins are sequentially (in a for loop) set to LO after the initial HI, you may end up with the right combination despite. Perhaps put a time delay circuit in there that counts down X seconds having #A on HI while #B is LO. It comes down to the circuitry though and has little to do with the OS that activates the GPIO's. I realise some people may want to use a lot more GPIO's for different purposes and using up a costly GPIO may seem wasteful. If you have 2 GPIO's you may as well do some more fancy signalling, although GPIO #B could be reused for other circuits as a safety.

        Comments
        1. By Sven G (sveng2021) on

          Thank you very much for your comments! I'm an absolute beginner in electronics, but I will definitely attempt to level up my understanding.

    3. By Sven G (sveng2021) on

      I have found that even a cheap UPS is enough to prevent accidental opening of the garage that might otherwise occur due to power loss, even with my very sensitive garage door wall console. That eliminates one class of reboots, but there's always hardware failure. . . . The issue I think is that simulating a press of the wall console button just takes a momentary short.

      Comments
      1. By Mike. (maple) on

        It may be worthwhile to put ~something~ between the Pi and the wall console.

        That something would stop signals from getting to the wall console until the Pi is in a stable state, e.g., waiting for a defined number of seconds after a power-up of the Pi.

        Whether that ~something~ is software or a chunk of hardware, well... :)

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]