Wednesday, February 5, 2014

Do it yourself security camera system

How you can build a security camera system that has a live video preview, motion detection, email notifications and uploads snapshots to the cloud?

Though you easily can go and purchase one for something under $100, if you know a bit of Linux you can build one yourself. In fact, it will be cheaper and will give you power of customization - so you can make it better than one out-of-the-box.

Pogoplug E02         $15 
USB Wifi adaptor     $10
USB Flash drive 8G   $10
USB HD Webcam***     $20
Total                $55

*** Here you can make it more expensive, or less: you can buy non-HD camera for $5 or have something with superior quality starting at $40. Also you can connect two cameras to the system directly, or even more if you add a powered USB hub.


REALLY helpful tutorial on Pogoplug, I used a lot of information from it for this blog post: Qui's techNOLOGY Blog. The blog post is based on Arch Linux ARM project Pogoplug v2 (Pink/Gray)

What is Pogoplug

ARM based computer, you can install Arch Linux on it.

CPU: 1.2GHz
RAM: 256Mb
4 USB ports
1 Ethernet port. 

And... much cheaper than Raspberry Pi, you can buy one for just $15 dollars with free shipping (link above)

Let's start

Better start at small home network, which you can easily scan with tools like nmap. Because when you connect Pogoplug to the network there is no way to find its address other than just scan network for it.

So you can network before and after you connect Pogoplug, and check for difference. For example if your network is I have this as default using my Comcast router
nmap -sn

Once you find a new IP, you pretty much need to follow tutorial at Qui's blog.
Let's say IP is, ssh as root, default password is "ceadmin"

ssh root@
password: ceadmin

# Stop the Pogoplug software
killall hbwd

# Install UBoot - E02 only
cd /tmp
chmod +x

# Would you like to disable the Pogoplug services? 
# answer 'Y'

Now plug in USB drive to the slot next to Ethernet, it should appear as /dev/sda
You need at least 4 GB, but it will only be enough to play with it. Better to have 16 GB.

Partitioning and formatting flash drive

I suggest to create two partitions, root and swap. Qui's blog does not say so. But since the unit has just 256Mb RAM, I thought it would be good to have 1GB swap partition.

/sbin/fdisk /dev/sda

Check manual how to use it to create partitions.
Here is the result. 
Disk /dev/sda: 16.0 GB, 16008609792 bytes
255 heads, 63 sectors/track, 1946 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks  Id System
/dev/sda1               1        1820    14619118+ 83 Linux
/dev/sda2            1821        1946     1012095  82 Linux swap

Note file file system types 83 and 82. 
also root partition should be first /dev/sda1, otherwise device will not boot.

If you want to partition in non-interactive mode, you can do something like this:
echo -e "o\nn\np\n1\n\n+15G\nn\np\n2\n\n\nt\n2\n82\nw\np\n" | fdisk /dev/sda

Unfortunately there is no better tool available for Pogoplug OS

Now formatting the drive, you will need to download mke2fs to do this
cd /tmp
chmod 755 mke2fs
./mke2fs -L ROOTFS -j /dev/sda1
mkdir -p /tmp/usb
mount /dev/sda1 /tmp/usb

Installing Arch Linux

Basically all what this does - you download a pre-baked "image" onto USB drive. Then you boot from it and upgrade to latest version:
cd /tmp/usb
tar -xzvf ArchLinuxARM-armv5te-*.tar.gz
rm ArchLinuxARM-armv5te-*.tar.gz
cd ..
umount /tmp/usb
busybox reboot

After reboot, generally the unit should come up on the same IP address. Otherwise you will need to scan your network again using nmap like at the beginning.

Login as root, default password is "root"

ssh root@
password: root

If you were able to do this, congratulations! I was also so glad when I first did this and it worked!
Now you need to upgrade to the latest version.

pacman -Sy linux-kirkwood linux-kirkwood-headers ntp yaourt base-devel nano wget

Accept defaults, but when it asks "Remove linux?" select "y"
After it complete proceed with most basic necessary steps

Full log

Enable swap

mkswap /dev/sda2
swapon /dev/sda2
echo "/dev/sda2 none swap defaults 0 0" >> /etc/fstab 

set timezone, use "timedatectl list-timezones" to get available values

timedatectl set-timezone America/Los_Angeles

Pogoplug has no hardware clock, to every time you reboot the time will be set to some date in 1969. Enable ntpd to fix time. By default it is not enabled.

systemctl enable ntpd
systemctl start ntpd

Couple more tricks is needed:

Check /usr/lib/systemd/system/ntpd.service. Edit it to have -qg in the ntpd startup line. Refer to this post I found about it.

ExecStart=/usr/bin/ntpd -qg -u ntp:ntp -p /run/

Also as per Qui's blog you can set it to sync time on network start:

echo "ExecUpPost='/usr/bin/ntpdate -u'" >> /etc/netctl/eth0

Next steps are as as per Qui's blog, check it for more details and variants. Below are commands that I executed on my Pogoplug E02

#Add ROOTFS to fstab so fsck will run when needed
echo "LABEL=ROOTFS / ext3 rw,noatime 0 1" >> /etc/fstab

pacman -Sy uboot-env
echo "/dev/mtd0 0xc0000 0x20000 0x20000">>/etc/fw_env.config

