====== ASSYRA ======
Alarm Security System with Raspberry Pi
Created by:
* Nohelia AlpĂzar
* Guillermo Rivera
===== Introduction =====
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.
===== Objectives =====
* Create a connection between the Raspberry Pi and a computer that has ZoneMinder, in order to access the video from the camera from any location.
* Create an script to initialize the video stream when the Raspberry Pi boots.
* Ensure the robustness of the connection of the server and the camera (RPi) using "watchdogs" that check continuously that the server, camera, and streaming are working as expected.
===== Video transmission from the Raspberry Pi to the server =====
==== Initialization script for streaming ====
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
==== Installation of Used Modules ====
=== Sockets ===
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
=== Video4Linux ===
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.
=== V4l2loopback ===
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.
==== Video capture of the Raspberry Pi stream in 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.
* capimage.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()
* capimagesetup.py
#!/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
==== Initialization script for video capture ====
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
===== "Watchdogs" monitoring the entire system =====
==== Monitoring of the connection of the RPi with the server and the streaming ====
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
==== Monitoring of the connection of the server with the Rpi and the capturing of the incoming video stream ===
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
==== Monitoring of the connection of the server to Internet ===
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
==== Running the "Watchdogs" on startup ===
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.
==== Activating the Raspberry Pi Hardware Watchdog ===
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
===== Results =====
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.
===== Conclusions =====
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.
===== References =====
*http://raspberrytank.ianrenton.com/day-14-video-streaming/
*http://code.google.com/p/pyffmpeg/
*http://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-single/v4l2.html
*https://code.google.com/p/v4l2loopback/
*https://github.com/memeruiz/usbtv007
*http://docs.python.org/2/howto/sockets.html
*http://stackoverflow.com/questions/17541044/how-can-i-make-the-python-program-to-check-linux-services
*http://www.stuffaboutcode.com/2012/06/raspberry-pi-run-program-at-start-up.html
*http://harizanov.com/2013/08/putting-raspberry-pis-hardware-watchdog-to-work/
*http://www.thegeekstuff.com/2012/03/lsbinit-script/
*http://blog.ricardoarturocabral.com/2013/01/auto-reboot-hung-raspberry-pi-using-on.html