Creating a HomeKit Driveway Sensor

It’s one of the quirks of the house that I live in that I cannot easily see the end of the driveway from inside the house. This means it’s hard to tell when someone might have arrived, whether expected or unexpected. The Guardline Wireless Driveway Alarm has been a good solution to that problem, as it gives us a nice, loud, BING when its beam is crossed. It’s not perfect — deer and even neighborhood cats occasionally set it off — but I’m happier with it than I was without it.

Having other home automation projects I’ve undertaken using HomeKit (more on that another time), I decided that it would be nice to know if the alarm goes off when I’m not at home. My first inclination was to connect it to a Raspberry Pi, since I have those lying around, and I’ve used them successfully for other home proijects. The Guardline has relay connections, and I wondered if I could wire it up to a Pi and read the change in state from a GPIO pin. Clearly if the answer was no, I wouldn’t be writing this.

It turns out to be fairly simple. I chose to wire the Normal Closed contact to a pin on the Pi (GPIO board pin 37), the sensor pin and the common to a ground pin.

Guardline relay contacts wired to Raspberry pi

From there I could detect events on the sensor pin:

def motion_detected(pin):
    print("Motion detected!")

sensor_pin = 37

GPIO.setmode(GPIO.BOARD)
GPIO.setup(sensor_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(
    self.sensor_pin,
    GPIO.BOTH,
    callback=motion_detected
)

Once I knew that I was getting state change, I built a simple HomeKit accessory using HAP-Python:

import logging

import RPi.GPIO as GPIO

from pyhap.accessory import Accessory
from pyhap.const import CATEGORY_SENSOR


logger = logging.getLogger(__name__)


class GPIOSensor(Accessory):

    category = CATEGORY_SENSOR

    def __init__(self, *args, sensor_pin=3, **kwargs):
        super().__init__(*args, **kwargs)

        self.sensor_pin = int(sensor_pin)

        logger.debug('Setting up GPIO input')
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(self.sensor_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        GPIO.add_event_detect(
            self.sensor_pin,
            GPIO.BOTH,
            callback=self.__motion_detected
        )
        logger.debug('Subscribed GPIO events')

        serv_sensor = self.add_preload_service('MotionSensor')
        self.char_detected = serv_sensor.configure_char('MotionDetected')

    def __motion_detected(self, pin):
        logger.debug('Motion detected')
        sensor_state = GPIO.input(pin)
        self.char_detected.set_value(sensor_state)

    def stop(self):
        super().stop()
        GPIO.cleanup()

Which was easy enough to then run using the HAP-Python example. Once it’s set up in HomeKit, I get handy notifications like this:

HomeKit driveway sensor notification