The Pi camera as a low budget home security system (Part 3 – Motion Detection)

For motion detection with the camera I have basically used the work of Claude Pageau and his piMotionLite script with simple modifications. I would advise you to look into his other work especially if you are looking for something that, for example, syncs with Google drive out of the box.

Minor modifications  I made was “import thread” at the start and then you really just need to modify the “userMotionCode” to do whatever it is you want to do – in this case I want to take a small video and email it to me.

def userMotionCode():

# Recording video for 30 seconds

msgStr = “Motion Found So Do Something …”
showMessage(“userMotionCode”,msgStr)
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.start_recording(‘my_video.h264’)
camera.wait_recording(30) # Number of seconds being recorded
camera.stop_recording()

# Convert file to a format most readers can handle

rightNow = datetime.datetime.now()
filename = “/home/pi/security/%04d%02d%02d-%02d%02d%02d.mp4” % (rightNow.year, rightNow.month, rightNow.day, rightNow.hour, rightNow.minute, rightNow.second)
command = “/usr/bin/MP4Box -fps 30 -add my_video.h264 ” + filename
os.system(command)

# Send e-mail on a separate thread so that the application is not waiting for this to be over to continue detecting motion

thread.start_new_thread(mailMe, (filename, ))
return

So you can see the final action is to call a mail function:

def mailMe(filename):
subject = “I am a random subject”
rcpt = “my@mail.com”
command = “/home/pi/mail/myMail.py -s ‘” + subject + “‘ -f ” + filename + ” -r ” + rcpt
print command
os.system(command)

The main reason we put this into a separate function is to make it threaded, you can see all it does is call the application we already built on part 2.

If everything is working fine you should now have received an e-mail with a video whenever motion is detected. Don’t forget to decrypt the file with for “gpg –decrypt encrypted.txt > file.mp4” and then you can just view the video with any media player of your choosing.

We could of course be doing more interesting stuff in addition to e-mail, for example get a speaker to start playing loud sounds or even automatically dial someone (the police… if you really trust the software is not sending a false alarm) or anything else you can come up with. I will look into some of these options in future posts.

The Pi camera as a low budget home security system (Part 2 – email)

So as mentioned in the previous post I will be using e-mail with PGP to receive the data sent by the security system (mostly either pictures or videos, maybe even sound files in the future). Although I could put all of this in the same program I opted to make a separate script just to send e-mails that can eventually be called by any other application I have on the system if I want to send mails from it.

Step 1: setting up PGP

#Install python-gnuph

sudo apt-get install python-gnupg

# If you don’t have a PGP key yet you will have to generate one on whichever device you will be decrypting the message. You can also create a separate private/public key pair on your Pi

gpg –gen-key

# Back on the Pi we will need to import the public key for the e-mail we will be receiving the data on. So save the public key to a file and then import it

gpg –import file-with-public-key.asc

# Sign the key

gpg –lsign-key your@email.com

And that is pretty much setup, you should find a new set of files under ~/.gnupg/ with your files. On my setup the Pi has its own key pair as well now all we need is to send e-mails with Python.

As I want it to be modular and be invoked by a different set of scripts I have made it so that most things are passed trough the command line instead of hardcoded. For example purposes I am also using GMail as it is still quite a popular choice but feel free to adapt to your own mail provider

#!/usr/bin/python
import os
import sys, getopt
import smtplib
import gnupg
import time ;
import subprocess ;
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email import Encoders

# Default values

subject = “I wish I had a real subject”
file = “/tmp/file”
encryptedFile = “/tmp/encrypted.asc”
rcpt = “/dev/null”
gmail_user = ‘username@gmail.com’
gmail_pwd = ‘password’

myopts, args = getopt.getopt(sys.argv[1:],”s:f:r:”)
for myopt, myarg in myopts:
if myopt == ‘-s’:
subject = myarg
elif myopt == ‘-f’:
file = myarg
elif myopt == ‘-r’:
rcpt = myarg

###################################################################################
# Encrypt our data
gpg = gnupg.GPG(options=’–armor’)

# Now that it is on disk lets work on getting it to the internet – encrypted
with open(file, ‘rb’) as f:
status = gpg.encrypt_file(f, recipients=[rcpt], output=encryptedFile)

