Cheerlights

When we first launched the Light on Kickstarter, we received mail from some folks who had what looked to be an interesting project – Cheerlights.  Basically it uses Twitter and some other server software to provide a universal ‘color’ for Internet-connected Christmas lights.  You can set a color on Cheerlights by posting a tweet with the hashtag #cheerlights somewhere in it, followed by a color name (white, warmwhite, red, orange, yellow, green, cyan, blue, purple, magenta).

The Cheerlights server listens for that sequence, then publishes the current color value in a JSON object accessible here. Devices can poll that object to learn the current Cheerlights color, and respond accordingly.

It’s all quite straightforward, and it was sitting on my to-do list until this week, when I started to give a real though to Christmas lights.  We’ll be doing a special holiday video and livestream a ‘change the color Light under the Christmas tree’ for folks to have a play, but on the way to that, I decided to have a look at Cheerlights, saw that it was going to be almost trivially easy to implement in our API, then wrote the whole thing in about 30 minutes  – in bash.

That’s right, we’ve implemented Cheerlights as a shell script. This means it’s quite fast – Python doesn’t need to load – and also very portable. It should run in some easily modified form on any *NIX box in the universe.

It does rely on two programs: cURL, which is considered part of the base package in most LINUX distributions, and jq, which is a command-line JSON parser in ‘C’, very fast, very flexible, and very powerful. As we do manipulate a lot of JSON data on the Light, we’ve compiled this package for the Light, and will ship it as part of the Light’s system software.

Here, in full, is the shell script:

#!/bin/bash

#

# Set the Light to the current CheerLights color

# This is all done in bash. Because we can?

#

# Copyright (c) 2012, Mark D. Pesce

# Released under the MIT License.

#

# First grab the current CheerLights JSON thingy, then parse it to extract field1

# Which happens to be the current color value

#

color=`curl -s http://api.thingspeak.com/channels/1417/field/1/last.json | jq .field1`

echo $color



# Now parse the color value which should be one of these fine colors maybe

#

case $color in

"red") echo "We got red"; export QUERY_STRING="color=0x80FF80"; /srv/http/cgi-bin/ajaxcolor

;;

"cyan") echo "We got cyan"; export QUERY_STRING="color=0xFF80FF"; /srv/http/cgi-bin/ajaxcolor

;;

"warmwhite") echo "We got warm white"; export QUERY_STRING="color=0xFFFFbF"; /srv/http/cgi-bin/ajaxcolor

;;

"white") echo "We got white"; export QUERY_STRING="color=0xFFFFFF"; /srv/http/cgi-bin/ajaxcolor

;;

"blue") echo "We got blue"; export QUERY_STRING="color=0x8080FF"; /srv/http/cgi-bin/ajaxcolor

;;

"green") echo "We got green"; export QUERY_STRING="color=0xFF8080"; /srv/http/cgi-bin/ajaxcolor

;;

"yellow") echo "We got yellow"; export QUERY_STRING="color=0xFFFF80"; /srv/http/cgi-bin/ajaxcolor

;;

"magenta") echo "We got magenta"; export QUERY_STRING="color=0x80bfFF"; /srv/http/cgi-bin/ajaxcolor

;;

"purple") echo "We got purple"; export QUERY_STRING="color=0x80FFFF"; /srv/http/cgi-bin/ajaxcolor

;;

"orange") echo "We got orange"; export QUERY_STRING="color=0x90FF80"; /srv/http/cgi-bin/ajaxcolor

;;

*) echo "We got no match at all"

;;

esac

The script needs to be run for every Cheerlights update, which could be done as a cron task, or it could be part of a background daemon.

Demo: Photo Sampler

 

Here’s another web app that demonstrates how HTML5 and the Light can work in concert to do something that previously would have required a dedicated platform app.  The Photo Sampler uses the HTML5 Canvas 2D and File interfaces to allow the user to pick a photograph (or take a photograph) from the device – which could be a computer, tablet, or smartphone.  It then puts that image onto the canvas, and where the user touches the image, the color at the touch point is sent to the Light using REST.

Although it’s still a wee bit buggy on iOS (which seems to take great liberties with EXIF data), it works quite well.

Here’s a link to the source. It’s a mix of HTML5 and Javascript. Enjoy!

Demo: display the air pollution level

After I posted the UV Index demo, a kind person pointed me to some live air pollution data helpfully supplied by the government of Hong Kong.  It was a very straightforward matter – using the awesome feedparser Python module – to extract the air pollution level for Central Hong Kong, and convert that to a color which is then displayed on the Light:

#!/usr/bin/python

#

import feedparser

import sys, urllib2, string



d = feedparser.parse('http://data.one.gov.hk/dataset/2/en')



for entry in d.entries:

	parts = string.split(entry.title, ' : ')

	if parts[0] == u'Central':

		pollution = parts[2]



colorval = 0x808080



# Map the value based on the value provided in the feed

if (pollution == u'High'):

	colorval = 0xFFFF80

if (pollution == u'Very High'):

	colorval = 0x80FF80

if (pollution == u'Low'):

	colorval = 0xFF8080



colorstr = "http://localhost/cgi-bin/ajaxcolor?color=0x%6x" % colorval

print colorstr

e = urllib2.urlopen(colorstr)

Demo: display the UV Index

Here’s a little something that was adapted from a URL in a comment thread posted to this blog.  The real-time UV indices for various points in Australia are posted by the Australian Radiation Protection and Nuclear Safety Agency.  It’s a fairly simple matter to extract that information from an XML file, and set the Light an appropriate color:

#!/usr/bin/python

#

import xml.etree.ElementTree as ET

import sys, urllib2



f = urllib2.urlopen('http://www.arpansa.gov.au/uvindex/realtime/xml/uvvalues.xml')

d = f.read()



root = ET.fromstring(d)



uvalue = 0.0

for child in root:

	if (child[0].text == 'syd'):  # For Sydney

		uvalue = float(child[1].text)



colorval = 0x808080



# Map the value based on the chart given at http://en.wikipedia.org/wiki/Ultraviolet_index

# Which is, you know, easier than visualizing it.

if (uvalue < 2.9): 	

   colorval = 0xFF8080 

if ((uvalue > 2.9) and (uvalue < 6.0)): 	

   colorval = 0xFFFF80 

if ((uvalue > 5.9) and (uvalue < 8.0)): 	

   colorval = 0xBFFF80

if ((uvalue > 7.9) and (uvalue < 11.0)): 	

   colorval = 0x80FF80 

if (uvalue > 10.9):

	colorval = 0x80FFFF



colorstr = "http://localhost/cgi-bin/ajaxcolor?color=0x%6x" % colorval

print colorstr

e = urllib2.urlopen(colorstr)

There’s a lot more that could be done here to make this easy to use, handle all the various cities, etc. But it’s a good basic example of how to use external data sources to drive the Light.