You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
13 KiB

4 years ago
---
title: A stupid smart doorbell system
tags: [doorbell, debian, ssh, fswebcam, bash, shell, microphone, webcam, raspberry pi, thinkpad]
updated: 2019-07-01 11:16
4 years ago
description: A stupid smart doorbell that mails you a photo of who rang
---
10 months ago
A [smart doorbell](https://en.wikipedia.org/wiki/Smart_doorbell) is useful when
4 years ago
you are not at home but you want to be notified about when and who rang.
## Ideas
10 months ago
The idea behind my implementation is very naïve: someone rings at the
doorbell, a program listening from a microphone pics up the sound and triggers
a script. A webcam pointed in front of the door takes a picture which is sent
4 years ago
as an email attachment.
10 months ago
Initially I wanted to use a [cheap wireless
4 years ago
doorbell](https://harizanov.com/2013/07/raspberry-pi-emalsms-doorbell-notifier-picture-of-the-person-ringing-it/).
10 months ago
The problem is that I have no experience in soldering and I didn't want to
4 years ago
mess things up. However, the idea intreagued me nonetheless.
10 months ago
I had to find another system to get the trigger. The obvious way was to use
the existing doorbell system in the house. For this purpose I found a [ruby
script](http://thomer.com/howtos/detect_sound.html) which uses
4 years ago
[ALSA](https://www.alsa-project.org/main/index.php/Main_Page) and [soX](http://sox.sourceforge.net/)
10 months ago
to record and examine the sound. If the sound is greater than the set
threshold an external script is called. I added an expected frequency range
detection check which is useful to avoid some false positives. To do this I
4 years ago
first translated the script from ruby to bash.
## Hardware tests
10 months ago
The first thing I did was to try the Raspberry PI 3B plus, with a
an unnamed USB webcam which has an integrated microphone. A Logitech USB webcam
4 years ago
would take the pictures instead.
10 months ago
The Raspberry was connected via Ethernet. Unfortunately the single board
computer suffers from USB bandwidth problems since [the 4 USBs ports and the
Ethernet socket are all shared as part of a single
4 years ago
hub](https://raspberrypi.stackexchange.com/questions/44433/does-wifi-on-the-pi-3-reduce-the-ethernet-bottleneck-when-using-usb-device).
10 months ago
Just in case I also tried using a powered 7 port USB hub. The results were the
4 years ago
following:
Error starting stream. VIDIOC_STREAMON: Connection timed out
VIDIOC_DQBUF: Invalid argument
Capturing 1 frames...
VIDIOC_DQBUF: Invalid argument
No frames captured.
10 months ago
What follows is part of the output from `$ lsusb` concerning the previously
4 years ago
cited webcam.
ID 0c76:1600 JMTek, LLC. Ion Quick Play LP turntable
ID 1871:0306 Aveo Technology Corp.
10 months ago
Even using the integrated WiFi card, which is not connected to the USB hub,
4 years ago
didn't solve the problem. I had to use a proper computer...
10 months ago
With an old IBM Thinkpad everything seemed to work fine so I decided
to add another feature. Using the same unnamed webcam and the software
4 years ago
[motion](https://motion-project.github.io/) it is possible to detect movement.
10 months ago
I tried to use that to know when and who passes through the front door.
Just like before, there were problems with the USB bandwidth. A cause of this
might be that the computer has USB version 1.1 ports. I had slightly better
improvements when I passed from a USB microphone to an analog one and changed
4 years ago
the original webcam to an
ID 058f:3880 Alcor Micro Corp.
10 months ago
[But the bandwidth was still not
4 years ago
enough](https://motion-project.github.io/motion_config.html#basic_setup_v4l2),
so I had to settle for a simple doorbell system for the moment.
## Ingredients
What follows are a couple of tables of all the hardware and software ingredients I used.
### Hardware
| Object | Quantity | Description | Purpose | Required |
|:-------------:|:-------------:|:-----:|:
| [IBM ThinkPad A31](https://www.thinkwiki.org/wiki/Category:A31) | 1 | computer | control the devices and read sensors | yes |
10 months ago
| [Logitech QuickCam E1000](https://wikidevi.com/wiki/Logitech_HD_Pro_Webcam_C920#Models) | 1 | webcam | Take photos | yes |
4 years ago
| [Dlink DHP-306AV](https://eu.dlink.com/uk/en/products/dhp-306av-powerline-av-network-adapter) | 1 | powerline to ethernet adapters | if your computer is out of range from the router or switch | no |
| Ethernet wire | 2 | CAT 5e | connect the power line devices | no |
| USB extension cord | 1 | | connect this cable between the computer and the webcam | no |
| analog microphone | 1 | cheap microphone with a 3.5mm jack | record audio | yes |
| plastic cup | 1 | put this around the microphone tip and point it to the doorbell | concentrate the sound | no |
| paper tape | some | | stick the microphone to the wall near the doorbell | no |
### Software
| Software | Description | Required |
|----------|--------------|----------|
| [Debian](https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-9.5.0-i386-netinst.iso) | i386 stable. Version 9.5.0. Operating system. I didn't want to fiddle too much this time | yes |
| [fswebcam](http://www.sanslogic.co.uk/fswebcam/) | take pictures | yes |
| [OpenSSH](https://www.openssh.com/) | configure the computer remotely | yes |
| [NTP](http://www.ntp.org/) | time synchronization daemon | yes |
| [S-nail]( http://www.sdaoden.eu/code.html#s-nail) | send mails | yes |
| [msmtp](https://marlam.de/msmtp) | MTA | yes |
| [soX](http://sox.sourceforge.net/) | sound processing | yes |
| [bc](https://www.gnu.org/software/bc/) | arithmetic comparisions in bash | yes |
| [ALSA](http://www.alsa-project.org) | set the audio levels | yes |
| [GNU Bash](http://www.gnu.org/software/bash/bash.html) | "The GNU Bourne Again shell" | yes |
| [eSpeak](http://espeak.sourceforge.net/) | speech synthesis | no |
| [Haveged](https://github.com/jirka-h/haveged) | "[...] Feed Linux's random device" | no |
| [webfs](http://linux.bytesex.org/misc/webfs.html) | a simple web server so you can access the pictures with in a simple manner | no |
## Scripts
What follows are the two scripts I used, called `listen.sh` and `shoot.sh`
respectively.
```shell
#!/bin/bash
#
# listen.sh
#
# Copyright (C) 2009 Thomer M. Gil [http://thomer.com/]
# 2018 Franco Masotti
#
# Oct 22, 2009: Initial version
# Oct 29, 2018: Translation from ruby to bash. Added expected frequency range.
#
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# This program detects the presence of sound and invokes a program.
#
# You need to replace MICROPHONE with the name of your microphone, as reported
# by /proc/asound/cards.
MICROPHONE='I82801CAICH3'
# Sampling format of the audio card.
FORMAT='S16_LE'
THRESHOLD='0.30'
# Expected frequencies in Hz.
EXPECTED_FREQ_MIN='600'
EXPECTED_FREQ_MAX='1250'
# Sample gathering in seconds.
SAMPLE_DURATION='3'
SCRIPT_FULL_PATH="/home/doorbell/srv_maint/scripts/doorbell/shoot.sh"
HWDEVICE="$(cat /proc/asound/cards | grep "${MICROPHONE}" | awk '{print $1}')"
while true; do
out="$(/usr/bin/arecord -D plughw:"${HWDEVICE}",0 -d "${SAMPLE_DURATION}" \
-f "${FORMAT}" 2>/dev/null | /usr/bin/sox -t .wav - -n stat 2>&1)"
# As you can see, no regex are used here -> this might fail.
amplitude="$(echo "${out}" | grep 'Maximum amplitude' | awk '{print $3}')"
frequency="$(echo "${out}" | grep 'Rough frequency' | awk '{print $3}')"
if [ "$(echo ""${amplitude}">="${THRESHOLD}"" | bc -l)" -eq 1 ]; then
if [ "$(echo ""${frequency}">="${EXPECTED_FREQ_MIN}"" | bc -l)" -eq 1 ] \
&& [ "$(echo ""${frequency}"<="${EXPECTED_FREQ_MAX}"" | bc -l)" -eq 1 ]; then
echo "match: f=${frequency} Hz; a=${amplitude}"
${SCRIPT_FULL_PATH}
else
echo "no match: f=${frequency} Hz; a=${amplitude}"
fi
else
echo "no match: a=${amplitude}"
fi
done
```
```shell
#!/bin/bash
#
# shoot.sh
#
# Copyright (C) 2018 Franco Masotti
#
# Oct 29, 2018: Initial version.
#
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# This program takes a picture and sends it via mail.
#
BASE_DIR="/home/doorbell/srv_maint/scripts/doorbell"
PICTURE_FILE="/var/www/doorbell.jpg"
MESSAGE="event: $(date +"%F %T")"
CAMERA="/dev/video0"
RESOLUTION="640x480"
CAPTURE_FRAMES="1"
SKIP_FRAMES="50"
BRIGHTNESS="100%"
4 years ago
CONTRAST="100%"
LOG_FILE="/var/log/doorbell.log"
MAIL_SUBJECT="doorbell"
MAIL_SENDER="Home"
MAIL_RECEIVER_ALIAS="all"
pushd "${BASE_DIR}"
fswebcam \
--set brightness="${BRIGHTNESS}" \
--set contrast="${CONTRAST}" \
-r "${RESOLUTION}" \
-R \
--font 'dejavu:10' \
-S "${SKIP_FRAMES}" \
-F "${CAPTURE_FRAMES}" \
-d v4l2:"${CAMERA}" "${PICTURE_FILE}" &
pid="$!"
# Below: put generic commands.
# Speak out.
espeak -s 125 -v it "Doorbell" &
4 years ago
# Keep a log file.
echo "${MESSAGE}" >> "${LOG_FILE}" &
# Wait for the picture to be taken.
wait "${pid}"
# Below: put commands which need the photo as dependency.
echo "${MESSAGE}" | mail \
4 years ago
-r "${MAIL_SENDER}" \
-s "${MAIL_SUBJECT}" \
-a "${PICTURE_FILE}" \
"${MAIL_RECEIVER_ALIAS}" &
popd
```
## Instructions
### Installation
- Configure the network in `/etc/network/interfaces`
- Install the software
```
# apt-get update
# apt-get dist-upgrade
# apt-get install alsa-utils fswebcam openssh ntp s-nail msmtp sox bc alsa-utils bash espeak haveged webfs
```
- Add a user and its password
```
# useradd -U -m -s /bin/bash doorbell
4 years ago
# passwd doorbell
# exit
```
- Login with the newly created user and copy the scripts
```
$ mkdir ~/srv_maint/scripts/doorbell
$ cp listen.sh shoot.sh ~/srv_maint/scripts/doorbell
```
- Add a cron entry so that the scripts runs automatically at every boot.
```
$ echo "@reboot /home/doorbell/srv_maint/scripts/doorbell/listen.sh" > ~/srv_maint/cron_entries.txt
$ crontab ~/srv_maint/cron_entries.txt
```
- Touch and prepare the log file
```
# touch /var/log/doorbell.log
# chown doorbell:doorbell /var/log/doorbell.log
```
- [Configure the mail system](https://wiki.archlinux.org/index.php/Msmtp#Using_the_mail_command). See [this](https://wiki.archlinux.org/index.php/Msmtp#Using_msmtp_offline) also.
- Configure webfs in `/etc/webfsd.conf`. Once everything is set up you may
run the shoot.sh script and `$ wget http://<doorbell_computer_address>/doorbell.jpg`
```
# debian config file for webfsd. It is read by the start/stop script.
# document root
web_root="/var/www"
# hostname (default to the fqdn)
web_host=""
# ip address to bind to (default: any)
web_ip=""
# port to listen on (default: 8000)
web_port="80"
# virtual host support (default: false)
web_virtual="false"
# network timeout (default: 60 seconds)
web_timeout=""
# number of parallel connections (default: 32)
web_conn=""
# index file for directories (default: none, webfsd will send listings)
web_index=""
# size of the directory cache (default: 128)
web_dircache=""
# access log (common log format, default: none)
web_accesslog=""
# use bufferred logging (default: true)
web_logbuffering="true"
# write start/stop/errors to the syslog (default: false)
web_syslog="false"
# user/group to use
web_user="www-data"
web_group="www-data"
# cgi path (below document root -- default: none)
web_cgipath=""
# extra options, including arguments
web_extras=""
```
#### Calibration
10 months ago
- Use `$ alsamixer` to set the audio levels. The hardest part was finding a
working interval for the amplitude and frequency values through which the
4 years ago
script is able to avoid as much false positives as possible.
- [Fix the desired audio level for the next reboots](https://unix.stackexchange.com/questions/210113/default-sound-volume-for-all-alsa-devices)
```
# alsactl store
```
## Possible roadmap
4 years ago
- Version 0.0: this version.
- Version 0.1: discontinue the Thinkpad A31 and use the Raspberry PI instead
10 months ago
with an (full HD?) IR camera module and its extension cord to reach out of
the door. This should free the USB hub that we must use for the audio
trigger (a usb microphone or USB audio card connected to the analog
4 years ago
microphone).
10 months ago
- Version 0.2: instead of using an audio trigger, use some kind of sensor. Our
doorbell transforms the electrical current to piston movement against two
4 years ago
metal bars that vibrate at a certain frequency, which in turn produce
10 months ago
sound. This new yet unkown method should always be reliable and avoid any
4 years ago
false positive.
10 months ago
- Version 0.3: add an open-close door sensor which interfaces to the GPIO. Use
4 years ago
a USB camera once this trigger activates.
10 months ago
- Version 0.4: adapt all this stuff so that it works with something like [Home
4 years ago
Assistant](https://www.home-assistant.io/) or [Kalliope](https://kalliope-project.github.io/).
~