###################################################################################
# We start with the headers for the e-mail
email = MIMEMultipart()
email[‘Subject’] = subject
email[‘From’] = gmail_user
email[‘To’] = rcpt

# We now want to attach things
part = MIMEBase(‘application’, “octet-stream”)
part.set_payload( open(encryptedFile,”rb”).read() )
Encoders.encode_base64(part)
part.add_header(‘Content-Disposition’, ‘attachment; filename=”%s”‘ % os.path.basename(encryptedFile))
email.attach(part)

###################################################################################
# Now we send e-mail – change the SMTP server if not using Google
smtpserver = smtplib.SMTP(“smtp.gmail.com”,587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(gmail_user, gmail_pwd)
header = ‘To:’ + rcpt + ‘\n’ + ‘From: ‘ + gmail_user + ‘\n’ + ‘Subject:’ + subject + “\n”
print header
msg = header + “\n\n” +  message
smtpserver.sendmail(gmail_user, rcpt, email.as_string())
print ‘done!’
smtpserver.close()

 

So now we simply have to call the script with the appropriate options:

./myMail.py -s ‘Sending mail’ -f ./file.txt -r ‘my@email.com’

Create “./file.txt” and put some random text on it and make sure that “my@email.com” public key exists on your Pi box before running it. If everything is setup correctly you should be receiving an encrypted e-mail shortly. Save the encrypted attachment to disk and run

gpg –decrypt file.txt

You should now be able to read the original file without encryption. This of course will also work with any other type of files like images or videos and not just text.

 

On Encryption and Terrorists

Not usually what this blog is about but definitely an important subject these days: On encryption and terrorists by Nadim Kobeissi, author of CryptoCat and other encryption software.

Ford and Toyota build automobiles so that the entire world can have access to faster transportation and a better quality of life. If a terrorist is suspected of using a Toyota as a car bomb, it’s not reasonable to expect Toyota to start screening who it sells cars to, or to stop selling cars altogether. And yet, this is the line of questioning that has besieged the cryptography community immediately after the Paris attacks.
[…]
In this rush to blame a field that is largely unknowable to the public and therefore at once alluring and terrifying, little attention has been paid to facts: The Paris terrorists did not use encryption, but coordinated over SMS, one of the easiest to monitor methods of digital communication. They were still not caught, indicating a failure in human intelligence and not in a capacity for digital surveillance
[…]
If we take every car off the street, every iPhone out of people’s pockets and every single plane out of the sky, it wouldn’t do anything to stop terrorism. Terrorism isn’t about means, but about ends.

The Pi camera as a low budget home security system (Part 1 – Intro)

So the Christmas lights have finally gone up and they have been mostly working without issues – except for that one time when we were watching a movie and someone on it said something similar to “lights off” and the Pi shut it down unexpectedly. Unfortunately the Christmas lights were not the only thing connected to that on/off zWave switch so that was unexpectedly fun.

After that was done I returned to my most recent project: a low cost security camera using the Pi Camera. I have most of it working already – except actually sending alerts and showing me the video when motion detected is enabled.

Been thinking long and hard on how to do this and since we are talking about basically sending me pictures / videos of my own house security becomes an important topic so where do I store this in a way that I can reach them when not in the house? I have been considering several options and to be honest I have not reached yet any conclusion.

  1. Google drive or dropbox seems to be a popular option as you can reach these from many devices and not just your computer however the security and privacy considerations when using this type of service leave much to be desired. One option is of course to simply encrypt the data before uploading it to such a cloud storage provider but then that means I can’t read the data on the go as my phone has no built in support for decrypting the files.
  2. SpiderOak would have been my favorite option (basically a Google Drive that has a business model based on selling you storage instead of selling your (meta)data to third parties) but unfortunately they do not yet support the Pi – if you are reading this and would like them too feel free to drop them an e-mail to let them know there is demand for it.
  3. SyncThing was another option on the list. It basically lets you setup your own cloud service so you are sure to not be sharing your data with anyone else. There are more technical complications as using something off the shelf obviously but in the end the reason I went against it is a lack of support for an iOS app. If you use Android it might be something worth considering.
  4. Simply e-mail. I am not a huge fan of this but e-mail is indeed widely supported everywhere. Again because of security / privacy  concerns the data would have to be encrypted but there are several out of the box solutions for that already (such as PGP).

So while the jury is still out on making a decision on how to actually get the data to me on the move for now I am going with option 4 and keeping an open mind if I spot something that works cross platform (Linux, Windows and iOS) and will be able to change it easily in the future due to the modular nature of the implementation.

If any of you knows of has any other possible solutions to this problem that I may have overlooked please feel free to leave it on the comments.

Part 2 (e-mail)

Making use of that Z Stick – Part 3 (Getting the sunset time)

Getting the sunset time is the easy part. I was already using pyowm python library by Claudio Sparpaglione to check the weather on Brains so I didn’t even need a second thought on how to get my sunset time. Because this is going to be a time that changes everyday though we are going to use at instead of crontab

sudo apt-get install at

And then the code is quite simple:

#!/usr/bin/python

import pyowm
import sys, os

owm = pyowm.OWM(‘7b7534dc372cc5bf1e8b741dbfc9a2ac’)
city = “Paris, France”

observation = owm.weather_at_place(city)
cWeather = observation.get_weather()
sunset = cWeather.get_sunset_time(‘iso’)
print sunset

time1 = sunset.split(” “)
time2 = time1[1].split(“:”)

command = “echo \”/home/pi/myZClient.py 3 1\” | at ” +  time2[0] + time2[1]
print command
os.system(command)

So basically this little script checks the time of sunset using the Open Weather Map API and then schedules a job to run at that time. To confirm the job is actually queued for the correct time you can run “at -l”. If so all you need to do now is put the script on crontab to check the sunset time each day.

crontab -l

# Turn off the lights at 00:30 every day
30 00 * * * /home/pi/myZClient.py 3 0

# Checks sunset time every morning at 9 am

0 09 * * * /home/pi/checkSunset.py

And there you go… completely overkill automated Christmas lights for you. If there is any interest I will probably put up a video of them working (I actually don’t have Christmas lights yet – I have been testing it with a lamp but they will be coming in the next few weeks)

Making use of that Z Stick – Part 2 (Making a small client server for ZWave instructions)

So the first thing required for this small project was a way to communicate between the ZWave controller and the On/Off Module. Best way to do this is of course to steal some code and adapt it to your needs and as I did not know anything about ZWave this Python wrapper by Sébastien Gallet for openzwave library seemed the best place to start.

I basically picked up his hello world example and put some sockets on it:

# Socket creation
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
except socket.error, msg:
print ‘Failed to launch server. Error message : ‘ + msg[1]
sys.exit();

server.listen(5)
print “Server is listening on %s:%s” % (HOST, PORT)

#wait to accept a connection – blocking call
while True:
conn, addr = server.accept()
data = conn.recv(1024).strip()
input = data.split(“:”)
node = int(input[0])

if “!quit” in data:
break
else:
#display client information
print data
print “Device: ” , input[0]
print “State: ” , input[1]

if int(input[1])  == 1:
state = True
else:
state = False

for val in network.nodes[node].get_switches() :
network.nodes[node].set_switch(val,state)

server.close()

So basically this is a server that does nothing more than listen for connections and expect data on a x:y format (X being the node ID and Y being the state on or off). For security reasons I binded it to the loopback interface only since as you can see I am not doing any input validations. Now although it is possible to control the light switch with telnet it is much easier to do a simple client application for this:

#!/usr/bin/python
import socket
import sys

HOST = ‘127.0.0.1’ # Specify a specific IP address if you want
PORT = 4242

try:
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print ‘Failed to create socket. Error message : ‘ + msg[1]
sys.exit();

message = sys.argv[1] + “:” + sys.argv[2]
s.connect((HOST, PORT))
s.sendall(message)
s.close()

So now if I ever need to turn on the light all I need is to run /home/pi/client.py 3 1 (3 is the device ID of my ZWave plug) and to turn it off /home/pi/client 3 0 which is kind of the API feel I wanted to control my stuff initially. Although of course now this is just limited to switches and nothing else but its open for future growth and changes.