Riddlegate: automating apartment intercoms

If you’ve ever lived in an apartment building or gated complex, you’ve probably seen one of these things:

Apartment Intercom

A person dials some code to reach you, you make sure it’s someone you’re expecting, and you press some digits on your phone to grant access.

However handy this is, there are situations where it’s not very helpful. I can’t count how many packages I’ve missed because I was away from my phone when the delivery driver arrived. I really wanted to be able to just give them a code that allowed them access.

Enter Twilio. It enables exactly this. You rent a phone number through them (very cheap — on the order of $1/month), which can be configured to call HTTP endpoints when it receives a call, SMS, etc.

I built a small application around this to automate my apartment’s intercom. The intercom is configured to call my Twilio number, which will interact with the application. I called it “Riddlegate” after that plotline in The Neverending Story with the sphinxes. It’s pretty simple and self-explanatory. Here’s a screenshot of the admin UI:

X30j6Vt

Now when I have a guest, I can give them instructions that don’t involve me being near my phone:

  1. Dial <number>
  2. Wait for tone
  3. Dial <passcode>

And Riddlegate will buzz them in!

A (hopefully-not-too-terse) setup guide is included in the Github README.

Security

Given that this controls access to your building/complex, security is an important concern. There are a few things Riddlegate does to improve security:

  1. Twilio signs all requests it sends with your API key. Riddlegate validates these signatures and denies access when it detects an invalid signature. This prevents a would-be attacker from brute-forcing your access code if they were to discover your endpoint URL.
  2. Admin area is password-protected. This is obviously only as secure as the password you choose. Also obviously better if you serve over HTTPS.

Security cameras: automatically recording and uploading footage when a door is opened

My last post detailed how to integrate a cheap IP cam with SmartThings. I briefly mentioned a SmartApp that took a picture when the door opened. This was pretty straightforward. I wanted to take it a step further and trigger recording when my door was opened (but no one is home). Beyond the obvious, I had the following requirements:

  1. SmartThings needs to be able toggle recording. The SmartApp should notify my household when it begins recording.
  2. Tampering with the camera shouldn’t destroy already captured footage.
  3. Footage should start uploading somewhere offsite as soon as possible.
  4. Control over uploaded footage.

I already covered (1) in my last post. My integration with the IP camera enables a scheduled recording feature, and configures this feature to always record. Switching off recording clears the schedule.

Uploading footage to S3

The camera I’m using already has builtin support to upload footage to an FTP server, which leaves everything but uploading to offsite storage.

Since it’s easy and cheap, I decided to upload footage to Amazon S3. I then needed a tool that:

  1. Watched for newly created files to appear in the directory my internal FTP server is pointed at. When a new file is detected:
  2. Immediately begin a streaming upload to S3. Since the file size isn’t known ahead of time, I made use of the multipart upload API, which allows for the breaking down of uploads into smaller (5MB) chunks.
  3. When the file is done being written to, complete the upload (i.e., tell Amazon the file is done being uploaded). This makes the file available on S3.

This seemed like a good fit for inotify, which allows for the monitoring of filesystem events. It’s possible to set up notifications that are triggered when, for example, a new file within a directory is opened, closed, or modified.

I didn’t find a tool that did exactly what I wanted, so I made a ruby library that did. I called it “s3reamer“. My sincerest apologies for being an awful portmanteau-ist. I run this on my home server:

This will automatically begin uploading to S3 when recording on the device is triggered. Here’s a snippet from the log file:

Uploading starts within a few seconds of recording being switched on. Most of that delay is waiting for the camera to begin uploading.

SmartApp to trigger recording when door opens

This part was pretty straightforward. Code below. This also sends a push notification when recording is switched on so my household knows and can react accordingly.

Integrating Foscam FI9821P with SmartThings

Motivated mostly by curiosity, I was recently in the market for a cheap IP camera. After a little bit of research, I settled on a Foscam FI9821P (I got mine for ~$45 as an Amazon Warehouse Deal). The app provided by Foscam is pretty nice, but I wanted to integrate it with my home automation setup as well. In particular, I wanted to accomplish the following:

  1. Secure access. Any communication with the camera should require some secure authentication mechanism.
  2. SmartThings integration. I wanted a device in SmartThings I could play around with.
  3. REST endpoint. Although I could probably get most of what I want done with SmartThings alone, I didn’t want to be bound to it.

SmartThings has a device type for cameras, so as long as there’s some way to access the camera within SmartThings, (2) is easy. In a previous post, I outlined a setup that uses HMAC to secure communication with smart home devices. I leveraged it in this project as well.

I should mention that I stumbled across some existing attempts at this, but nothing that would’ve given (1) and (3).

I put together this route for my home automation gateway, which accomplishes (1) and (3). With it, I can capture a snapshot and control some rudimentary functionalities of the camera. I can, for example, request a snapshot of what the camera is currently seeing simply by accessing this URL (with the appropriate security headers in place):

http://HA_GATWAY_URL/camera/foscam1/snapshot.jpg

You can see that there’s baked in support for multiple cameras (since the endpoint is scoped by a camera name). While I don’t anticipate buying more cameras, I figured adding support would make this project more generally useful.

To integrate with SmartThings, I created a virtual device (code embedded below). It allows me to request an image, shift the camera to one of three preset positions, and to start/stop recording. Here’s a demo of the interface:SmartThings Interface

This project was a lot of fun, and quite a bit easier than I was anticipating. My favorite thing this has enabled is a SmartThings SmartApp that signals the camera to take a picture when my front door opens. To avoid being too creepy, this only happens when no one is home. If I can muster the motivation, I’ll probably write a separate post about that.