Building a Siri/iOS HomeKit-Enabled Garage Door Control with Raspberry Pi – Part 4: Door Sensors

This post is the fourth in a series exploring home automation using a Raspberry Pi, each covering a different aspect of the build of a garage door controller:

  1. Basic hardware acquisition and installation into a project box
  2. Software installation and code for controlling the door
  3. Software camera configuration and code streaming video to HomeKit
  4. Installing and configuring door open/closed sensors

Hardware Acquisition

I purchased an additional item (listed below) to detect whether or not the garage door is closed. I’ve included a link to Amazon for your convenience, but you may be able to find this item at a lower cost elsewhere.

Item Purpose Price
Magnetic Switch Magnetic/reed switch for detecting if the garage door is closed. $8.99

Door Sensor Code

Back in Part 2, we stubbed out the door sensor code in src/sensor.js. We can implement that now.

import gpio from 'rpi-gpio';
import config from '../config.json';
import * as _ from 'lodash';
const debug = require('debug')('controller:sensor');

const closedPin = config.door.pins.closed;

gpio.setMode(gpio.MODE_RPI);

const readValue = () => {
  return new Promise((fulfill) => {
    gpio.setup(config.door.pins.closed, gpio.DIR_IN, function () {
      gpio.read(config.door.pins.closed, function(err, value) {
        debug('readValue', value);

        fulfill(value);
      });
    });
  });
}

const isDoorClosed = async () => {
  const status = await readValue();

  debug('isDoorClosed', status);

  return status;
}

export default { isDoorClosed };

Configuration

We’ll need to supplement the configuration to include the GPIO pin we used for our door closed sensor. We can do that in our config.json:

{
  "door": {
    "accessory": {
      "name": "Garage Door",
      "username": "01:23:45:67:89:AB",
      "pincode": "876-54-321",
      "port": 51826
    },
    "pins": {
      "toggle": 11,
      "closed": 7
    }
  },

  "camera": {
    "accessory": {
      "name": "Garage Camera",
      "username": "BA:98:76:54:32:10",
      "pincode": "123-45-678",
      "port": 51062
    },
    "snapshot": {
      "rotation": 180
    },
    "stream": {
      "width": 640,
      "height": 400,
      "fps": 15,
      "bitrate": 100,
      "rotation": 180
    }
  }
}

I used GPIO 4 (pin 7). You can use any GPIO as long as you’re not using it for anything else.

Wiring

I placed the magnetic sensor on the floor next to the garage door and the magnetic part (the part without the wire connections) on the door itself. Then I ran the 22-gauge wire from the switch back to the terminal block on the outside of the project box we set up in Step 1.

Next, I connected “COM” on the magnetic switch to GPIO 4 and “NO” on the switch to a ground pin. “NO” means “normally open,” so you will only get a 3.3V reading (high) when the magnets are adjacent to each other. By setting it up this way, we will get a signal when the door is closed, but no signal when the door is open.

Wrap-Up

You should now see the status of the door in the Home app on iOS. And that’s it!

Door Status in iOS Home app

I’ve placed all of the source code for the project on a GitHub repo. You can download the whole set of code and work from there. Clone it, fork it, improve it. Feel free to submit pull requests if you have some great ideas/improvements.

Conversation
  • JammerX19 says:

    This is a great series, thanks for doing this! I have two questions for you:

    1. I keep getting this error: UnhandledPromiseRejectionWarning: …. TypeError: _doorState is not a function. I’ve searched the code for _doorState and can’t find it. What is this?

    2. I’m not sure how to get this to start up when the Pi boots. Got any pointers on that? The few things I’ve tried have failed.

    • Gentry Smith says:

      Bumping for visibility! Also getting the _doorState TypeError error. Any ideas?

      JammerX19, you can set boot commands in the /etc/rc.local file. Just add two commands above the exit 0 line that cd into wherever you placed the garage-pi directory and to run the yarn controller command.
      My two commands:
      cd /home/pi/garage-pi/
      sudo /usr/bin/yarn controller

      And it runs the program as root from start!

      • JammerX19 says:

        Thanks, I eventually figured that part out. My google-fu wasn’t strong the day I wrote that.

        • mike612 says:

          Did anyone figure out the _doorState TypeError? Also, does this only check state when the switch button is clicked? If I open the door by pressing the hardwired button or my remote, will this not detect it?

          • Kyle says:

            I’m pretty sure the doorState is not a function error is related to the misspelling of doorState on line 72 of main.js. I’ve been meaning to submit a pull request for it I just haven’t. Maybe I’ll do it tomorrow.

            I don’t have any errors in my log but the door state doesn’t quite seem to be working perfectly yet.

          • Kyle says:

            Just kidding. The misspelling isn’t the cause of “_doorState is not a function”. Still working on debugging it.

  • Jennifer Kylie says:

    Very interesting , good job and thanks for sharing such a good information about garage door sensors. This is a so useful post ever.

  • Comments are closed.