Alarm Security System with Raspberry Pi
Created by:
This project is born from the necessity of an affordable article that gives users the possibility to monitor and get notice of any event that may happen in places that are important to prevent any vandalism or burglary.This article has to have a high performance and provide the option to check the cameras from any location through Internet. The Raspberry Pi was chosen because of its low cost and because the new camera module gives good images with high resolution.
In first place, because the RPi has to function as camera all the time, a script was created to initialize the video streaming when it's turned on.
#!/bin/sh ###BEGIN INIT INFO # Provides: Raspivid-netcat # Required-Start:$remote_fs $syslog # Required-Stop: $remote_fs $syslog # Description: It starts the Raspberry Pi Camera using raspivid command # and sends it to a server using netcat directed to an especific # IP. ###END INIT INFO . /lib/lsb/init-functions RETVAL=0 prog="/etc/init.d/streaming" start() { echo "Starting video streaming" /usr/bin/raspivid --nopreview -t 0 -o - | /bin/nc [server IP] 5001 RETVAL=$? return $RETVAL } stop() { echo "Stopping streaming" killall raspivid RETVAL=$? return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status_of_proc $prog RETVAL=$? ;; *) echo "Usage: /etc/init.d/streaming {start|stop|status|restart}" RETVAL=1 ;; esac exit $RETVAL
This code has to be saved in the directory /etc/init.d as an executable that starts working when the system boots up.
chmod 755 /etc/init.d/streaming update-rc.d streaming defaults
This is a module that is included in Python and is a straightforward transliteration of an Unix system call and library. For more information visit : http://docs.python.org/2/library/socket.html
Is a video capture and output driver framework for Linux that supports many USB webcams, TV tuners, and other devices. This driver was selected because ZoneMinder supports v4L, what gives a facility of communication between the programming needed for this project and the progress was done in the first part of the entire project.
In this case the loopback device is used to create a virtual video device in the server that gets the stream coming from the camera (RPi) and “converts” it to a device that ZoneMinder will perceive as other camera inside the server.
To capture the video stream coming from the RPi, there was a code written in Python that creates a socket that receives the data from the camera. Once the data is received, it is passed through a module called video loopback device that creates a “virtual” device in the computer that simulates a real physical device inside the computer that receives the stream. Finally it is send to the device with video 4 linux; this is going to be the device that is added as a monitor in ZoneMinder. The main program for capturing is cap.image.py and the setup of the capture is established in capimagesetup.py.
#! /usr/bin/env python from capimagesetup import CapImageSocket from time import time, sleep import sys import gc from optparse import OptionParser def main(): host = '' port = 5001 device = "/dev/video1" vstart = 0 vend = 1048576 * 8 vblock = 1024 parser = OptionParser() parser.add_option("-d", "--device", dest="device", help="v4l loopback device filename", default="/dev/video1", metavar="FILE") (options, args) = parser.parse_args() cis = CapImageSocket() cis.init(host, port, vstart, vend, vblock, device) if __name__=="__main__": main()
#!/usr/bin/env python #server recieves the data from fcntl import ioctl import socket import os import commands import v4l2 as v from time import sleep from fcntl import ioctl from time import time, sleep import weakref import numpy as n class CapImageSocket(): def init(self, host, port, vstart, vend, vblock, device): self.v4l_device = device self.host = host self.port = port s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((host, port)) s.listen(5) conn, addr = s.accept() print "connected by",addr self.d=os.open(self.v4l_device, os.O_RDWR) cap=v.v4l2_capability() ioctl(self.d, v.VIDIOC_QUERYCAP, cap) vid_format=v.v4l2_format() vid_format.type=v.V4L2_BUF_TYPE_VIDEO_OUTPUT vid_format.fmt.pix.width=1920 vid_format.fmt.pix.sizeimage=1036800 vid_format.fmt.pix.height=1080 vid_format.fmt.pix.pixelformat=v.V4L2_PIX_FMT_YUYV vid_format.fmt.pix.field=v.V4L2_FIELD_NONE vid_format.fmt.pix.colorspace=v.V4L2_COLORSPACE_SRGB ioctl(self.d, v.VIDIOC_S_FMT, vid_format) self.old_t=time() t=time() delta_time=t-self.old_t self.old_t=t out='' count = 0 while True: print "cycling", count out=conn.recv(1036800) os.write(self.d, out) count += 1
In order to have a higher efficiency, a script similar to the streaming script was created. This script initializes the video capturing in the server in the moment it boots up.
#!/bin/sh ###BEGIN INIT INFO # Provides: Video capture coming from Rpi # Required-Start:$remote_fs $syslog # Required-Stop: $remote_fs $syslog # Description: It starts a Python script that is listening to a video stream # coming from a Raspberry Pi and introduces it to a Loopback Device. ###END INIT INFO . /lib/lsb/init-functions RETVAL=0 prog="/home/nole/Documents/UCR/Plataformas/Codigo/capimage.py" start() { echo "Starting video capturing" /usr/bin/python [Path to the capture program]/capimage.py RETVAL=$? return $RETVAL } stop() { echo "Stopping video capturing" killall python [Path to the capture program]/capimage.py RETVAL=$? return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; status) status_of_proc $prog RETVAL=$? ;; *) echo "Usage: /etc/init.d/capturing {start|stop|status|restart}" RETVAL=1 ;; esac exit $RETVAL
The monitoring in the RPi is achieved through a script written in Python that checks the connection with the server by doing a “ping” constantly. In case the “ping” is not possible, it reestablishes the connection to the network and sends a restart to the script that starts the video stream from the RPi camera. If the network is working fine, it just checks the status of the stream and repairs it if it's broken.
#!/usr/bin/env python import subprocess import os import time while True: a = subprocess.call(['/bin/ping', '-c1', '[server IP]']) if(a != 0): os.system('sudo ifdown eth0') b = os.system('sudo ifup eth0') if(b == 0): c = os.system('sudo /etc/init.d/streaming status') if(c != 0): os.system('sudo /etc/init.d/streaming restart') else: c == 0 else: b != 0 else: d = os.system('sudo /etc/init.d/streaming status') if(d != 0): os.system('sudo /etc/init.d/streaming restart') else: d == 0
This script checks if the server has connection with the network. If the connection fails, it reestablishes it and restarts the program that captures the video stream coming from the RPi. If the connection works, it just checks the status of the capture program and restarts it in case it's not working.
#!/usr/bin/env python import subprocess import os import time while True: a = subprocess.call(['/bin/ping', '-c1', '[RPi IP]']) if(a != 0): os.system('sudo ifdown wlan0') b = os.system('sudo ifup wlan0') if(b == 0): c = os.system('sudo /etc/init.d/capturing status') if(c != 0): os.system('sudo /etc/init.d/capturing restart') else: c == 0 else: b != 0 else: d = os.system('sudo /etc/init.d/capturing status') if(d != 0): os.system('sudo /etc/init.d/capturing restart') else: d == 0
The server has to be connected to Internet all the time to ensure that the users can access to their camera system from any location. This watchdog tests the connection to a website that the user prefers and if it can't connect it repairs the connection.
#!/usr/bin/env python import subprocess import os while True: a = subprocess.call(['/bin/ping', '-c1', '[Desired web page]]) if(a != 0): os.system('sudo ifdown eth0') os.system('sudo ifup eth0') else: a == 0
The Watchdogs have to start running as soon as the system boots up. One option is to create an init script similar to the streaming or capturing scripts that executes the watchdogs. To do this, the watchdogs must be executable and the init script has to run the following command:
./conn_server.py
or
python conn_server.py
Other option is to add the same command lines in the .bashrc file of the system in order to execute on startup.
The hardware watchdog that comes embedded in the RPi is a watchdog timer that is used to detect when a running software is hung up on a task and if this happens it resets it. The first step to activate the watchdog is to load the watchdog kernel module by adding:
bcm2708_wdog
to the /etc/modules file. Then follows the installation of the software watchdog daemon:
sudo apt-get install watchdog
To make sure it runs in every boot then run the command:
sudo update-rc.d watchdog defaults
To configure the watchdog daemon open /etc/watchdog.conf and uncomment the line that starts with #watchdog-device and the line #max-load-a=24 to reboot the device if the load goes over 24 over 1 minute. Finally, to start the watchdog daemon:
sudo /etc/init.d/watchdog start
After exhaustive investigation, the option of creating an init script in the Raspberry Pi to start sending a video stream on boot was the most efficient and safe choice. This also allows the user to stop the stream by accessing the RPi remotely to fix any problems or in case they want to remove the camera. The video stream coming from the RPi camera is in h264 format that needed to be decoded in order to use it as a camera in ZoneMinder, this hasn't been completed and is pending in order to obtain the complete functionality that was proposed at the beginning of the project.
For the watchdogs in the server and the RPi, the os and subprocess modules made the task easier because they gave the option of using code that is similar to running console commands. The init scripts created for streaming and capturing provide the status of the program in order to give the watchdogs the information necessary to control the execution of the surveillance system. This scripts are capable of fixing any problem presented that is related with the communication between the server and the RPi in almost any given situation.
After developing a series of tests, the connection the gave the best results was through Ethernet, specially on the RPi. The server worked well with wireless connection, even though the servers are usually connected to the network via Ethernet.
The first objective proposed was to communicate the RPi with the server via network connection. It was possible to create a communication and data transfer between the RPi and the server and observe the video coming from the RPi camera module.
The original system was improved by means of watchdogs and init scripts that provided autonomy and efficiency to the RPi used ans the camera and to the server that is expected to work all the time. The init scripts worked as expected, as well as the watchdogs created in Python.
After the decoding of the video is achieved this will be an efficient low cost system that allows the possibility of having a high resolution video surveillance system. Other systems that are similar to this are over prized and many of them don't give the user the option of accessing the videos from any location.