How to Build a Surveillance System with Raspberry Pi 3 and camera

Learn how to build a Raspberry surveillance system in this guest post by Maneesh Rao, the author of Internet of Things with Raspberry Pi 3.

Before proceeding to code the Surveillance System with Raspberry Pi 3, you need to install Node.js on your Raspberry Pi 3. Log in via SSH, and update your Raspberry Pi system packages to their latest versions. Update your system package list:

[bash]pi@w3demopi:~ $ sudo apt-get update[/bash]

Upgrade all your installed packages to their latest version:

[bash]pi@w3demopi:~ $ sudo apt-get dist-upgrade[/bash]

To download and install the latest version of Node.js, use the following command:

[bash]pi@w3demopi:~ $ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -[/bash]

Now install it by running the following command:

[bash]pi@w3demopi:~ $ sudo apt-get install -y nodejs[/bash]

Check the version number and whether the installation was successful with the following command:

[bash]pi@w3demopi:~ $ node –v[/bash]

Now that Node.js has been installed on your Raspberry Pi, you can now start with the coding the Raspberry surveillance system.

Coding the Raspberry Pi camera module

The first step to build the Raspberry surveillance system is using the camera. You need to include a library from npm. Use the pi-camera library; to install it, run the command in the terminal, as shown below. Check out the official link for the pi-camera npm module at https://www.npmjs.com/package/pi-camera:

Now, create a file with the name, CameraModule.js, and include the pi-camera module in it:

[javascript]const PiCamera = require(‘pi-camera’);[/javascript]

As per the documentation of the pi-camera module, you need to set the configuration of the camera. You have to define two configurations, one for taking still pictures and one for taking videos:

[javascript]const myCameraPhoto = new PiCamera({
mode: ‘photo’,
output: `/home/pi/Node_Programs/photos/photo.jpg`,
width: 640,
height: 480
});

const myCameraVideo = new PiCamera({
mode: ‘video’,
output: `/home/pi/Node_Programs/videos/video.h264`,
width: 1920,
height: 1080,
timeout: 5000
});[/javascript]

In both the configurations, the following aspects are defined:

  • A mode that defines whether the camera takes still photographs or a video. Note that the video is created in the h246 format, which is the raw format, and can be played on quite a few popular video players, including VLC media player.
  • The output, which defines the path where the photo or video will be saved in local storage.
  • The height and width, which define the resolution.
  • Timeout (only in case of videos) defines the length of the video that will be recorded.

Define a cameraInUse flag and set it to false by default. This flag ensures that the camera doesn’t accept any further requests when taking pictures or recording a video. This is to prevent any consequent errors while loading the camera:

[javascript]var camerInUse = false;[/javascript]

Now, define a function that will take a picture when called. This function takes callback as an argument and returns a success message when the picture is clicked successfully.

More useful resources

Raspberry Pi IoT: Sensors, InfluxDB, MQTT and Grafana

Python Tools for Raspberry Pi: Unleash the power of Python

Note that module.exports is used to define the function, which will make this function available when CameraModule.js is included (imported) in other modules.

[javascript] module.exports.takePicture = function (callback){
if (camerInUse == false) {
camerInUse = true;
myCameraPhoto.snap()
.then((result) => {
console.log(‘Your picture was captured’)
callback(‘success’)
camerInUse = false;
})
.catch((error) => {
console.log(error.toString());
callback(error.toString());
});
}
else {
console.log(‘camera in use..’)
}
}[/javascript]

Before taking a picture, the code checks the value of the cameraInUse flag and starts the camera only if the flag is set to false. Once the camera starts taking photos, the flag is set to true so that no further requests are accepted for the camera until it is done clicking pictures.

Similarly, define a function that will record the video when called:

[javascript] module.exports.takeVideo = function (callback) {
if(camerInUse == false){
camerInUse = true;
myCameraVideo.record()
.then((result) => {
console.log(‘recording completed…!!’);
callback(‘success’)
camerInUse = false;
})
.catch((error) => {
console.log(error.toString());
});
}
else{
console.log(‘camera in use..’)
}
}[/javascript]

Coding the Raspberry Pi email module

The next step to build the Raspberry pi surveillance system is the email module. It is used to send email notifications whenever a trespasser enters the premises along with evidence in the form of a video or photograph. To accomplish this task, use the npm module nodemailer. Download this by running the npm install nodemailer command in the terminal as shown below. Check out the official link for the nodemailer npm module at https://www.npmjs.com/package/nodemailer:

Create a file with the name, EmailModule.js, and include the nodemailer module in it:

[javascript] var nodemailer = require(‘nodemailer’);
[/javascript]

Now, set the transport configuration for the email module by providing the details of the email service provider, the email ID from which the email will be sent, and its username and password:

[javascript] var transporter = nodemailer.createTransport({
service: ‘gmail’,
auth: {
user: ‘YOUR_EMAIL_ADDRESS’,
pass: ‘PASSWORD’
}
});
[/javascript]

