• iot

Real Time Error Reporting System

We have a well tested and stable codebase so we don’t have too many errors in our production environment. However things change (including third party services) and when things eventually go wrong I want to know about them and quickly.

The traditional method of troubleshooting may be through scheduled testing, trawling through log files or worse yet waiting for the end consumer to notify of an issue. Wouldn’t it be nice if you could be notified in real time as and when errors occur?

Bugsnag

Here’s where Bugsnag comes into play as it claims to ‘automatically detect crashes in all of your applications’. What this means in practice is it notifies when an error occurs and shows where and when it occurred (including a helpful stacktrace where available) and how many users are affected. It’s incredibly simple to install for most platforms and once it detects an error can notify of the error via a variety to methods from email to a Hipchat notification to a custom webhook. However, I wanted something a little more ‘in your face’ such that when an error occurs a big flashing alarm goes off above my desk. This is pretty hard to ignore…

Spark Core

Having procured a novelty police beacon light and secured it into place conveniently above my desk I set about looking for ways to control the device over the internet.

To control the device I turned to the Spark Core. Think of Spark as an internet connected Arduino type device. The brilliance of Spark is that the device is always connected to the ‘Spark Cloud’ and exposes a beautifully simple REST API that you can use to control your core over the internet.

As the novelty police beacon light is a powerful beast requiring 120V of power, which the Spark Core can’t provide without a relay, I hooked it into a PowerSwitch Tail. The PowerSwitch Tail is a relay which removes the need to mess around with the wiring of a wall outlet device as you can simply plug in the device to the PowerSwitch Tail directly. To attach it to the Spark core simply connect Spark pin D0 to the + terminal of the PowerSwich Tail and the ground pin of the Spark core to the -ve terminal. Now setting digital pin 0 to HIGH turns on the relay and whatever device is plugged into the PowerSwitch Tail.

PHP Wrapper Library

The Spark Core ships with default firmware that exposes various methods to control the Core over the internet. These require submitting an API request to the Spark Cloud which is always connected to the Core. To simplify the process of submitting the requests, receiving responses and handling errors I created the SparkPHP library which is largely based on Guzzle.

This library is installable via composer and includes a number of examples that demonstrate all methods of the Spark API.

"require": {
    "wensleydale/spark": "dev-master"
}

So the simplest script that would turn on the alarm would look something like this:

 use Wensleydale\SparkCore;
 use Wensleydale\SparkException;

 require $_SERVER['DOCUMENT_ROOT'] . '/vendor/autoload.php';

 //Get your access token from either the Spark Build site or make a token request
 $accessToken = 'my_access_token';

 //Create a new Spark instance
 $core = SparkCore::make($accessToken);

 //Set the device that you wish to interact with
 $core->setDeviceId('my_device_id');

 $core->setPin('D0');
 $core->setValue('HIGH');

 $result = $core->digitalWrite(); //Alarm is on

Turning the alarm off with Iron MQ

Once the alarm is turned on, there needs to be a way to turn it off. This can be achieved simply by setting pin D0 to ‘LOW’ so

 $core->setValue('LOW');
 $result = $core->digitalWrite();

Whilst this could be configured such that the alarm was only turned off when the error was resolved I decided to turn off the alarm after a suitable time period, say 2 minutes. There are various approaches that can be taken to achieve this from using delay() in the Spark firmware, or a more crude method of using sleep() in a PHP script. However there are some associated issues with using delay() and I wanted this application to use the default tinker firmware so I used IronMQ to push a new message to a queue with a delay that would POST to an ‘alarm_off.php’ script after a suitable delay. To utilise IronMQ queues add the following to composer.json

"require": {
    "wensleydale/spark": "dev-master",
    "iron-io/iron_mq": "1.5.1"
}

You will need to configure a new queue, set it as a push queue and add a subscriber URL to an accessible alarm_off.php script. Now, when we have successfully turned the alarm on, we send a new message to the queue:

try {
     $result = $core->digitalWrite();

     if($result->return_value)
     {
         //Send an off message to the queue
         $ironmq = new IronMQ(array(
             'token' => 'my_token',
             'project_id' => 'my_project'
         ));

         $ironmq->postMessage("Alarm", "Turn Off Alarm", array(
                 'delay' => 120
             ));

         echo "The alarm is on. We will automatically turn it off after 120 seconds if you don't do it before.";
     }

 } catch (SparkException $e) {
     echo "There was an issue with the digital write method";
 }

Bringing it together

So now when Bugsnag detects an error it POSTs to a custom webhook which contains an alarm_on.php script that will turn on the alarm and send a message to the IronMQ push queue with a delay. After that delay is up a new message is POSTed to the alarm_off.php script which turns off the alarm.

To test the system I simply added a method to throw an uncaught ‘AlarmException’ Exception. Here’s the resulting page in Bugsnag.

The delay from the exception to the alarm turning on was negligible (a fraction of a second). Clearly, as I have created generic pages for turning the alarm on and off I can repurpose the alarm for any API that permits webhooks and with the Spark Core you can hook up just about anything to be controlled so the opportunities are near limitless.