I have set up a surveillance system, consisting of a first generation 'TL-WR1043ND'
router running Backfire, with USB-storage attached and three cheap wireless
IP-cameras from ebay. I wish to share this project with anyone interested.
The chosen cameras are from the manufacturer 'Wanscam' and features motion
detection with FTP-uploading.
For setting up USB-storage refer to the documentation in OpenWRT's wiki.
In my setup, I have a 320GB USB-disk formatted with ext4, mounted at /mnt/storage
The recording functionality depends on a FTP-server and a handful of scripts.
I chose 'vsftpd' available in the package repository.
First step is to create an user for the FTP-service. In my setup, this was done
like this:
useradd -m -N -d /mnt/storage/cctv -s /bin/false cctv
Next, set a password and configure the FTP-server. My configuration looks like
this (/etc/vsftpd.conf):
listen=YES
background=YES
check_shell=NO
listen_address=192.168.0.1
dirmessage_enable=NO
session_support=NO
syslog_enable=NO
write_enable=YES
local_enable=YES
local_umask=0402
chroot_local_user=YES
userlist_enable=YES
userlist_file=/etc/vsftpd.users
userlist_deny=NO
anonymous_enable=NO
xferlog_enable=YES
xferlog_file=/var/log/vsftpd
xferlog_std_format=YES
Note: the cameras chosen in my setup, required a chroot'ed user setup to
function. Remember to add the FTP-user to the userlist_file:
echo cctv > /etc/vsftpd.users
The logging from the FTP-server is used by the following two scripts, to
record a video stream when the cameras motion-detection is triggered.
#!/bin/sh
# file:/bin/streamtrigger
LOG=${LOG:-/var/log/vsftpd}
RUNDIR=${RUNDIR:-/var/run/cctv}
WORKDIR=${WORKDIR:-/mnt/storage/cctv}
export RUNDIR
mkdir -p ${RUNDIR}
tail -f ${LOG} |
while read line; do
set $line
ip=$7; jpg=${WORKDIR}$9
spid=${RUNDIR}/${ip}.savestream
wpid=${RUNDIR}/${ip}.wget
touch -c ${spid}
if [ ! -f ${wpid} ]; then
touch ${wpid}
start-stop-daemon -x savestream -b -S -- ${ip} ${jpg}
fi
done > /dev/null 2>&1
#!/bin/sh
#file:/bin/savestream
RUNDIR=${RUNDIR:-/var/run}
mjpg=${2%.*}.mjpg
stream="http://${1}:80/videostream.cgi?user=cctv&pwd=wanscam&rate=0"
self_pidfile=${RUNDIR}/${1}.savestream
wget_pidfile=${RUNDIR}/${1}.wget
nice wget --quiet --output-document=${mjpg} ${stream} &
pid=$!
echo $$ > ${self_pidfile}
echo ${pid} > ${wget_pidfile}
until jobs -l | grep "${pid} Done" > /dev/null 2>&1; do
if test ${self_pidfile} -ot ${wget_pidfile}; then
kill -9 ${pid}
break
fi
touch ${wget_pidfile}
sleep 10s
done
wait ${pid}
rm ${wget_pidfile} ${self_pidfile}
chown cctv ${mjpg}
chmod 264 ${mjpg}
The first script reads the FTP logfile and launches the second script and/or
update the timestamp of a pidfile every time a file is received over FTP.
The second script use 'wget' to fetch a video-stream from the given camera and
terminates 'wget' once the timestamp of said pidfile is no longer updated. This
script might need some changes to reflect a different configuration of the
cameras.
The system is started during bootup, from the following init-script:
#!/bin/sh /etc/rc.common
# file:/etc/rc.d/cctv
START=75
LOG=/var/log/vsftpd
RUNDIR=/var/run/cctv
WORKDIR=/mnt/storage/cctv
start() {
# needed for running vsftpd chrooted
mkdir -p =/var/run/vsftpd
# exporting enviroment
export LOG RUNDIR WORKDIR
if pidof streamtrigger > /dev/null; then
echo streamtrigger is already running
pidof streamtrigger
else
if test ! -p ${LOG}; then
rm ${LOG} 2> /dev/null
mkfifo ${LOG}
fi
start-stop-daemon -x streamtrigger -b -S
fi
start-stop-daemon -x vsftpd -S
}
stop() {
killall -9 tail
killall -9 vsftpd
sleep 5s
rm ${LOG}
}
Note: the init-script belonging to 'vsftpd' is not used!
To ensure that the disk does not run out of space, I run the following
cleanup-script as a cron-job every night:
#!/bin/sh
# file:/bin/cleanup
MOUNTPOINT=/mnt/storage
WORKDIR=${MOUNTPOINT}/cctv
LOWER=10485760 # 10 x 1024^2 = 10G
cd ${WORKDIR} && for e in *; do
AVAILABLE=$(df | grep ${MOUNTPOINT} | tr -s ' ' | cut -d\ -f4)
[ -z "${AVAILABLE}" ] || [ ${AVAILABLE} -gt ${LOWER} ] && break
rm -r ${e}
done
In case there is less than 10GB available, the script will remove the oldest
surveillance data to free up some space. This script assumes that the cameras
create a folder for each day, which is the case for the chosen cameras.
A note on storage capacity: In my setup, the cameras motion-detection is set on
highest sensitivity and they upload one image (VGA resolution) per second, when
triggered. The three cameras generate approximately 3GB data in total per day.
For browsing the surveillance archive, I have written a CGI-script in Lua,
which I'll post upon request.
(Last edited by rathka on 8 Feb 2014, 23:45)