Next, set the email options for sending the email with the video and photo as attachments:

[javascript] const videoMailOptions = {
from: YOUR_EMAIL_ADDRESS’,
to: ‘RECEPIENT_EMAIL_ADDRESS’,
subject: ‘Intruder in your Castle…!!’,
html: ‘Some one is trying to steal your gold…!!’,
attachments: [{
filename: ‘IntruderVideo.h264’,
path: ‘/home/pi/Node_Programs/videos/video.h264’
}] };
[/javascript]

Here, the following are defined:

  • from: This is the email address of the sender of the email
  • to: This is the email address of the email recipient
  • subject: This is the subject line of the email being sent
  • Html: This is the content of the email
  • attachments: This includes the following elements:
    • filename: Here, you can set the name of the file that is sent as an attachment
    • path: This is the local file storage path from where the file will be picked for attachment

Similarly, define the email option for sending still photos as shown in the following block of code:

[javascript] const photoMailOptions = {
from: YOUR_EMAIL_ADDRESS’,
to: ‘RECEPIENT_EMAIL_ADDRESS’,
subject: ‘Intruder in your Castle…!!’,
html: ‘Someone is trying to steal your gold…!!’,
attachments: [{
filename: ‘IntruderImage.jpg’,
path: ‘/home/pi/Node_Programs/photos/photo.jpg’
}] };
[/javascript]

Now, write functions that will send the email whenever triggered:

[javascript] module.exports.sendMailVideo = function () {
transporter.sendMail(videoMailOptions, function (err, info) {
if(err){
console.log(err.toString());
}
else{
console.log(‘Video email success..!!’);
}
});
}

module.exports.sendMailPhoto = function (){
transporter.sendMail(photoMailOptions, function (err, info) {
if(err){
console.log(err.toString())
}
else{
console.log(‘Photo email success..!!’);
}
});
}
[/javascript]

Coding the Raspberry Pi Sensor module

The most important step in building a Raspberry surveillance system is handling the sensor. Now, it’s time to write the code for sensor modules, which will govern the functioning of all the sensors and LEDs. To accomplish this task, you need an npm module called pigpio, which gives access to the GPIO of Raspberry Pi. To install the pigpio module, run the sudo npm install pigpio command in the terminal as shown below:

raspberry pi surveillance system

Check out the official npm link at https://www.npmjs.com/package/pigpio for more details about the pigpio module.

Create a file with the name, Survillance.js, and include the pigpio module. Also include CameraModule.js and EmailModule.js, which you developed just now. This will give access to the functions of each module for taking pictures, videos, and sending emails:

[javascript] var GPIO = require(‘pigpio’).Gpio,
cameraModule = require(‘./CameraModule’),
emailModule = require(‘./EmailModule’);
[/javascript]

Make sure that Survillance.jsEmailModule.js, and CameraModule.js are placed in the same directory. Initialize the Raspberry Pi’s pins for reading out and sending signals to sensors and LEDs:

[javascript] var PIR_out= new GPIO(19,{mode: GPIO.INPUT,alert: true}),
red_LED= new GPIO(17,{mode: GPIO.OUTPUT}),
buzzer= new GPIO(26,{mode: GPIO.OUTPUT}),
IR_out= new GPIO(5,{mode: GPIO.INPUT,alert: true}),
trigger = new GPIO(16, {mode: GPIO.OUTPUT}),
echo = new GPIO(21, {mode: GPIO.INPUT, alert: true});
[/javascript]

The PIR sensor’s output (PIR_out) is connected to GPIO 19, so declare GPIO 19 as the input and set the alert event flag to true. The alert event indicates that an alert event will be raised whenever the value at the GPIO changes from low (0) to high (1) or vice versa. You can listen to the alert event and take action accordingly. This is important to build a Raspberry surveillance system.

The positive terminal of LED (red_LED) is connected to GPIO 17. The LED will work as an indicator; whenever a trespasser is detected, the LED will glow. GPIO 17 is set as the OUTPUT pin.

The buzzer is connected to the Pi with one of its terminals connected to GPIO 26 and the other connected to the ground. The buzzer is used to raise an alarm when an intruder is detected, so set GPIO 26 as OUTPUT.

The infrared sensor’s output (IR_out) is connected to GPIO 5, which is declared as the INPUT pin, and the alert event flag is set to true.

The trigger terminal of the ultrasonic sensor is used to generate high-frequency ultrasonic waves. The trigger pin is connected to GPIO 16, so declare it as the OUTPUT pin.

The echo pin of the ultrasonic sensor is connected to GPIO 21. The echo pin is used to get the output of the ultrasonic sensor, so it is declared as INPUT and the alert event flag is set to true.

Make sure you initialize the LED to low level (0):

[javascript] red_LED.digitalWrite(0);
[/javascript]

First, write the code block to read the data of the PIR sensor:

