Screenshot-Dashboard - Google Chrome So, the other week I made a simple security device for my house, using a Raspberry Pi, that will (when I have a moment to wire it up), give a read out before I leave the house telling me if I have any windows or doors open.

Since I’ve been coding this Home API thing, the next obvious step is to wire the it up to the API so other things could make use of the data.

The first step was to modify the code running on the Raspberry Pi to transmit the status of each switch to a central server as a JSON POST request whenever something changed. On the server, I wrote a plugin which accepted this payload and stored for display, using the newly coded CouchDB support. This means that Home.API doesn’t have to poll the device, which would be more complicated and less efficient.

Sending data Home.API

Here is the client code, complete with Home.API integration:

The important lines of code are between lines 68 and 78. These lines check whether an update needs to be sent (we check for a state change in one of the lines we’re monitoring, and raise a flag if it is different from the last pass), and then package up an array of results as a JSON object and fire it over to Home.API using HTTP.

In our plugin

On the server, our class endpoint is loaded, and our decode method called. For efficiency we store this in a NoSQL database, which our display function getAll() just echos the contents off.

public function update() {
$result = json_decode(\home_api\core\Input::getPOST());

if ($result === NULL)
throw new \home_api\plugins\PluginException(i18n::w ('raspberrypidistw:exception:no_json_data'));

// Decode status
$this->status = array();
foreach ($result as $key => $value)
$this->status[$key] = $value;

// Create couch store
$uuid = \home_api\storage\nosql\NoSQLStorage::generateUUID($this, 'LastValues');
$couch = \home_api\storage\nosql\CouchDB::getInstance();

// See if there is an existing status
$latest = $couch->retrieve($uuid);
Log::debug("Retrieved: " . print_r($latest, true));
if (!$latest)
$latest = new stdClass();
$latest->status = $this->status;

// Store revision
Log::debug("Updating UUID:$uuid with " . json_encode($latest));
return $couch->store($uuid, $latest);
}

Pretty simple, have a play!

Home.API The modern world is full of cool gizmos, but our houses are pretty primitive by comparison.

Still, more and more houses are getting water and electricity smart meters of one sort or another. Various new home automation, like the Belkin Wemo, are hitting the market, and that is not to mention all the home brew efforts that various hackers are putting together themselves.

As you can see from other posts on this blog, I’ve been having a bit of fun playing around my Current Cost smart electricity meter, as well as playing around with the Raspberry Pi and PiFace, which has got me thinking about building a number of appliances around the place to solve a number of real world problems around the house – monitoring and controlling a number of things (I’ll post some more on this later).

So, problem is, all these devices have their own ways of talking to them, reading data and controlling them, and I thought it’d be cool if we had a common and easily extensible API, which you could talk to using standard web technologies. Having such a platform would enable people to start wiring things together in unexpected ways, using a variety of different devices, the more apis get added the more possibilities you have!

Introducing Home.API

Hacked together as an itch-scratching weekend project, Home.API is my first stab at solving the problem. It is a PHP 5.3+ web app that runs on a web server and is designed to be easily extensible through simple plugins and human readable configuration files.

Out of the box it includes a couple of demo plugins, and a simple dashboard, although the real power comes from its extensible JSON API which can be accessed by simple web calls.

Key features

  • Simple plugin format and configuration files.
  • Wire up the API in a branch structure which suits, use each plugin multiple times.
  • Simple but powerful development dashboard.
  • Currently a JSON API, but trivial to extend to other output formats using a powerful template system.

Format of an endpoint definition file

You API is defined using one or more configuration files in the /def directory. The configuration file contains a number of entries, separated by blank lines, each one defines the endpoint, class to use, and any initialisation parameters.

E.g.

/bedroom/light
    class \x10\DimmerLight
    minvalue 0
    maxvalue 50
    deviceIP 192.168.0.45

/hallway/light
    class \x10\DimmerLight
    minvalue 0
    maxvalue 100
    deviceIP 192.168.0.46

Making a call

Making an API call is simply a matter of making a call to a URL http://my.home.api/api/your/endpoint/function.format?param1=xxxx¶m2=yyyy, where function.format is the exposed method of the plugin class, and format is the template to use (e.g. json).

Each of these endpoints can act independently, and in our example you might be able to execute commands like:

http://home.local/api/bedroom/light/currentLevel.json

or

http://home.local/api/bedroom/light/setting.json?level=20

or

http://home.local/api/hallway/light/off.json

Have a play, and let me know what you think!

» Visit the project on Github…