A pragmatic programmer

2 notes &

Connected lighting is jump-starting home automation

I’ve been working on the Philips hue lightbulbs for more than a year now, specifically on the internet connectivity part. And I’ve found that hue is the start of a much bigger movement. Let me whow you.

Remote control
The hue kit that you can buy at the Apple store has a few built-in remote features. First, there’s the basic “remote control" from outside of your house. Secondly there’s geofencing. By setting a perimeter around your house, you can let your app turn the lights on before you even open the front door. And thirdly, there’s IFTTT, which lets you create triggers on internet events to control your lights. For example, you can have the lamp in your hallway turn blue if it’s going to rain and you should bring your umbrella when you go out.

Build your own apps
Philips also opened up the internal API of the hue bridge to the public, allowing you to build your own apps. This of course resulted in loads of different interfaces on various devices.

But it also sparked more creative minds, like the hue disco app, that reacts to sounds via the microphone, and you can create your own in-home disco lighting. Or the goldee app that uses dynamic scenes, where the light gradually and slightly changes color over time, to mimic a more natural lighting.

Combining with other devices
But that internal API also enables your lights to talk to other devices in your house. The goldee box is a wall switch that can control your hue (or lifx, or ilumi) lighting, and improves your interaction with lighting without the need of a smartphone.

Take it a step further and you arrive at the revolv. It’s a box that you install somewhere in your house, and it can talk multiple channels. Not just lighting, but also your wemo outlet, yale lock, sonos sound system and others. And this thing is already in production, I have one sitting next to me on my desk at Q42.

The future
These things all exist today. Look how far we’ve gotten. But there’s still a bright future ahead for home automation. The nest thermostat and nest secure are doing a pretty good job at presence awareness and more importantly, presence prediction. If your house knows you’re going to need a warmed-up house, it can arrange that for you. Same goes for lights, music, etc. And it’s not just your house that’s connected to this ecosystem. The Tesla Model S for instance, also has an API.

So hue is really at the start of a bigger ecosystem of connected products. By being an open system, it’s using that ecosystem to make itself more useful. And I’m excited to be a part of that.

1 note &

Hosting static files on Google App Engine (GAE)

I’m currently working on an app for the new FirefoxOS phone’s hitting the market. A small html/js/css only app that you can run offline and controls your Philips Hue lightbulbs. Who wouldn’t want a $60 dollar phone to control your $200 lightbulbs? My point exactly.

So I have a really lightweight app, that I want hosted. And as I’m doing nearly everything with Google App Engine hosting these days, I want the html/js/css files hosted there.

The easiest way, I found, was to create a Python project. You’ll only need one extra file on top of the static files you have, and put all your files in a subdirectory of the project (say “static_files”). The file is called app.yaml and has something like the following content:

application: firefoxos-hue
version: 1-0                #no . characters allowed :(
runtime: python27
api_version: 1
threadsafe: true

- url: /                         # redirect the homepage to index.html
  static_files: static_files/index.html
  upload: static_files/index.html
- url: /(.*)                     # serve all other files as if they were in the root
  static_files: static_files/\1
  upload: static_files/(.*)

The top block is some metadata about the project, below that the URL handlers. One handler serves index.html when users access the homepage. The second serves all static files from the static_files directory directly to users.

Now you can use the Google App Engine Launcher to import this directory, run it locally, or deploy it as an appengine project.

0 notes &

Open Data Anthology

I was at the The Hague Open Data Meetup this evening. It was held at the Dutch National Library (KB), and I recognized a scenario they’d encountered during their first Hackathon: the developers didn’t know what to do with the data the KB offered, and nothing came out of it.

The problem is that the data of the KB wasn’t appealing to the attendees of the hackathon. The data was OCR-scanned 18th century books. Who attends hackathons? Developers. What do they know of 18th century literature? Nothing.

To get meaningful information out of the dataset, you need other people than just developers. Researchers and people that have insight into the content itself, they are the people that come up with interesting concepts, so you have to get them aboard! 

Let’s start with giving the event a different name. "Hackathon" is a really nerdie term, and going to scare away others. 

How about “Jam”, “Anthology”, “Assembly”, “Poem night”…

0 notes &

Single Page Interface using Backbone

Here’s a little snippet that contains the bare basics of a single page interface built in backbone.