#Have uboot mount partition as ext3 
#safer in power outages
#E02 only, V4 defaults to ext3 already
fw_setenv usb_rootfstype ext3
#Correct machid - make LED Green versus Orange
#Only for E02
fw_setenv machid dd6


Now basic installation is complete. From this step you have a unit that you can shape to your need. I decided to make it a security system with two cameras

Making it a security camera system

This is how is looks now
- front side with Wifi adaptor:

 - back side with USB flash drive

Wifi setup

(here I get into some troubleshooting)

I remember that I purchased some cheap wifi USB adaptor at Fry's several years back, and almost did not use it. I was lucky I did not lose this small thingy, that's so easy if it's not plugged in somewhere.

Hoping for the best I plugged it in, followed "Wireless Configuration" section of Qui's blog post 

#install netctl and related packages
pacman -Sy wireless_tools netctl ifplugd wpa_actiond dialog

#Connect to wireless network and create wireless profile
cd /etc/netctl

and.... It did not work right away. Apparently system did not recognize it as wifi adaptor :(

But it does see it as a USB device, this is better:

# lsusb
Bus 001 Device 005: ID 0411:014f BUFFALO INC. (formerly MelCo., Inc.) 
Bus 001 Device 003: ID 13fe:3623 Kingston Technology Company Inc. 
Bus 001 Device 002: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Googling of 0411:014f, Buffalo WLI-UC-GN revealed a potential chipset it uses - Ralink 2870, and Arch Linux has a driver for it - rt2800usb. But the driver just does not know about device ID: 0411:014f.

Here is how it can be fixed:

# load needed driver
modprobe rt2800usb 

# add ID of wifi adaptor 0411:014f from lsusb command output
echo 0411 014f > /sys/bus/usb/drivers/rt2800usb/new_id

# check how it worked

# start wifi
systemctl start netctl-auto@wlan0.service

I guess this technique can be used to make almost any adaptor to work. Most hard thing here will be find correct chipset and driver name

Wireless configuration, it can be generated using "wifi-menu" wizard like in Qui's blog, but you also can just create a config file, like this way:

cat > /etc/netctl/wlan0-your_network_name << EOF
Description='Wifi profile for your_network_name'

Also patch for wifi driver does not persist reboot. So you will need to execute it at boot time. Here is what I end up with - created a service:

cat > /usr/lib/systemd/system/buffalo-wifi.service << EOF


And script for fixing driver, used by service. You also can put all these commands directly into service file, but I did not spend much time fixing syntax for it:

cat > /usr/bin/buffalo-wifi << EOF
/usr/bin/modprobe rt2800usb 
/usr/bin/echo 0411 014f > /sys/bus/usb/drivers/rt2800usb/new_id
/usr/bin/systemctl start netctl-auto@wlan0.service

Set correct permissions and enable service to start at boot time:

chmod +x /usr/bin/buffalo-wifi
systemctl start buffalo-wifi
systemctl enable buffalo-wifi

Install httpd

pacman -S apache
systemctl enable httpd
systemctl start httpd

Some additional configuration in next section

Motion WebCam

pacman -S motion x264 fswebcam

Configuration is in /etc/motion/motion.conf, here is what I changed from defaults:

# Restrict webcam connections to localhost only (default: on)
webcam_localhost off

# Image width (pixels). Valid range: Camera dependent, default: 352
width 1280

# Image height (pixels). Valid range: Camera dependent, default: 288
height 720

# TCP/IP port for the http server to listen on (default: 0 = disabled)
control_port 0

# The mini-http server listens to this port for requests (default: 0 = disabled)
webcam_port 8090

# set palette to MJPEG, turn on compression to use less bandwidth of USB hub
v4l2_palette 2

# disable storing video fragments (does not work properly from my point of view)
# Use ffmpeg to encode mpeg movies in realtime (default: off)
ffmpeg_cap_new off

# Target base directory for pictures and films
# Recommended to use absolute path. (Default: current working directory)
target_dir /srv/http/motion/camera

Create folders:

mkdir -p /var/run/motion
mkdir -p /srv/http/motion/camera

Auto start Motion:

cat > /etc/systemd/system/motion.service << EOF
Description=motion camera

ExecStartPre=/usr/bin/fswebcam -r 320x240 -d /dev/video0 -v /dev/null
ExecStart=/usr/bin/motion -c /etc/motion/motion.conf


systemctl enable motion

Try starting it manually to see that there are no errors:

fswebcam -r 320x240 -d /dev/video0 -v /dev/null
motion -n -c /etc/motion/motion.conf 

Start service:

systemctl start motion

httpd configuration to proxy camera stream at 8090 as /motion/video0/ on port 80

cat >> /etc/httpd/conf/httpd.conf << EOF 
ProxyPass /motion/video0/ http://localhost:8090/

Add some password protection to folder "/motion", for example basic authentication. Look apache docs for more details 

<Directory "/srv/http/motion">
    AuthType Basic
    AuthName "Motion"
    AuthBasicProvider file
    AuthUserFile /etc/httpd/conf/passwd
    Require user motion

Add user "motion" with a password:

htpasswd -c /etc/httpd/conf/passwd motion
New password: 
Re-type new password: 
Adding password for user motion

Create a basic HTML page, that shows video and links to folder with pictures

cat > /srv/http/motion/index.html << EOF
<a href="camera/?C=M;O=D"><img src="video0/"/></a>

Restart httpd to pick our configuration changes

systemctl restart httpd

Check how it works:

http://<Pogoplug IP>/motion/