- Go 98.1%
- Makefile 1.6%
- Shell 0.3%
QCC doorbot
Heavily inspired by open-keyless.
Requirements
Hardware
-
1x Raspberry Pi 4 (4GB)
-
1x Raspberry Pi Screw Terminal Shield (link)
-
1x PN532 or PN7150-based NFC reader modules (link)
-
1x 5v Switching Relay module (capable of switching at leave 12v) (link)
-
1x Adafruit NeoPixel Ring - 24 RGB LED (link)
-
1x SeeedStudio Grove PIR Mini Motion Sensor (link)
-
1-2x 3v-12v Buzzer Module (link)
-
1x Momentary Pushbutton (for doorbell)
-
1x On-Off Pushbutton (for event mode button)
-
1x USB webcam (for pictures when someone rings the doorbell)
-
1x 12v Continuous-Duty Latching Doorstrike (Assa Abloy)
Software
- Raspberry Pi OS (Lite, 64-bit)
- Go 1.23.x (dependencies listed below)
Setting up the Raspberry Pi
Configuration
This bot uses a lot of different hardware endpoints, including I2C, SPI, PWM, and general purpose I/O. There are a few things that need to be done before it can use all of them in harmony.
First, create an SD card using the Raspberry Pi Imager. In that app, click Operating System / Choose OS, click Raspberry Pi OS (Other), and then Raspberry Pi OS Lite (64-bit). We don't need the full version of the OS for doorbot, so the Lite version is the one we want. You can use the Imager's built-in settings generator to pre-define WiFi and login settings, as well as enable the SSH server, which helps when you don't want to have to plug the Pi into a monitor at first boot.
Then flash the card according to that app's instructions, put the card into the Raspberry Pi, and boot it up.
Once you've booted and logged in, the first thing you must do is you must disable the onboard sound chip (as per rpi-ws281x's setup instructions).
In /boot/cmdline.txt, append the following to the end of the only line in the file:
spidev.bufsiz=32768
This allows the LEDs to have enough buffer when being driven through the SPI hardware on the RPi.
Next, to enable PWM (which controls the buzzer/doorbell), you'll need to do a couple of things. First, you'll need to disable the onboard analog sound chip, and force audio through the HDMI ports instead. This is because the PWM module is usually used for audio, but we're going to be using it for a buzzer instead.
Create the file /etc/modprobe.d/snd-blacklist.conf, and add the following to it:
blacklist snd_bcm2835
Then, add the following to /boot/config.txt:
# this enables PWM on pin 18, which is what we want
dtoverlay=pwm,pin=18,func=2
# this forces audio onto HDMI
hdmi_force_hotplug=1
hdmi_force_edid_audio=1
Dependencies
The project requires a few libraries to compile and work properly.
- golang - the language this app is written in (I'm sorry)
- linux_libnfc-nci - extensions for the NFC module library
- libnfc - NFC module library
- rpi-ws281x - RGB LED ring library
Install various dependencies using the dependencies.sh file. This includes general things to make things compile:
sudo ./dependencies.sh
Install go with the following:
wget https://go.dev/dl/go1.23.0.linux-arm64.tar.gz
sudo tar -xpf go1.23.0.linux-arm64.tar.gz -C /usr/local
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
source ~/.bashrc
# check that it's working
go version
Replace 1.23.0 with the latest version from the link above, and add /usr/local/go/bin to your PATH.
We also need to install a bunch of extensions for libnfc called libnfc-nci. This isn't available in apt, so we have to install it manually.
NOTE: This MUST be installed first!
git clone https://github.com/NXPNFCLinux/linux_libnfc-nci.git
cd linux_libnfc-nci
./bootstrap
# even though there is a --enable-i2c option, that is NOT WHAT WE WANT
# --enable-alt == correct
./configure --enable-alt
make
sudo make install
You'll need to export these libraries so that the next dependency can build against them.
export LD_LIBRARY_PATH=/usr/local/lib
echo "export LD_LIBRARY_PATH=/usr/local/lib" >> ~/.bashrc
# ... or .zshrc
We also install a hand-rolled version of libnfc so we can use our pn71xx-based NFC module. You can't just install this from apt, unfortunately.
git clone https://github.com/nfc-tools/libnfc.git
cd libnfc
# we want to use the latest stable release
git checkout libnfc-1.8.0
autoreconf -vis
# add all of the drivers we might use - currently those are pn71xx and pn532 boards
./configure --with-drivers=pn532_i2c,pn532_uart,pn71xx
make
sudo make install
Next, install rpi-ws281x which controls the RGB LEDs:
git clone https://github.com/jgarff/rpi_ws281x.git
cd rpi_ws281x
mkdir build && cd build
cmake ..
cmake --build .
sudo make install
You'll need to add LD_LIBRARY_PATH pointing to /usr/local/lib to the global profile. Do that with the following:
echo "export LD_LIBRARY_PATH=/usr/local/lib" | sudo tee -a /etc/profile.d/local-lib.sh
Compiling & Running
Once all that's done, you can compile the app. The make commands should have you covered, and all of the Go dependencies should work out of the box.
make && make run
Structure of the app
The app is structured like this:
-
config/- code relating to the configuration files and parsing them -
etc/- where the.conffiles live, includingsettings.conf,secrets.conf, andmembers.conf -
devices/- files related to hardware devices such as the door reader, doorstrike power relay, RGB LED ring, doorbell button, etc. -
services/- files related to internet-connected services, such as the Discord bot -
tests/- random files for testing specific functions of the doorbot -
doorbot.go- contains the main loop of the app, which then calls out to thedevicesandservicesto set them up -
main.go- only really serves as an entrypoint into the app to set up basic logging
Settings
The settings.conf file contains various sections to control devices connected to doorbot.
doorstrikeConfig- defines the output for the doorstrike relay, which is what opens the actual door. The GPIO pinstrikePindefined here defines which GPIO pin the relay is connected to.ledConfig- defines the RGB LED ring attached to the front door. This is set up as an array in case we want to add more LED strips to doorbot later.buzzerConfig- defines the pin for the door chime/buzzer. This one is defined a bit differently as the library I use for other GPIO operations currently has a bug which prevents us from using it for PWM, so I had to use a different library for now. (TODO: fix this when the bug is fixed)miscConfig- defines the inputs/ouputs for various buttons and sensors that don't warrant their own independent module.paths- defines the paths for each configuration filelogging- affects the logger Doorbot uses (zerolog)
Secrets
The secrets.conf contains things like passwords and tokens for other services and devices, including:
cameraSettings- for the RTSP-based webcam we use for the front doordiscordBot- settings for the Discord integration
Songs/Chimes
Songs and chimes are defined by their chromatic notes and their traditionally-defined note lengths, relative to their beats per minute. Check out etc/songs.conf for examples.
You can add songs/chimes to this list if you want a custom melody for your own entrance.
Wiring
For wiring up Doorbot, see the wiring guide.