Hacker News Update: Raspicam & WeMo

A quick update on my recent discoveries.

Raspicam

I now have a Raspberry Pi Camera Board (Raspicam)!

There is a brilliant combo deal on at the moment allowing you to buy a Raspicam, Model A + 4GB SD card for about £35 (including VAT + shipping!)! That’s £35 for a device that can run OpenCV with a camera capable of 30fps at HD resolutions. I will leave you to think about that for a moment.

The downside is that the software is still not quite there. The Raspicam couples directly to the Raspberry Pi; this means it is not (at the moment) available as a standard USB video device (e.g. /dev/video0 on Linux). Now most Linux software and packages like SimpleCV work based on a standard USB video device. This means as of 24 October 2013 you cannot use SimpleCV with the Raspicam.

However, not to fret! The Internet is on it. I imagine that we will see better drivers for the Raspicam from the official development communities very soon. While we wait:

WeMo and Python

As you will see from the previous posts I have been using IFTTT as a make-shift interface between my Raspberry Pi and my WeMo Motion detector and switch.  This morning though I found a Python module that appears to enable you to control the Switch and listen to motion events via Python. Hurray!

The module is called ouimeaux (there is a French theme this week). Details can be found here: link.

Very soon I hope to adapt my existing code to control my Hue lights based on motion events (e.g. turn on when someone walks in the room, turn off when no motion). Watch this space.

Doing Useful Things with WeMo Motion

Using both the WeMo Motion rules and IFTTT allows you to do certain things with this motion detector. However, to expand our possibilities it would help if we could store our motion data and make it accessible to the programs that we write.

20131004-063848.jpg
To store our motion data in a database we need a bit of a convoluted process. It goes something like this:

20131004-063802.jpg
First we set up an IFTTT recipe to send an email to a Gmail account when motion is detected.

20131004-064517.jpg
Having done this you will get a series of emails:

20131004-064837.jpg
I recommend setting up a separate Gmail account for automation to avoid spamming yourself with IFTTT emails. It would also make things more secure for the next steps. To make things easier when using multiple IFTTT recipe emails, I set up a filtering rule in Gmail to automatically label all emails like this as “Motion”.

The next step is to write some Python code to access our emails, process messages and store data in an SQLite database.

  • The email processing makes use of the imaplib and HeaderParser libraries; and
  • The database processing makes use of the sqlite3 libraries.

A first function accesses all unread emails with a particular label and returns an array of the subject lines of those emails.

def read_subjects(label):
	obj = imaplib.IMAP4_SSL('imap.gmail.com', '993')
	obj.login('username@gmail.com', 'password')
	obj.select(label)  # <--- it will select inbox
	typ ,data = obj.search(None,'UnSeen')

	subjects =[]

	for num in data[0].split():
		data = obj.fetch(num, '(BODY[HEADER])')

		header_data = data[1][0][1]

		parser = HeaderParser()
		msg = parser.parsestr(header_data)
		#print msg['Subject']
		subjects.append(msg['Subject'])

	return subjects

A second set of functions then processes each subject line to extract a ‘datetime’ that the motion occurred and a motion sensor name.

def store_motion(subjects):
#Initilise temporary array for data
	rows = []
	unread_count = len(subjects)-1

	#Process and store unread mail items
	for j in range(0,unread_count):
		#print subjects[j]
		#Extract date/time of last motion
		extracted_date = extract_date(subjects[j])
		#Extract motion time
		motion_time = datetime.datetime.strptime(extracted_date, "%B %d, %Y at %I:%M%p")
		#Extract sensor name
		s_name = extract_sensor(subjects[j])
		#Add (motion time, sensor name) tuple to rows
		rows.append((motion_time, s_name))
	#print rows
	storemotioninsql(rows)

def extract_date(word):
	date_index_start = word.find("ion: ")+5
	date_index_end = word.find(" at")+11
	date_out = word[date_index_start:date_index_end]
	return date_out

def extract_sensor(word):
	name_end = word.find("' ")
	word_out = word[1:name_end]
	return word_out

A third function stores the prepared ‘datetime’ and motion sensor name in an SQLite database.

def storemotioninsql(rows):
	#Save in database
	con = lite.connect('motion.db')

	with con:

	    cur = con.cursor()

	    #Create a READINGS table if it doesn't already exist
	    cur.execute('CREATE TABLE IF NOT EXISTS motion (r_datetime TIMESTAMP, r_s_name TEXT)')

	    for row_values in rows:
	    	#print row_values
	    	cur.execute('INSERT INTO motion VALUES(?,?)', (row_values[0], row_values[1]))

All that remains is to set these functions up in a python script and then use cron to schedule it to run every 15 minutes (crontab -e etc…).

WeMo Motion / IFTTT Bugs

Just bought the WeMo Switch and Motion sensor.

Setup was fine via app.

Next step was connecting IFTTT. I did this via the “…More” button on the app. Click on “Connect to IFTTT” option. A pin is generated. It took me a couple of attempts to realise you can click on the button under the pin to log in to IFTTT to activate the devices – if you do this the pin is automatically copied across.

The switch activated without problems on IFTTT. However, when I tried the Motion IFTTT said the pin was not valid (invalid pin message in a red box). Generating different pins did not work, neither did a clear or a factory reset of the Motion (via “Edit”) in the app.

I tried deactivating, then deleting the Switch. This did something as the app then said it could not generate a pin. I then deleted and reinstalled the app. This time a pin was generated and the Motion connected.

I then performed a factory reset on the Switch (hold button on top and plug in). Then added this via the app. The first attempt to connect to IFTTT failed but the second time worked.

Success! Both Switch & Motion connected to IFTTT.