Arduino, Redis, Dropcam + Holiday Cheer = Jinglebots!

Hopefully, you've been able to experience our Jinglebots -- the 2012 Pointless Corp holiday project -- for yourself. Klaus 5000, Cornelius, and Ru 2 Dee 2 are the Jinglebots -- “robots” which reside in each of our Viget offices.  They “speak” tweets and messages for all of the world to hear through a Dropcam feed. As a user, you can check out the web site and either tweet with the #jinglebots hashtag or submit a message through a basic messenger on the site.

I've estimated the amount of coordinating technologies to be around a bazillion. For those who may be interested in how to use your computer to control Christmas lights, power electric toy trains, or do other cool things (using Ruby!), I’ll walk you through how to do it below.

Step 1 - Instant Communication

We knew that we'd be responding to messages and tweets in real time. For this, we made use of Redis pub/sub capabilities. Redis is super simple to get going locally and use of RedisToGo gives you access to a free online Redis instance you can use in production. When a message comes in, we publish the message data (sender name, message, timestamp, etc.) in JSON to a Redis channel.

REDIS.publish("holiday_messages", data.to_json)

Each of our Jinglebots is subscribed to the holiday_messages channel.

REDIS.subscribe('holiday_messages') do |on|
 on.message do |channel, raw_data|
 data = JSON.parse(raw_data)
 ... some awesome stuff using the data
 end
end

Instant communication has never been easier.

Step 2 - Receiving Messages/Tweets

On the web site, a form allows users to submit a message and a name. On submission success, the app then compiles the necessary data, converts it to JSON, and publishes it to the holiday_messages Redis channel.

To capture incoming tweets with the #jinglebots hashtag, we made use of EventMachine and the twitter-stream gem. This bit of code owes great credit to Twerrible Towel which has their code open sourced. The following code takes care of all the Twitter listening for us.

EventMachine::run do

 stream = Twitter::JSONStream.connect(
 :path => '/1/statuses/filter.json',
 :auth => "#{twitter_username}:#{twitter_password}",
 :method => 'POST',
 :content => "track=#jinglebots"
 )

 stream.each_item do |item|
 tweet = JSON.parse(item)
 if tweet && tweet["user"]
 data = assemble_data(tweet)
 REDIS.publish("holiday_messages", data.to_json)
 end
 end
end

Step 3 - The Fun Part

So, with a stream of messages coming in, we had to figure out what to do with them. If you're on a Mac, open up the terminal and type say hello master. With the volume turned up, your computer has been given a voice! After some massaging of the incoming message (removing special characters, subbing out bad words for a system beeeeep), we now had robots which could speak any message we threw at them.

We weren't done though. What's a talking robot without a face? Enter the tag team work of designer Joseph Le and front-end developer Nate Hunzaker. A simple-yet-awesome Node.js app on Express meant that we had three different faces (one for each Jinglebot) which could be turned to "talking" and "not talking" mode with a curl command to the local server.

`curl --data "" http://localhost:3000/say?message=true`
`curl --data "" http://localhost:3000/shutup`

Open sourced code is available here.

Using the same Node.js/Express combination, a gif(t) displayer was coded up so the talking robots had something to display while they read your message aloud.

Step 3.5 - The Really Fun Part

Arduino time! An Arduino is a programmable microcontroller which allows you to develop in Processing and do cool things like turn on LEDs or make an Iron Man Costume. We're still pretty new at this stuff, so we went with the ability to control Christmas lights and an old electronic toy train set (maybe next year we'll go for the Iron Man Costume).

There's one more piece of this puzzle to introduce which made this process super easy -- dino. Dino is an awesome gem which lets you control your Arduino using Ruby. Simply load up the dino code to your Arduino, set up your board in Ruby, and start sending power where you want it.

require 'dino'

board = Dino::Board.new(Dino::TxRx.new)
pin = Dino::Components::Led.new(pin: 13, board: board)

pin.on
sleep 4
pin.off

We made use of a relay and a power cord cut in half. When the relay switch is open, no power can pass from the wall to our appliance. When we give the command pin.on, we send 5V to our relay, closing the switch, powering our appliance with a full 120V from the wall. A basic tutorial of how to set this up is available here.

Note: To get the Christmas lights to flash, we actually set a Redis key named "flash" to true or false and had a Ruby script checking that variable every second and flashing the lights independent of the robot. This was done to keep blocking operations from interfering with each other.

Step 4 - The Web Site

Viget's home turf. Designer Mark Steinruck, UXers Jason Toth and Lance Gutin, and again the almighty front-end developer Nate came together to make a festive, easy, and fun-to-use site. We leveraged the Dropcam already set up at each office to let users watch each Jinglebot right on the sight, and displayed a running list of the most recent messages, as well as aggregate stats, on the bots and messages.

Messages and tweets that came in were not only published to the Redis channel, but were also saved to a PostgreSQL database with the help of DataMapper. In this way, we had a clean and organized record of all messages that came in to the Jinglebots.

Step 5 - The Jingle Report

As a little bonus, we wanted to give the user more than just a talking robot. A Jingle Report was created for every message or tweet that came in, and tweets were sent to users with the Report link to view. Here's a personal favorite - http://jinglebots.com/report/901.

Each report required a screenshot of a Jinglebot scene, as well as a voice recording of the message. LAME was used to convert the saved audio files (say -o file/path/to/save.aiff message) into web-friendly formats, some Dropcam craftiness was used to grab screenshots from a given time (thanks to a post in this forum), and Amazon S3 was used to store these assets. Boom: Jingle Reports.

Step 6 - The Auto Pilot

Cronjobs were a big win for this project. Having the code systematically restart every so often meant that if anything did go wrong (a lot of coordinated tech -> a lot of potential problems), it would take care of restarting itself.

This was a major component for things like the amount of sleep Ben and I could get without having to restart the Jinglebots after they mysteriously crashed in the middle of the night. The code behind this is here.

Summary

On Friday the 21st, the Jinglebots had been spreading holiday cheer for two whole weeks, and the project was a blast to work on. It was a great combination of Viget’s coding skills, as well as our discovered "building-real-things" skills. More on why the crew involved came together to build something like this can be read here.

Jinglebots was the brainchild of Ben Eckerson (without him the project would never have existed) and the collaborative effort of many - Becky Tornes, Khanh Stenberg, Anjali Mckenzie, Mike Ackerman, and the whole Viget dev team for their advice and mentorship.

Happy Jinglebottin!

Eli uses his mathematics degree from Carnegie Mellon to blur the lines between the digital and physical worlds. He codes for Shure, Volunteers of America, and other clients from our Boulder, CO, office.

More posts by Eli