var AppRouter = this.Backbone.Router.extend({
    routes: {
        “*actions”: “defaultRoute”

var app_router = new AppRouter();

This creates a Backbone Router. When this router receives a “navigate” command, it in turn triggers the “route:defaultRoute” event.

app_router.on(‘route:defaultRoute’, function (actions) {
    var contentcontainer = $(‘#body .main-content’);
    $.get(‘/’ + actions).then(function (data) {
        contentcontainer.html(‘<div>ajax loaded:</div>’ + data);
    }, function (data) {
        contentcontainer.html(‘An error occurred: ’ + data);

Now, when the defaultRoute is triggered, the url it is navigating towards is retrieved via ajax and then inserted in the contentcontainer.

    pushState: true,
    root: “/”,
    silent: true

To keep the history and url’s working, we initiate the Backbone history, with pushState.

$(function () {
    $(‘body’).on(‘click’, ‘a’, function (evt) {
        app_router.navigate($(this).attr(‘href’), {
            trigger: true

And then to tie things together: on each link in the page, prevent the default action and trigger the routing.

On the server you can see if the request is AJAX or not. If it is, don’t return the header and footer, just the contents of the main-content element. If it’s not and AJAX call, then serve the entire page. This way the entire site works like a single page interface, but when you reload the page it’ll work too.

This is especially neat because search engines often don’t use javascript the same way your typical user does. Using the above approach makes the website navigable without javascript.

Best of all, it’s extensible! Want a specific pagetransition to animate? No problem, create a route for it and handle that specific transition.


1 note &

OkCupid put a smile on my face

A colleague encouraged me to try out OkCupid. For educational purposes of course: they had a very addictive way of getting users to answer a bunch of questions about themselves. He had himself answered hundreds (!!) of questions.

But what I liked most about my 5 minutes on OkCupid was the feedback on the registration flow. Check out the city box, when I fill in that I’m from Leiden:


I really liked the feedback and it’s tone of voice. But it got me wondering what it would do with more difficult input. So I typed “haag”:


Awesome, so it had a good location search. Now let’s just pick one and move on:


Whow! Didn’t see that coming :)
The password feedback also put a smile on my face:


After this experience I was looking forward to the questions that I was actually here for. But I didn’t even get beyond the first question: “What are you looking for? A: Sex or B: True love”. How am I going to explain either answer to my wife?

0 notes &

It’s w00tcamp time!!! And I’m creating awesome stuff with the Philips Hue lamps! George from Philips brought about 50 lamps this way and we’re lighting up the entire office :)

2 notes &

Social responsibility

Today I held a presentation at Q42, about Q42. The listeners were four entrepreneurs from developing countries (kosovo, pastina) who are in the process of building or running a technical enterprise. The BiD Network helps these people by getting them in contact with companies that can aid them in their development process.

When they asked me, I couldn’t say no to an oppertunity to tell people how awesome Q42 is. And if I could help these entrepreneurs by doing so, all the more reason.

So I told them about our developer-centric working environment, with project- and company management as facilitators to the all-mighty developers. About our 48 employees of which 45 are developers. Each one motivated by the cool projects they do, the cutting-edge technology they’re using, weekly passion-time, yearly w00tcamp, company outings, and so on.

The entrepreneurs were quite amazed when they learned that our founder Kars at some point hired a CEO so he could spend more time developing again. The people I told the story to were at this point founders of small companies, but they hadn’t foreseen this possible future for themselves yet ;-)

For me personally it was a good exercise in explaining outsiders what Q42 is and what it stands for. The devil is in the details, and it’s quite a challenge to put your finger on the sweet spot. And of course, a little CSR (that’s what google translate makes of it…) never hurts!

0 notes &


Small tip: don’t name your static files like “marketing.css”, because some ad blockers might think it’s untrustworthy and block the download of it :-$

Just found out the hard way…

0 notes &

Class not enhanced correctly - Siena

When calling my EnhancedModel.findById(Object) function, I get this error:

UnsupportedOperationException occured : Class not enhanced correctly

Turns out this is because inside the EnhancedModel I created an overload of the findById function with two parameters: findById(String, String).

This is also the case with getByKey(Object) function; if you create an overload with other parameters; class not enhanced correctly.