Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@harrisonhjones
Last active July 9, 2016 18:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harrisonhjones/335b16c4123814c5c9f5cf3ffbc84d4b to your computer and use it in GitHub Desktop.
Save harrisonhjones/335b16c4123814c5c9f5cf3ffbc84d4b to your computer and use it in GitHub Desktop.
Particle Device IsUp Report Generator
module['exports'] = function particleDeviceIsUpCheck (hook) {
// User parameters
const DEFAULT_TIMEOUT = 5000; // The default request timeout in milliseconds
// The list of devices the check
var devicesToCheck = [];
devicesToCheck.push({deviceID: '39002a000547343432313031', method: 'info'});
devicesToCheck.push({deviceID: '350037000347343337373739', method: 'variable', variableName: 'fv', expectedValue: 'ninjas'});
// Reporting function. Change this to whatever you want. The function is called after all the devices are checked. The parameter 'devices' is an array of all devices. Each device has the following properties: name, deviceID, method, online, and (sometimes) error.
function handleIsUpReport(devices) {
var isADeviceOffline = false;
var isException = false;
var emailBody = '<h1>Particle Device "Is It Up" Report</h1>';
emailBody += '<table border="1"><tr><th>Status</th><th>Name</th><th>Device ID</th><th>Exception / Error</th></tr>';
for (var i = 0; i < devices.length; i++) {
emailBody += '<tr>';
var d = devices[i];
switch(d.online) {
case 'yes':
emailBody += '<td>online</td><td>' + d.name + '</td><td>' + d.deviceID + '</td><td>' + d.error || '' + '</td></tr>';
break;
case 'no':
isADeviceOffline = true;
emailBody += '<td><b>offline</b></td>' + d.name + '</td><td>' + d.deviceID + '</td><td>' + d.error + '</td></tr>';
break;
default:
isException = true;
emailBody += '<td><b>' + d.online + '</b></td>' + d.name + '</td><td>' + d.deviceID + '</td><td>"' + d.error + '</td></tr>';
break;
}
};
emailBody += '</table>';
emailBody += '<h2>Raw Output</h2>' + JSON.stringify(devices);
var subject = 'Particle Device "Is It Up" Report. ';
if(isADeviceOffline)
subject += 'Device Offline. ';
if(isException)
subject += 'Device Exception. ';
var nodemailer = require('nodemailer');
const SMTP_HOSTNAME = 'smtp.mailgun.org';
var transporter = nodemailer.createTransport('smtps://' + hook.env.MAILGUN_SMTP_USERNAME + '%40' + hook.env.MAILGUN_SMTP_DOMAIN + ':' + hook.env.MAILGUN_SMTP_PASSWORD + '@' + SMTP_HOSTNAME);
// setup e-mail data with unicode symbols
var mailOptions = {
from: '"Particle Device Is It Up Service" <' + hook.env.MAILGUN_SMTP_USERNAME + '@' + hook.env.MAILGUN_SMTP_DOMAIN + '>', // sender address
to: hook.env.APP_PARTICLE_DEVICE_ISUP_TO_EMAIL, // list of receivers
subject: subject, // Subject line
text: JSON.stringify(devices), // plaintext body
html: emailBody // html body
};
transporter.sendMail(mailOptions, function(error, info){
var returnObject = {};
if(error){
returnObject.ok = false;
returnObject.error = error;
}
else
{
returnObject.ok = true;
returnObject.info = info.response;
}
hook.res.end(JSON.stringify(returnObject, true, 2));
});
}
// ----------------------------------- //
// DO NOT CHANGE ANYTHING BELOW THIS //
// UNLESS YOU KNOWN WHAT YOU ARE DOING //
// ----------------------------------- //
var rp = require('request-promise');
var Promise = require("bluebird");
var deviceIsUpPromises = [];
for (var i = 0; i < devicesToCheck.length; i++) {
// console.log(devicesToCheck);
var device = devicesToCheck[i];
var url = '';
switch (device.method) {
case 'variable':
deviceIsUpPromises.push(getIsUpByVariable(device));
break;
default:
deviceIsUpPromises.push(getIsUpByDeviceInfo(device));
}
};
Promise.all(deviceIsUpPromises).then(function(val) {
handleIsUpReport(val);
});
// Determine if a device is up by asking the Particle cloud for the device's status.
function getIsUpByDeviceInfo(device) {
var url = 'https://api.particle.io/v1/devices/' + device.deviceID + '?access_token=' + hook.env.PARTICLE_API_KEY;
var p = new Promise(function(resolve, reject) {
getDeviceName(device).then(function (device) {
var options = {uri: url, timeout: device.timeout || DEFAULT_TIMEOUT};
rp(options)
.then(function (htmlString) {
device.online = JSON.parse(htmlString).connected ? 'yes' : 'no';
device.error = 'not connected to Particle cloud';
resolve(device);
})
.catch(function (err) {
resolve(handleErrorTypes(device, err));
});
});
});
return p;
}
// Determine if a device is up by asking the Particle cloud for a variable value. If the request is successful the device is considered 'online'. Returns a promise which will eventually resolve and return a device object. If the device property 'expectedValue' is specified then the variable's value will be compared against it. If it is not equal the device will still be considered 'online' but will have an error proprty indicating the mitmatch.
function getIsUpByVariable(device) {
var url = 'https://api.particle.io/v1/devices/' + device.deviceID + '/' + device.variableName + '?access_token=' + hook.env.PARTICLE_API_KEY;
var p = new Promise(function(resolve, reject) {
getDeviceName(device).then(function (device) {
var options = {uri: url, timeout: device.timeout || DEFAULT_TIMEOUT};
rp(options)
.then(function (htmlString) {
// Process html...
//console.log(htmlString);
var data = JSON.parse(htmlString);
if(device.expectedValue) {
if(data.result === device.expectedValue) {
device.online = 'yes';
} else {
device.online = 'yes';
device.error = 'mismatch: expected variable value (' + device.expectedValue + ') did not match retrieved value (' + data.result + ')';
}
} else {
device.online = 'yes';
}
resolve(device);
})
.catch(function (err) {
resolve(handleErrorTypes(device, err));
});
});
});
return p;
}
// Handle known error types. Takes a device and an error, parses the error, and then updates the device's online and error properties accordingly. Returns the device object.
function handleErrorTypes(device, err)
{
switch(err.name) {
case 'RequestError':
if(err.message === 'Error: ETIMEDOUT') {
device.online = 'no';
device.error = 'timeout';
} else {
device.online = 'unknown';
device.error = err.message;
}
break;
case 'StatusCodeError':
switch(err.statusCode) {
case 401:
device.online = 'unknwon';
device.error = 'bad access token';
break;
case 404:
device.online = 'yes';
device.error = JSON.parse(err.error).error;
break;
default:
console.log(err);
device.online = 'unknown';
device.error = err.message;
}
break;
default:
console.log(err);
device.online = 'unknown';
device.error = err.message;
}
return device;
}
// Grab a device's name form the Particle cloud. Return a promise which will eventually resolve returning a device object with a name property.
function getDeviceName(device) {
var url = 'https://api.particle.io/v1/devices/' + device.deviceID + '?access_token=' + hook.env.PARTICLE_API_KEY;
var p = new Promise(function(resolve, reject) {
var options = {uri: url, timeout: DEFAULT_TIMEOUT};
rp(options)
.then(function (htmlString) {
device.name = JSON.parse(htmlString).name;
resolve(device);
})
.catch(function (err) {
device.name = 'unknown';
resolve(device);
});
})
return p;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment