RaspberryPi motion detector with remote alert using Realtime and Python

RaspberryPi motion detector with remote alert using Realtime and Python

A few months ago I decided to finally buy me a Raspberry Pi. I loved the concept of having a small piece of hardware that, although obviously limited by its size, it’s still a computer, with its own operating system and easily accessible to developers to hack away cool projects.

My first real use of the Pi was to make it a media center, through the use of RaspBMC. Two months ago I decided to make it a NAS which, although not having a brilliant performance, works great as a backup network drive.

A couple of weeks ago we at Realtime released the Python API (you can find the documentation here) and I decided to give it a try with one of the small fun projects I had in mind: making the RPi a motion detector that could broadcast real-time warnings.

For this project I am using a Microsoft LifeCam VX-800 which worked flawlessly from the start. I have seen reports that the Playstation Eye also works great, although I haven’t tried it myself – call me lazy. Any USB camers should do the trick, actually. I can only tell you my experience with the Microsoft cheap camera, and it works amazingly well.

As for the motion detection, I used Motion. It took me a bit to get everything to work, as there were some dependencies that needed to be installed, but all-in-all it was pretty straightforward.

Please note: this is NOT a full-blown application. I just want to demonstrate here how easy it is to set all this up. The code I present here is not without flaws and it is NOT the perfect and correct way to develop a production-ready piece of software. There are some issues that I describe at the end of this post which should be trivial to solve to any Python expert out there. Again, please see this post and the code included in it as a mere demo.

Note 2: (added May 3rd): As stated by one of the folks commenting bellow, I could have used the ORTC RESTful API, which would actually be even easier. I wanted to use the native Python API for this example and will soon release another post with the much easier solution of using the REST API instead of using Python.

Installing Motion

To start with, it is always recommended you start by updating your Linux build by entering:

sudo apt-get update

After which you should then install Motion:

sudo apt-get install motion

Once it’s installed we will need to configure it. We’ll do that later on, though, so it’s time to get our hands dirty on some coding.

Our Python script

To keep everything simple, I used Realtime’s Python Pub/Sub example presented in GitHub as a base for my script, which you can grab at https://github.com/RTWWorld/pubsub-examples/tree/master/Python.

The example provided at GitHub is simple, yet powerful. Using it you can connect to an ORTC server, disconnect, subscribe and unsubscribe channels, send and receive messages. It’s all very easy, as it is normal with the other Realtime APIs.

I added some variables and changed the method on_subscribed in order for my script to send a message indicating that we just detected movement as soon as we subscribe a channel.

    def on_subscribed(sender, channel):
    print ('ORTC Subscribed to: '+channel)
    ortc_client.send(channel, 'Seems like we have an intruder!')

The workflow for the script is pretty simple. After our variables, we set up some methods to handle the ORTC events.

def on_exception(sender, exception):
    print ('ORTC Exception: ' + exception)

def on_connected(sender):
    print ('ORTC Connected')
    ortc_client.subscribe(CHANNEL, True, on_message)

def on_disconnected(sender):
    print ('ORTC Disconnected')
    import thread    
    thread.interrupt_main()

def on_message(sender, channel, message):
    print ('ORTC Message ('+channel+'): ' + message)
    ortc_client.unsubscribe(channel)

def on_subscribed(sender, channel):
    print ('ORTC Subscribed to: '+channel)
    ortc_client.send(channel, 'Seems like we have an intruder!')

def on_unsubscribed(sender, channel):
    print ('ORTC Unsubscribed from: '+channel)
    ortc_client.disconnect()

def on_reconnecting(sender):
    print ('ORTC Reconnecting')

def on_reconnected(sender):
    print ('ORTC Reconnected')

ortc_client.set_on_exception_callback(on_exception)
ortc_client.set_on_connected_callback(on_connected)
ortc_client.set_on_disconnected_callback(on_disconnected)
ortc_client.set_on_subscribed_callback(on_subscribed)
ortc_client.set_on_unsubscribed_callback(on_unsubscribed)
ortc_client.set_on_reconnecting_callback(on_reconnecting)
ortc_client.set_on_reconnected_callback(on_reconnected)

After which we actually connect to the ORTC server.

ortc_client.cluster_url = ORTC_URL
ortc_client.connect(APP_KEY)
ortc_client.disconnect()

Once our script starts running, we connect to the ORTC server. This connection will cause our on_connected method to kick in which, in turn subscribes the motion:cam1 channel. Subscribing a channel also raises an event and our on_subscribed method is called, which finally sends our message to the same channel we have subscribed. The logic doesn’t stop here but it’s very easy and you’ll understand it easily after a quick look at the code.

The bottom line is: our message will be sent when our script runs. This take a few seconds as we need to connect to the server — a bit of a overhead — but it does get sent.

Configuring motion

The next step will be to configure it but first you need to change permissions on the motion.conf file through the following commands:

sudo chmod -R 777 /etc/motion/motion.conf
sudo chmod -R 777 /tmp/motion

You can then open and edit the file. I used Nano to do it and you can do it too by entering:

sudo nano /etc/motion/motion.conf

Will will notice that the file is rather lengthy but we only need to edit a line, which will call our script. We will assume our file is placed at /home/realtime-motion-alert/realtime-motion-alert.py

The line we need to edit is the one that indicates Motion that it’s supposed to call a external script. Once you open our file in Nano, search for on_motion_detected and edit it so it looks like this:

    on_motion_detected python /home/realtime-raspberrypi-motion-alert/realtime-raspberrypi-motion-alert.py

Now simply run Motion by entering motion and hitting enter. You should see something like the image bellow.

Motion working on a Raspberry Pi

Motion working on a Raspberry Pi

Move the camera or make something else that makes the image change a bit (wave at it, for example) and you should have some more output. Our messages should be on their way too and you should see them on the output too.

Python script sending messages to Realtime's ORTC

Python script sending messages to Realtime’s ORTC

Testing our motion detector

Seems like we’re cooking. So what else do we need? Well, we do need to see if it’s actually working!

Our output says that we are broadcasting data so anything that subscribes to our motion:cam1 channel (as long as it’s using the same Application Key) should get it, right? Let’s see if that’s true, then.

One of the easiest ways of doing it is by building a small HTML page that connects to ORTC, subscribes our channel and outputs the data:

<!doctype html>
<html>
<head>
</head>
<body>
    <div id="log"></div>
	<script src="http://code.xrtml.org/xrtml-3.2.0.js"></script>
	<script>
		var appKey = 'YOUR_APP_KEY';
		var authToken = 'abcdefg';
		var url = 'http://ortc-developers.realtime.co/server/2.1';

		xRTML.ready(function(){
			xRTML.Config.debug = true;

			xRTML.ConnectionManager.create({
				appKey: appKey,
				authToken: authToken,
				url: url,
				channels: [{name: 'motion:cam1'}]
			}).bind({
				message: function (e) {
					var content = document.getElementById('log').innerHTML;
					document.getElementById('log').innerHTML = content + '<br />' + new Date() + ' - ' + e.message;
				}
			});
		});
	</script>
</body>
</html>

Once our page gets a message, it displays it, with the current timestamp, by adding a message to a div. If we run our motion example again on our RPi and move the camera, we not only should see the output on our RPi console, but we should also be seeing it on the webpage.

Receiver test page showing the messages being sent by Raspberry Pi

Receiver test page showing the messages being sent by Raspberry Pi

Don’t forget that you need a Realtime developer key, which you can get, for free at https://app.realtime.co/developers/getlicense.

Problems and limitations

Like I said in the beginning of this post, this is just a demo and there are some problems and some limitations. You will probably notice that it does take a while to connect to the server. Once it does, though, sending a message is a breeze. If you are interested in using Realtime to broadcast security or sensitive data, you should change your application in order for it to be connected to the ORTC servers at all times.

Also, you will notice that when you move the camera, you will have several message broadcasts. This is because Motion is capturing and raising events very fast. Although Realtime can handle it — easily — this is far from perfect and you should really optimize it.

That said, have fun and I really hope to see some other cool examples out there!

Code and resources

As usual, you can download my code freely at GitHub: https://github.com/SergioMSCosta/realtime-raspberrypi-python-motion-detector

Feel free to change it, hack it, make it better, whatever you wish.

For more information about Realtime you can head out to www.realtime.co.

Don’t forget to check out the xRTML (Realtime’s APIs) documentation at http://docs.xrtml.org/

I really hope you enjoyed this article and that it inspires you to do some other cool examples.

About the author

Sérgio Costa I've been working as a developer since 1999 in all kinds of different projects. I have contributed and provided support to both Marketing and PR teams in the form of consultation or the creation of documents and articles. I’ve also participated in public events a abroad, as well as online events (webinars) and provide training to partners and developers. My previous experience also involves project management and multiple team management. Do you have comments on this post or maybe a suggestion? I would love your thoughts on this! You can leave a comment below, get in touch or catch me on Linked In, Twitter or Google+.