The Raspberry Pi is an amazing device. Although not the most powerful mini computer out there, it bolsters a tremendous support community, tons of hardware add-ons and coding libraries to your heart’s desire. The Raspberry Pi also makes an affordable media player but so much more can be done with it. In this post, I’ll try to show you how I turned your typical Raspberry Pi, combined with some cheap components and IP Cameras, into a state-of-the-art home monitoring system capable of recording video, turning power outlets on or off and sensing movement.
Some time ago, I bought a couple of your run-of-the-mill entry level IP cameras. I’m sure you’ve seen them. They can be had for $50 to $100, are feature packed, and able to connect to your home network via Wifi or Ethernet. However, I’ve always had issues with the built-in motion sensing feature which seems to be affected quite easily based on the changing lighting conditions. After numerous false positives, I’ve decide to take matters in my own hands. It snowballed. This is the end result…
All code related to this project can be found here at my github project page.
Key Features
- Displays live feed and records to a local or network disk from two IP cameras
- Controls two wireless power outlets/switches
- Orvibo S20 WiFi power socket
- Able to sense motion and trigger sending of emails (SMS to cell phone), snapshots and recording
- Can be scheduled via a simple UNIX cron-like interface
- Displays temperature/humidity (why? not sure really, seemed like a cool thing to do)
Camera Setup
For the camera setup, I connect the camera via Ethernet on my LAN and simply configure a static IP address, a gmail account and turn on the Motion Detection Alarmed as a fail safe (even though I will use a PIR sensor). Also, I created an additional administrator account through the interface.
The Record Camera buttons (on my interface) trigger a bash script that essentially just calls ffmpeg in the following way (take a look below on how I compile the latest ffmpeg for the Raspberry Pi):
ffmpeg -use_wallclock_as_timestamps 1 -f mjpeg -i "http://IP/videostream.cgi?user=USERNAME&pwd=PASSWORD" -i "http://IP/videostream.asf?user=USERNAMEpwd=PASSWORD" -map 0:v -map 1:a -acodec copy -vcodec copy -f segment 3600 $cam_record_length -reset_timestamps 1 "FILENAME.mkv" > /dev/null 2>&1 &
The above line was the only way I able to produce a scan-able (able to jump to any time code) video file. I invite you to take a look at the following script:
/bin/camrec/camrec.sh
Raspberry Pi GPIO
What makes the Raspberry Pi so versatile is that it comes with a set of input/output pins, more specifically:
The Raspberry Pi has a 26-pin General Purpose Input/Output (GPIO) connector that carries a set of signals and buses. There are 8 general purpose digital I/O pins – these can be programmed as either digital outputs or inputs. One of these pins can be designated for PWM output too. Additionally there is a 2-wire I2C interface and a 4-wire SPI interface (with a 2nd select line, making it 5 pins in total) and the serial UART with a further 2 pins.
If you didn’t quite understand that, it’s all ok, ’cause neither did I. What you really need to know is how to identify the pins, as this is where we will be connecting the sensors. If you don’t know how to identify the pins yet, take a look at this blog post.
PIR Sensor
The first sensor we’ll connect is a PIR sensor and can be purchased on Ebay quite cheaply. The PIR sensor is a motion sensor and has 3 pins. In fact, hooking it up to your Raspberry Pi, assuming you have jumper wires, couldn’t be any easier. It requires no soldering nor any additional components.
When researching how to incorporate the PIR sensor with the Raspberry Pi, I came across this post. The author even provides some Python code which I used as a template for my own Python script.
PIR Sensor | Raspberry Pi |
---|---|
+5V | Pin 2 (+5V) |
Out | Pin 26 (GPIO7) |
Ground | Pin 6 (Ground) |
In short, I added some functionality to the script – which quite honestly, wasn’t that hard to do. Now, when the PIR sensor is tripped the following happens:
- Arms the camera (that is, it turns on the option Send Mail on Alarm on the camera)
- Sends an email to both my personal email and to my phone via the email address phone_number@phone_provider
- Kicks off a recording from a specified camera to a local or networked disk via ffmpeg (as the Foscam cameras have no built-in way to record video)
This is all configurable in the configuration file and triggered via the PIR Alarm button on the UI. This is my el cheapo security system.
Please take a look at the code in:
/bin/pir/pir.py
Permissions
Unfortunately, the pir.sh script (that’s kicks off the pir.py script) needs sudo to run, because of this, the www-data user needs the appropriate rights. I know, totally insecure to do this, but since the project resides on an internal LAN, I’m not worried.
sudo visudo (add) www-data ALL=NOPASSWD: /{PATH_TO_WWW}/mypihc/bin/pir/pir.sh
Going Further – Smartphone Integration
I also wanted some way to quickly start the PIR Alarm with my smartphone when I quickly leave my home. For that I used the amazing Andriod app called Tasker along with the SSH Plugin. As you see below I create a task and use the SSH Plugin to log into the Pi and start the pir.sh as follows:
sudo /var/www/mypihc/bin/pir/pir.sh <start|stop>
I did the same thing for a stop task. Finally, I added a widget icon on the home screen for quick toggling. Cool! Another thing, if you have NFC cards and your phone supports it, you can also create tasks that are triggered when you touch your phone on an NFC card. Really cool!
Compile ffmpeg
You will need the latest version of ffmpeg installed on the Raspberry Pi. Unfortunately, I had to compile mine from source code, which isn’t too hard to do but could take hours!
As I said before, I use ffmpeg to handle the recording from the camera to disk. It’s a fool proof way to produce a manageable video file.
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg cd ffmpeg ./configure make sudo make install
Once complete you should have the ffmpeg binary in:
/usr/local/bin/ffmpeg
433MHz RF Transmitter/Receiver
Another rather cool component is the 433MHz Transmitter/Receiver, which again, is relatively inexpensive and easy to connect to your Raspberry Pi. The reason for this is that I’d like to be able to control the power outlets such that I could turn on/off devices via a script or web interface instead of always using the included remote (as you see in the picture below). You could use wired relays connected to the GPIO pins instead, but generally that involves some basic electrical knowledge and necessitates that the Pi be close to the device you want to control. This way, the remote outlet switches can be further away. These buttons are labelled Switch A / Switch B on the web interface.
The major difficulty you will have is intercepting the wireless codes sent from the remote to the outlets. The following site was instrumental in getting both the transmitter and receiver connected. (Ingore the Arduino stuff as we will not be using one).
The following is a schematic from the aforementioned site.
Once connected as per above, we need to download and compile some code. First, we need to grab the wiringPi library. WiringPi is s GPIO access library written C.
git clone git://git.drogon.net/wiringPi cd wiringPi/wiringPi sudo ./build
Next, we need to install a set of utilities that will allow us to use the transmitter and receiver.
git clone git://github.com/ninjablocks/433Utils.git cd 433Kit/RPi_utils make all
I had to change some code in order for the receiver to be able to pick up my codes as for some reason my 433MHz codes were longer. If this is your case, change line “mySwitch.send(code, 26);” in codesend.cpp
Within the 433Utils/RPi_utils directory, do a:
sudo ./RFSniffer
Grab your wireless remote and press a button! With any luck, you should see its code appear in your terminal:
Starting Up.. Received 35849236
In my case this was the On button for the first outlet. Now, let’s test whether we could turn on the same outlet with some code. In the same directory, do a:
sudo ./codesend 35849236
If it turns on, success! Repeat for all other buttons.
Permissions
Unfortunately, the codesend script that calls the codesend binary also needs sudo to run.
sudo visudo (add) www-data ALL=NOPASSWD: {PATH_TO_WWW}/mypihc/bin/codesend/codesend.sh
Orvibo S20 WiFi Power Socket
The Orvibo S20 WiFi is really a nifty device. Relatively inexpensive from various online sites, this device connects through your WiFi network enabling you to control and power various home appliances up to 10 Amps. The manufacturer offers a smart phone app which permits you to control the socket and also set up timers via the app. However, it just so happens that this device has been reversed engineered and as such makes it that much more interesting for to incorporate into this project. Basically, the S20 is very similar to the RF transmitter just discussed, only difference is that it uses WiFi.
Please see this separate blog post detailing how I got it set up.
Permissions
The script I use for the Orvibo should also use sudo to run.
sudo visudo (add) www-data ALL=NOPASSWD: {PATH_TO_WWW}/mypihc/bin/orvibo/s20command.sh
DHT22 Temperature/Humidity Sensor
For the sake of geekiness and sheer curiosity, I also incorporated a temperature/humidity sensor. Totally not necessary for the goal of this project but seemed like fun to do. Once more, the sensor is quite cheap and will only run you a couple of dollars. Keep in mind, that you will need to protect the Raspberry Pi’s GPIO from excessive voltage, hence the discussion of the voltage divider below. The pinout is as follows:
DHT Sensor | Circuit |
---|---|
Pin 1 | +5V |
Pin 2 | GPIO 4 |
Pin 3 | Not used |
Pin 4 | Ground |
Many guides suggest adding a 10K ohm resistor between the +5V and data pin (pin 2). You could also build a voltage divider as well. I will show you how that’s done.
Voltage Divider
For DHT22 5V operation connect pin 1 to 5V and pin 4 to ground. The following pin 2 connection works for me. Use at YOUR OWN RISK.
Next we need to install the library that will poll the sensor by doing:
git clone https://github.com/adafruit/Adafruit_Python_DHT.git cd Adafruit_Python_DHT sudo python setup.py install
Please take a look at the code in:
/bin/dht22/dht22.py
However, the Python code is short enough to post here:
import Adafruit_DHT as dht h, t = dht.read_retry(dht.DHT22, 4) sys.stdout.write("%0.1f,%0.1f" % (t, h))
Permissions
The dht22.sh script (that’s kicks off the dht22.py script) needs sudo to run. Do the visudo thing once more.
sudo visudo (add) www-data ALL=NOPASSWD: /{PATH_TO_WWW}/mypihc/bin/dht22/dht22.sh
Crontab
Because the www-data user (the user under which lighttpd is running) alters the pi user’s crontab, additional steps need to be taken for this to happen. First, we need to install a crontab PHP library. But before this, we will install the PHP package manager, Composer.
echo "<?php echo file_get_contents('https://getcomposer.org/composer.phar') ?>" | php > composer.phar sudo mv composer.phar /usr/local/bin/composer sudo chmod +x /usr/local/bin/composer
Now install the library:
composer require tiben/crontab-manager ~1.0
Not done just yet! Let’s give him the sudo rights.
sudo visudo (add) www-data ALL=(pi) NOPASSWD: /usr/bin/crontab
By altering visudo you basically give the www-data user permission to modify crontabs under the pi user.
To make this clearer, when jobs are scheduled through the interface, as you see below, they are in fact configured in the user pi‘s crontab.
To inspect the crontab do this:
crontab -l
Thus a row in red means that the job is temporarily paused, shown by the first #. In this case the Orvibo S20 will turn on every hour. The stuff after the # (hash) symbol is simply commented out text I use to better managed each individual line through the interface.
Serving the Project
Lastly, we will need to serve the PHP code from the Raspberry Pi. For this, I used lighttpd. Here’s how I got that installed:
sudo apt-get update sudo apt-get install lighttpd mysql-server php5-common php5-cgi php5 php5-mysql php5-cli sudo lighty-enable-mod fastcgi-php sudo service lighttpd force-reload
Permissions:
sudo chown www-data:www-data /var/www sudo chmod 775 /var/www sudo usermod -a -G www-data pi
Configuration
So all in all, that’s the project. I can go further into depth but I rather invite you to look over the code for yourself and mess around with it, if you’re interested that is…All it should take really is basic programming knowledge to manage yourself through my ugly code.
Lastly, all configuration for the project is handled through the config.ini file. I know, I know, I could have handled the configuration more gracefully, like through the interface or something but for sheer simplicity, I opted for the quick and dirty approach – so everything was thrown into one file. Therefore, all specifics to your setup will need to be populated accordingly. This includes the IP camera’s IP/user/password, specific 433Mhz codes (if using the transmitter), save directory, email, google voice, etc… Please read the README file for more info.
Take a look at the github project page and thanks for stopping by!
Hello Bobby,
Your post is quite interesting, i’m starting to think about a similar system (Foscam cam + PIR). The difference is about the PIR, i like to use existing PIR (wirelesse 433MHz) because i want easily add and remove sensors and i don’t want a Raspberry for any PIR.
Do you think it is possible to intercept and decode the PIR wireless signals with the same method that you used for the outlets ?
Also i like to know if in your case you have decoded the same signal for turning on/off every outlet (same brand) or not? in this case how can you decide which outlet turning on/off without affecting also the others (maybe this is a noob question but I do not have much knowledge about these things)
If the PIR operates on the same frequency I don’t see why not.
The outlets I have came in a pack of two and both had unique codes so you wouldn’t have to worry about affecting the others.
This is a really great project. I read that the Foscam IP Camera has two way audio. Is it possible to extend your project by:
Getting the audio from the cameras?
Sending audio to the speaker of the cameras?
Happy to discuss this with you.
Hi Michael,
In all honesty, I haven’t thought about incorporating audio – seems like a good idea though. But how would you implemented such a thing over a browser? Maybe one-way audio would work however sending audio via a microphone would require direct access to the client’s computer hardware – that could be a little difficult to get working. If you have thoughts on how this would work, I’d love to hear it.
Hi,
I have an older version of the Foscam camera (FI8908W) wich have I/O alarm connectors. Do you think it’s possible to directly plug your IR Sensor on it ? I found this schema : http://www.paillassou.com/tmp/IO.JPG
So I don’t have to buy a new Raspberry Pi.
Thanks !
Probably not possible given my code, sorry.
Hi bobby.
Currently I have 5 Foscams and a NAS server. Do you think the RPI can handle all 5 and record to the NAS?
Hi Angel,
If you’re talking about the Raspberry Pi 2, then yes, it should work (disclaimer: have not tested this with more than two cameras).
How do I install this? Do I extract the github zip file in a certain directory? I have emailed the developer, but would like to have the answer posted public in case another person runs across this cool program. I tried home and /var/www/html but still receive these errors.
‘.$ini_array[‘config’][‘save_to_dir’].”:’Invalid path!’; ?>
(Running…)”; } else { echo $ini_array[‘switch-c’][‘name’]; }?>
$value) { if ($value) $string .= “, $key”; } echo ‘(‘.str_replace(‘_’, ‘ ‘, substr($string, 2)).’)’; ?>
(Running…)”; } else { echo $ini_array[‘switch-d’][‘name’]; }?>
(Running…)”; } else { echo $ini_array[‘switch-e’][‘name’]; }?>
Hi Lee,
Try unzipping the downloaded mypihc-master.zip file into /var/www and then rename the directory to /var/www/mypihc. Once done, go through the installation via the Requirements section outlined here: https://github.com/bobbyromeo/mypihc.
You can either hit http://YOUR_IP/mypihc or put a index.php file in the /var/www directory that contains the following:
Good luck.