Here is the latest in a series of libraries I’ve been releasing which package up some of my often used, cut and pasted code, into reusable modules for myself and others to use.

So here is the companion piece to my previously released Web Services client library, a web services API endpoint library.

Usage

The library allows you to expose a Callable type (function, object method or static function, closure, and call it via a built in Simple Page Handler endpoint that you can attach to a virtual page (e.g. http://example.com/api).

The library will then use reflection to extract the required and optional parameters, and any default values to pass, and then pass them accordingly.

Once the code has run it’ll trigger an event which you should listen to and determine what format to output the results in based on the 'format' parameter. You might want to look at the Simple Template Library to help you here!

I’ve written an example handler that exposes a single API, but feel free to fire over any comments or questions!

» Visit the project on Github…

Current-Cost This is just a quick note to spotlight the fact that Home.API now has native support for the Current Cost EnviR smartmeter.

Setting it up

Check out the latest version of Home.API from the Github repository, and then attach the plugin to an endpoint by adding a definition to a .conf file in your def directory. E.g.

# Current cost envir
/power/smartmeter
     class \power\smartmeters\CurrentCostEnviR

This will install the plugin using the default parameters, but you can override these by specifying them in your definition. Available parameters are:

  • port, which defaults to '/dev/ttyUSB0'
  • baud, the baud rate to connect to, defaulting to 57600
  • timeout, defaulting to 10 seconds.

Your Current cost meter should be connected to the same machine as your Home.API install, and the web server user granted access to the comm port the device is connected to.

Exposed API

Once you have enabled the Current Cost plugin, you should see a new entry appear on your Home.API dashboard which gives a quick summary of the information retrieved from the device. It also makes available a number of functions which you can query at your endpoint (http://home.api/api/path/to/endpoint/), and these are:

  • time.json: Retrieve the time from the device.
  • temp.json: Retrieve the temperature from the device.
  • power.json: Retrieve the power in watts from the device.
  • latest.json: Retrieve all of the above at once, and return them as an array.

Visit the endpoint in your browser and see it working!

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!