Weekend Project: Web-controlled Christmas Lights with Node.js, Arduino, and Raspberry Pi

Christmas Lights

This is my Node.js “hello world.” It’s a weekend project that allows you to control GE Color Effects lights over the internet through the use of a Raspberry Pi (running nginx and a Node.js application) connected to an Arduino. Like I say in the video, I think it may be possible to control the data line of these lights directly from the Raspberry Pi’s GPIO pins, but I already wrote an Arduino library┬áto handle that and it works nicely.

Tech Stuff

The setup is fairly simple. The Raspberry Pi runs a frontend with my webserver of choice, nginx. It serves up a static page on / and proxies to my Node.js application on /api. Post data sent to /api is decoded by the Node application and matched with a hex value (assuming the color sent was valid). This hex value is then packed into the two-byte serial format I developed for my Arduino library, and sent over serial to the Arduino. Internally the Arduino uses a data structure called a circular buffer. Circular buffers are especially cool for this usage, because when I ‘push’ a light onto the string of lights, every single light needs to be updated (as each color is ‘moving’ down the line). With a circular buffer, the data structure remains a constant size, and all that’s required to update it is to write a new value at the ‘head’ location and then increment the location of the head. More specifics about how this works can be found in the linked Wikipedia article as well as the source code for the aforementioned Arduino library.

I had a lot of fun with this project. One thing I really like about Node.js is how simple it makes creating APIs that can do Really Cool Things. Using just the JavaScript environment available in my web browser, I can package the color data in the format Node needs it, and let Node handle the rest. Node.js is not for everything, but the ease of communication between browser and application makes it a joy to work with.

Do It Yourself

Get a Raspberry Pi set up with Node.js installed, and an Arduino with the sketch linked below flashed to it. To flash the Arduino, you need the GEColorEffects library as a dependency. ┬áConnection to the lights themselves is outside of the scope of this post, but more info can be found in darco’s original post. Clone the nodejs-christmas-lights git repository onto the Raspberry Pi. Ensure that the Arduino manifests as a serial port (usually /dev/ttyACM0) on the RPi, and chmod it to be accessible by your user. A simple ‘chmod 777 /dev/ttyACM0′ should do, since (hopefully…) your Raspberry Pi isn’t a production box.

Set up nginx on your Raspberry Pi, and put the contents of the nodejs-christmas-lights repository’s www folder in your webroot. Again, this is more or less outside the scope of this post, but the following config should act as a starting point. Important to note is that the /api path must forward to the host/port of your Node.js application.

server {
    listen 80;
    server_name lights;

    root /var/www/vhosts/lights/htdocs;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location /api {
        proxy_pass http://localhost:8080;
    }
}

If all is set up correctly, navigate to the Raspberry Pi in your browser, choose a color, and hit the ‘Go!’ button.

Resources

Feel free to ask questions in the comments. If you do something cool with this code, I’d love to hear about it!

    • Dovy
    • September 25th, 2013

    So… could you change the buffer to add the color to more than just the end of the string? Seems like you could do a pretty cool string effect by doing multiple hexes at once. Very interested in your work. I’d probably mod it to be all javascript instead of python. ;)

    • Gnewt
    • September 25th, 2013

    Yeap. They’re all individually addressable, so the lights can be controlled in any arbitrary pattern. And this release is all JavaScript! I had previously written a Python version but the code I put up on GitHub and talked about in this post is pure JS.

  1. I’m glad I stumbled onto your Youtube page. It got me thinking about something. There must be some module for Node that can interpret color values from a web video file. Or if not, one could be built. I can see using Node’s realtime architecture for playing Christmas videos through your Christmas lights.