OpenWrt Forum Archive

Topic: [HowTo] OpenWRT based surveillance system

The content of this topic has been archived on 29 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

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)

Nice writeup.  You might put it in the "Community Documentation" area.  I would put HOWTO somewhere in your post so that a search on "howto surveillance" would find your thread.  Oops, with my posting, it will.

thanx. I've added [HowTo] to subject, but could not figure out how to move the post to "Community Documentation". any help would be appreciated.

@rathka, just to say thank you. Very interesting. What model camera do you recommend?

thats a pretty innovative way to rig a system up.

(Last edited by gruelius on 13 Feb 2014, 13:22)

@dmcdonnell, in my setup I'm using two Wanscam JW0011 outdoor cameras and one JW0004 indoor camera.
I wanted the three cameras to be from the same manufacturer, other than that I was aiming for the cheapest wireless IP cameras I could find on ebay. The setup should function with any IP camera featuring motion detection and FTP-upload.

Hello! After much work, since i am a newbee to linux, i have this "homemade NVR" running on my TP-Link TL-1043ND with one IP camera, and it works recording accelerated videos on motion detection. When I play these videos in slow motion, there are several frame losses at constant intervals, which leads to this accelerated playback at normal speed. Probably this happens because of low processor speed of my router, since there are other applications running on it and consuming resources. I put the startup script in init.d and enable to start with the system. But I have a doubt: in my active processes, there are two identical instances relating to this installation:

PID          Owner                             Command                                            CPU              MEM
1173          root            {streamtrigger} /bin/sh /bin/streamtrigger             0%                2%
1176          root            vsftpd                                                                       0%                2%
1180          root            tail -f /var/log/vsftpd                                                 0%                2%
1181          root            {streamtrigger} /bin/sh /bin/streamtrigger              0%                2%


Is normal two instances of streamtrigger running? I'm using Barrier Breaker 14.07.

I did something similar but without using specific surveillance cameras, I used a webcam.
My system records motion pictures and sends me a SMS message whenever a motion is detected, also it calls my mobile and lets me listen to the remote audio and  to talk through the remote speaker.

https://forum.openwrt.org/viewtopic.php?id=54722
and
https://forum.openwrt.org/viewtopic.php … 90#p253590

Youtube video:
https://www.youtube.com/watch?v=5cV3UDCnim4

http://www.lovisolo.com/asterisk/software/openwrt/Vodafone-Station-Home-Automation-Server/antifurto.jpg

http://www.lovisolo.com/asterisk/software/openwrt/Vodafone-Station-Home-Automation-Server/antifurto2.jpg

http://www.lovisolo.com/asterisk/software/openwrt/Vodafone-Station-Home-Automation-Server/relay2c.jpg

(Last edited by pilovis on 16 Mar 2015, 23:30)

@pilovis cool project, with a bit more hardware modding than I am up to smile

@mbarriles I just upgraded my setup to barrier breaker and it is still running. Had to change the vsftpd config a little to allow writeable root.
The two streamtrigger processes looks right. One is the parent process running a tail- and second streamtrigger process. The second streamtrigger process evaluates the never ending while loop fed by the tail process.

Thanks for the reply rathka. As the videos were getting bad, i decided to buy a raspberry pi 2 to run my NVR based on motion. My old TL-1043ND it was not enough to run my services. I got to run a NVR with a modified version of motion (ffmpeg enabled) in the tp-link, but it consumed all resources. Raspberry 2 already has enough power to run all my services, allowing leave the tp-link only for wi-fi due to its strong signal.

The discussion might have continued from here.