Wednesday, 25 February 2015

Security Webcam: (Improve) Uploading Photo to Dropbox with a Linux Board


Recently I bought a used webcam Microsoft Lifecam HD3000 on ebay.
I was interested in this device because it is Linux compatible and it can be used with one of my linux boards: Arduino Yun.



I was interested to use the Webcam, the Yun and a Pir Sensor to make a rudimental security camera system for my home.

If you are interested in this type of activity, you can find a lot of material, just "googling" (and of course you can use another linux board, like a raspberry pi):
What I didn't like from these projects is the way they execute actions from the arduino side.

The components of my finished project are very similar to the first link from adafruit.com: a webcam, a pir sensor and the arduino yun.

The events on the Yun, Arduino side
The example that I've found works like this:
  1. wait for move event (eg. from pir sensor)
  2. use Process and call fswebcam to get a photo from the webcam
  3. use Process and call a python script to upload a photo on dropbox
  4. ... do something ...
  5. go back to 1.
Everytime in a yun's sketch you will use Process, you are blocking the execution of the arduino part until the command is completed.
As long as the step 3 is completed, it is impossible to capture another photo.
Some samples use Temboo for dropbox, but I don't like it: it makes the sketch more complicated to mantain and the Dropbox Api is easy to use.
Since I didn't want to wait the 3rd step or use Temboo api on my system, I have wrote some code.

My solution: Arduino part
In my solution the arduino part work like this:
  1. wait for move event (From pir sensor)
  2. use Process and call fswebcam to get a photo from the webcam saving it, in a temporary directory
  3. use Process to move the photo to a destination directory where will be picked by the linux part
  4. go back to 1
The step number 3 is needed to be sure that the photo is totally written before the upload on dropbox.
Now, I have again 2 call to Process... but move a photo of less than 100 kbyte from a directory to another is faster than uploading the same photo to dropbox.
The arduino side, it is indipendent from the dropbox upload: this is a job for the linux side.
(if you want the arduino's sketch, just ask in the comments).

Linino part
I wrote a python script upload_to_dropbox.py in /root, that is able to continually check the photos's destination directory and when it finds one new, it uploads it on my dropbox account and on a succesfull upload, it deletes the local photo from the yun.
For setup of python and dropbox library on arduino yun I have followed this tutorial.
What I have changed from it, it is the sketch and the python script.

The python script is here, just edit it with your generated dropbox key.

 import dropbox  
 import glob   
 import os  
 import json  
 from time import sleep  
 photodir = '/mnt/sda1/arduino/www/';  
 client = dropbox.client.DropboxClient('DropBoxGeneratedKeyGoHere')  
 #starting main loop here  
 while(1):  
      toupload = glob.glob(photodir+'*.jpg');  
      try:  
           for fname in toupload:  
                print "Uploading... " + fname;  
                f = open(fname, 'rb');  
                response = client.put_file(fname[len(photodir):], f);  
                print "uploaded" + fname[len(photodir):];  
                print response['bytes'];  
                if(response.has_key("bytes") and response['bytes'] > 0):  
                     os.remove(fname);   
           sleep(0.3);  
      except:  
           sleep(2);  

In order to start the script automatically on each boot of the Yun, you need to edit /etc/rc.local adding:

export PYTHONPATH=/mnt/sda1/python-packages
python /root/upload_to_dropbox.py &