[javascript] PIR_out.on(‘alert’, function(level, tick){
if(level==1) {
cameraModule.takePicture(function (callback) {
var result = callback;

if (result == ‘success’) {
emailModule.sendMailPhoto()
}
})
console.log(‘PIR : Intruder Alert..!!’)
red_LED.digitalWrite(level);
buzzer.digitalWrite(level);
}
else {
red_LED.digitalWrite(level);
buzzer.digitalWrite(level);
}
})
[/javascript]

Here, listen to the alert event for the PIR sensor. As soon as the PIR sensor detects any trespasser in the house, the output goes high from the initial low state, which causes an alert event to fire. This is the most important step because the PIR sensor detects motion that is the base of our Raspberry surveillance system.

The alert function returns a callback with two parameters: one is level and the other one is tick. The level parameter indicates the state of the GPIO at that moment and tick is the timestamp at which the change in state is observed at the GPIO. So, the alert event is checked and if the level is high (1), then the takePicture function of the camera module is called to click a photo of the trespasser immediately.

Then, the output of the buzzer and LED indicator is set to high to raise the alarm. Once the success callback is received from the camera module’s takePicture function, the sendMailPhoto function of the email module is called, which sends the alert email along with the photo of the trespasser to the owner of the house.

Now, write the code for the IR sensor, which is very much similar to the PIR sensor code:

[javascript] IR_out.on(‘alert’, function(level, tick){
if(level==1){
cameraModule.takeVideo(function (callback) {
var result = callback;
if(result == ‘success’){
emailModule.sendMailVideo() ;
}
})
console.log(‘IR : Intruder Alert..!!’
red_LED.digitalWrite(level);
buzzer.digitalWrite(level);
}
else {
red_LED.digitalWrite(level);
buzzer.digitalWrite(level);
}
})
[/javascript]

An IR sensor works in the exact same way as the PIR sensor. The only difference is that it records a video instead of taking a still photo.

Lastly, it’s time to write the code block for the ultrasonic sensor module:

[javascript] trigger.digitalWrite(0);
var MICROSECDONDS_PER_CM = 1000000/33000;
// Trigger a distance measurement once per second
setInterval(function () {
trigger.trigger(10, 1); // Set trigger high for 10 microseconds
}, 5000);

//The number of microseconds it takes sound to travel 1cm at 20 degrees celcius
var startTick;
echo.on(‘alert’, function (level, tick) {
var endTick,
diff;

if (level == 1) {
startTick = tick;
}
else {
endTick = tick;
diff = (endTick >> 0) – (startTick >> 0); //Unsigned 32-bit arithmetic
var actualDist = (diff / 2 / MICROSECDONDS_PER_CM) ;
if (actualDist < 10){
console.log(‘Ultrasonic : Intruder Detected…!!’)
red_LED.digitalWrite(1);
buzzer.digitalWrite(level);
cameraModule.takePicture(function (callback) {
var result = callback;
if (result == ‘success’){
emailModule.sendMailPhoto()
}
})
}
else {
red_LED.digitalWrite(0);
buzzer.digitalWrite(0);
}
}
});
[/javascript]

Making use of the trigger function of the pigpio module, a high-pulse is sent to the trigger pin of the ultrasonic sensor for 10 microseconds, which causes the sensor transmitter to emit a burst 8 high-frequency pulse, which makes the output at the echo pin high.

The output of the ultrasonic sensor is taken from the Echo pin on which you are listening for the alert event. As soon as the ultrasonic wave is transmitted, the state of the Echo pin changes to high and the alert event is fired, which returns a callback with two parameters. The first is the level, which is used to check whether the state of echo is high (1) or low (0) and the other is tick, which is used to check the timestamp when the state changed.

The state of the echo is changed from low to high and this timestamp is saved as startTick. When the waves get reflected from obstruction and fall on the receiver, the state of the Echo pin is changed from high to low. This timestamp is saved as endTick. Now, to get the distance of obstruction from the sensor, you need to record the time taken by the ultrasonic waves to travel to and from the sensor—subtract startTick from endTick. The tick is the number of microseconds since system boot. Its value is an unsigned 32-bit quantity. So, to get the correct value after subtraction, use the right shift operator. Once you have the travel time, you can then calculate the distance.

Once you have the distance, check whether the distance is less than 10 cm. If it is, raise an alert by lighting the LED, beeping the Buzzer, taking a picture, and finally sending the alert through email.

The code part is finally completed. Execute the code by running the following command in the terminal:

[bash]sudo node Survillance.js[/bash]

This is the output for the PIR sensor:

surveillance raspberry pi 3

This is the output of the IR sensor:

This is the output of the ultrasonic sensor:

The following is a snapshot of the email notification received as an alert:

If this article intrigued you and made you want to learn more about IoT and Raspberry Pi 3, you can explore the book, Internet of Things with Raspberry Pi 3 by Maneesh Rao. The book covers several powerful features of Raspberry Pi with hands-on, practical examples, and also guides you through the nuances of building a weather station, facial recognition systems, and security surveillance systems.