Skip to content

Instantly share code, notes, and snippets.

@ElectricImpSampleCode
Last active September 18, 2017 17:19
Show Gist options
  • Save ElectricImpSampleCode/1d958fef70e11b6dd1eeb6193c03210b to your computer and use it in GitHub Desktop.
Save ElectricImpSampleCode/1d958fef70e11b6dd1eeb6193c03210b to your computer and use it in GitHub Desktop.
impCentral API Example Code: Working with Access Tokens
// CONSTANTS
// Replace the 'USERNAME' and 'PASSWORD' values with your own
const USERNAME = '...'
const PASSWORD = '...'
const API_URL = 'api.electricimp.com'
const API_VER = '/v5/'
const FILE_NAME = '.impCentralData'
// GLOBALS
var https = require('https');
var fs = require('fs');
var products = [];
var accessToken = null;
var expiryDate = null;
var refreshToken = null;
// FUNCTIONS
function setLoginOptions() {
// Returns an HTTPS request options object primed to get your access token
return {
hostname: API_URL,
path: API_VER + 'auth',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
}
function setTokenUpdateOptions(token) {
// Returns an HTTPS request options object primed to refresh your access token
return {
hostname: API_URL,
path: API_VER + 'auth/token',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
}
function setOptions(verb, path, token) {
// Returns an HTTPS request options object primed for API usage
return {
hostname: API_URL,
path: API_VER + path,
method: verb,
headers: {
'Content-Type': 'application/vnd.api+json',
'Authorization': 'Bearer ' + token
}
};
}
function showError(resp) {
console.log(`STATUS: ${resp.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(resp.headers)}`);
}
function login(cb = null) {
// Login to the server - ie. get the initial access token
let req = https.request(setLoginOptions(), (resp) => {
// Construct the returned response body
let body = '';
resp.setEncoding('utf8');
resp.on('data', (chunk) => { body += chunk; });
// Code that's called when the body is retrieved
resp.on('end', () => {
if (body.length > 0) {
try {
// Is the returned data valid JSON?
const data = JSON.parse(body);
if (resp.statusCode === 200) {
// We have the new access token and other credentials
accessToken = data.access_token;
expiryDate = data.expires_at;
refreshToken = data.refresh_token;
// Save the credentials locally
writeData();
// Call the passed in function
if (cb) checkAccessToken(cb);
} else {
// API Error
console.log('API ERROR: ' + data.code + ' (' + data.message + ')');
}
} catch (err) {
// JSON error
console.error(err.message);
}
} else {
// HTTP Error
showError(resp);
}
});
});
// Error callback
req.on('error', (err) => { console.error(`REQUEST ERROR: ${err.message}`); });
// Begin by setting credentials as request body
req.write(JSON.stringify({
'id': USERNAME,
'password': PASSWORD
}));
// Send the request
req.end();
}
function checkAccessToken(cb = null) {
if (accessToken === null) {
// Don't have the token, so load it
console.log('We don\'t have an access token - trying local file');
fs.readFile(FILE_NAME, {'encoding': 'utf8', 'flag': 'a+'}, (err, data) => {
if (err) return console.error(err);
if (data !== null && data.length > 0) {
try {
let fdata = JSON.parse(data);
if ('at' in fdata) {
accessToken = fdata.at;
refreshToken = fdata.rt;
expiryDate = fdata.ed;
console.log('Read in access token');
checkAccessToken(cb);
} else {
console.log('No locally stored access token - getting a new one');
login(cb);
}
} catch (e) {
console.error(e);
}
} else {
console.log('No locally stored access token - getting a new one');
login(cb);
}
});
} else {
console.log('We have an access token - checking it');
let expiry = new Date(expiryDate);
let now = new Date();
if (expiry < now) {
// Access token expired
console.log('Access Token Expired - updating...');
let req = https.request(setTokenUpdateOptions(), (resp) => {
// Construct the returned response body
let body = '';
resp.setEncoding('utf8');
resp.on('data', (chunk) => { body += chunk; });
// Code that's called when the body is retrieved
resp.on('end', () => {
if (body.length > 0) {
try {
// Is the returned data valid JSON?
const data = JSON.parse(body);
if (resp.statusCode < 400) {
// Success - retain the new token and expiry info
accessToken = data.access_token;
expiryDate = data.expires_at;
// Store the data locally
writeData();
// Call the passed in function
if (cb) cb();
} else {
// API Error
console.error('API ERROR: ' + data.code + ' (' + data.message + ')');
}
} catch (err) {
// JSON error
console.error(err.message);
}
} else {
// HTTP Error
showError(resp);
}
});
});
// Error callback
req.on('error', (err) => { console.error(`REQUEST ERROR: ${err.message}`); });
req.write(JSON.stringify({
'token': refreshToken
}));
// Send the request
req.end();
} else {
// Access token is good - use it
console.log("Access Token OK - ready to access impCentral");
if (cb) cb();
}
}
}
function writeData() {
// Write the access token data
let data = {};
data.at = accessToken;
data.rt = refreshToken;
data.ed = expiryDate;
fs.writeFile(FILE_NAME, JSON.stringify(data), (err) => {
if (err) return console.error(err);
console.log("Access Token acquired, written to local storage");
});
}
// RUNTIME
checkAccessToken(() => {
// Create a request to get the account's products
let req = https.request(setOptions('GET', 'products', accessToken), (resp) => {
let body = '';
resp.setEncoding('utf8');
resp.on('data', (chunk) => { body += chunk; });
resp.on('end', () => {
if (body.length > 0) {
try {
let data = JSON.parse(body);
data = data.data;
if (resp.statusCode === 200) {
// 'data' is an array of product objects
for (let item of data) {
let product = {};
product.id = item.id;
product.name = item.attributes.name;
product.devicegroups = [];
products.push(product);
}
console.log(`You have ${products.length} product(s) in your account:`);
let tabs = 0;
for (let product of products) {
if (product.name.length > tabs) {
tabs = product.name.length;
}
}
let pcount = 0;
for (let product of products) {
let sp = " ".substring(0, tabs - product.name.length + 1);
console.log(` ${pcount + 1}. ${product.name}${sp}(ID: ${product.id})`);
pcount += 1;
}
} else {
// API Error
console.log('API ERROR: ' + data.code + ' (' + data.message + ')');
}
} catch (err) {
// JSON Error
console.error(err.message);
}
} else {
// HTTP Error
showError(resp);
}
});
});
// Error callback
req.on('error', (err) => { console.error(`REQUEST ERROR: ${err.message}`); });
// Send the request
req.end();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment