aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml3
-rw-r--r--Gruntfile.js20
-rw-r--r--active911.js106
-rw-r--r--examples/sample_app.js14
-rw-r--r--lib/Agency.js45
-rw-r--r--lib/Device.js12
-rw-r--r--lib/active911.js63
-rw-r--r--lib/util.js3
-rw-r--r--package.json19
-rw-r--r--tests/active911.js105
-rw-r--r--tests/replies/agency.json24
-rw-r--r--tests/replies/device.json19
-rw-r--r--tests/replies/devices.json0
-rw-r--r--tests/replies/error.json4
15 files changed, 331 insertions, 108 deletions
diff --git a/.gitignore b/.gitignore
index eb5deef..5db9d70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
npm-debug.log
+node_modules
+.DS_Store
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..982fee7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "0.10"
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..34f8dc8
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,20 @@
+module.exports = function (grunt) {
+
+ grunt.initConfig({
+ jshint: {
+ all: ['lib/*.js', 'examples/*.js']
+ },
+ mochaTest: {
+ test: {
+ options: {
+ reporter: 'spec'
+ },
+ src: ['tests/*.js']
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-mocha-test');
+ grunt.registerTask('default', ['jshint', 'mochaTest']);
+};
diff --git a/active911.js b/active911.js
deleted file mode 100644
index df2e2c6..0000000
--- a/active911.js
+++ /dev/null
@@ -1,106 +0,0 @@
-var http = require('https');
-var querystring = require('querystring');
-
-module.exports = function (app_key, api_key) {
-
- // this is used to run all server commands
- var server_command = function (data, callback) {
-
- // add keys to the POST request
- data.app_key = app_key;
- data.api_key = api_key;
-
- // convert the object to a querystring for POSTing
- var post = querystring.stringify(data);
-
- // HTTP request configuration
- var options = {
- host: 'access.active911.com',
- port: '443',
- path: '/interface/open_api.php',
- method: 'POST',
- headers: {
- 'Content-Length': post.length
- }
- };
-
- // set up the request
- var request = http.request(options, function (res) {
-
- res.setEncoding('utf8');
-
- var json = '';
- res.on('data', function (chunk) {
- json += chunk;
- });
-
- res.on('end', function () {
-
- var response = JSON.parse(json);
-
- if (response.result === 'error') {
- callback(response.message);
- } else {
- return callback(false, response.message);
- }
- });
-
- res.on('error', function (err) {
- callback(err);
- });
- });
-
- request.write(post);
- request.end();
-
- };
-
- return {
-
- ping: function (callback) {
- var options = {
- 'operation': 'ping'
- };
-
- server_command(options, callback);
- },
-
- getDevice: function (device_id, callback) {
- var options = {
- 'operation': 'get_device',
- 'device_id': device_id
- };
-
- server_command(options, callback);
- },
-
- getAlert: function (alert_id, callback) {
- var options = {
- 'operation': 'get_alert',
- 'alert_id': alert_id
- };
-
- server_command(options, callback);
- },
-
- getLocations: function (north, south, east, west, callback) {
- var options = {
- 'operation': 'get_locations',
- 'north': north,
- 'south': south,
- 'east': east,
- 'west': west
- };
-
- // use an intermediate callback to extract the location array
- server_command(options, function (err, response) {
- if (err) {
- return callback(err);
- } else {
- return callback(err, response.locations);
- }
- });
- }
-
- };
-};
diff --git a/examples/sample_app.js b/examples/sample_app.js
new file mode 100644
index 0000000..a08b039
--- /dev/null
+++ b/examples/sample_app.js
@@ -0,0 +1,14 @@
+var Active911 = require('../lib/active911').Active911;
+
+var oauth_id = '12345';
+var oauth_secret = 'asdf';
+var oauth_scope = 'read_agency read_alert read_device';
+
+var api = new Active911(oauth_id, oauth_secret, oauth_scope);
+var uri = api.getAuthorizationUri();
+console.log('Please go to ' + uri + ' to authenticate.');
+
+api.ready(function() {
+ console.log('OAuth workflow complete');
+
+});
diff --git a/lib/Agency.js b/lib/Agency.js
new file mode 100644
index 0000000..c22a141
--- /dev/null
+++ b/lib/Agency.js
@@ -0,0 +1,45 @@
+var _util = require('./util');
+
+module.exports.Agency = function(options) {
+ this._id = options.id;
+ this._name = options.name;
+ this._address = options.address;
+ this._city = options.city;
+ this._state = options.state;
+ this._latitude = options.latitude;
+ this._longitude = options.longitude;
+ this._devices = options.devices;
+ this._uri = options.uri || _util.API_BASE + '/agency/' + options.id;
+};
+
+module.exports.Agency.prototype.getId = function() {
+ return this._id;
+};
+
+module.exports.Agency.prototype.getName = function() {
+ return this._name;
+};
+
+module.exports.Agency.prototype.getAddress = function() {
+ return this._address;
+};
+
+module.exports.Agency.prototype.getCity = function() {
+ return this._city;
+};
+
+module.exports.Agency.prototype.getState = function() {
+ return this._state;
+};
+
+module.exports.Agency.prototype.getLatitude = function() {
+ return this._latitude;
+};
+
+module.exports.Agency.prototype.getLongitude = function() {
+ return this._longitude;
+};
+
+module.exports.Agency.prototype.getDevices = function() {
+ return this._devices;
+};
diff --git a/lib/Device.js b/lib/Device.js
new file mode 100644
index 0000000..bfc4d34
--- /dev/null
+++ b/lib/Device.js
@@ -0,0 +1,12 @@
+var _util = require('./util');
+
+module.exports.Device = function(options) {
+ this._id = options.id;
+ this._name = options.name;
+ this._latitude = options.latitude;
+ this._longitude = options.longitude;
+ this._position_accuracy = options.position_accuracy;
+ this._position_timestamp = options.position_timestamp;
+ this._agencies = options.agencies;
+ this._uri = options.uri || _util.API_BASE + '/devices/' + options.id;
+};
diff --git a/lib/active911.js b/lib/active911.js
new file mode 100644
index 0000000..e75eaca
--- /dev/null
+++ b/lib/active911.js
@@ -0,0 +1,63 @@
+var OAuth2 = require('oauth').OAuth2;
+var http = require('http');
+var events = require('events');
+var querystring = require('querystring');
+var url = require('url');
+var Agency = require('./Agency.js').Agency;
+var Device = require('./Device.js').Device;
+var _util = require('./util');
+
+module.exports.Agency = Agency;
+module.exports.Device = Device;
+
+// Constructor
+module.exports.Active911 = function(client_id, client_secret, scope) {
+ this._client_id = client_id;
+ this._client_secret = client_secret;
+ this._scope = scope;
+ this._oauth_complete = false;
+ this._emitter = new events.EventEmitter();
+
+ // Create the HTTP server that will receive the OAuth code after the user
+ // has authenticated to Active911.
+ this._http_server = new http.Server();
+
+ // The request handler
+ this._http_server.on('request', function(req, res) {
+
+ // The only thing we care about is the /?code=xxx
+ var qs = url.parse(req.url).query;
+
+ // If a code has been sent, and we don't already have one, we are good
+ // to go.
+ if (qs.split('=')[0] === 'code' && !this._oauth_complete) {
+ this._oauth_code = qs.split('=')[1];
+ this._oauth_complete = true;
+ emitter.emit('oauth_complete');
+ }
+
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.end();
+ });
+
+ // Once the server is listening, store its port number for use in auth uri
+ this._http_server.listen(0, function() {
+
+ });
+};
+
+module.exports.Active911.prototype.getAuthorizationUri = function() {
+
+ var qs = querystring.stringify({
+ client_id: this._client_id,
+ response_type: 'code',
+ redirection_uri: 'http://localhost:' + this._oauth_server_port,
+ scope: this._scope
+ });
+
+ return _util.API_BASE_NAME + '/open_api/authorize_agency.php' + qs;
+};
+
+module.exports.Active911.prototype.ready = function(func) {
+ emitter.on('oauth_complete', func);
+};
diff --git a/lib/util.js b/lib/util.js
new file mode 100644
index 0000000..08efbfb
--- /dev/null
+++ b/lib/util.js
@@ -0,0 +1,3 @@
+module.exports.API_BASE_NAME = 'https://access.active911.com';
+module.exports.API_BASE_PATH = '/interface/open_api/api';
+module.exports.API_BASE = exports.API_BASE_NAME + exports.API_BASE_PATH;
diff --git a/package.json b/package.json
index 5388a38..2bf3062 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,23 @@
"version": "0.1.1",
"author": "Ben Burwell <hi@benburwell.com>",
"description": "A simple interface to Active911",
- "tags": [ "active911", "cad" ],
- "main": "./active911.js",
+ "tags": [ "active911", "cad", "fire", "ems", "dispatching" ],
+ "main": "./lib/active911.js",
+ "dependencies": {
+ "oauth": ">=0.9.11"
+ },
+ "devDependencies": {
+ "mocha": "latest",
+ "nock": "latest",
+ "should": "latest",
+ "grunt-mocha-test": "latest",
+ "grunt": "latest",
+ "grunt-cli": "latest",
+ "grunt-contrib-jshint": "latest"
+ },
+ "scripts": {
+ "test": "grunt --verbose"
+ },
"repository": {
"type": "git",
"url": "https://github.com/benburwell/active911.git"
diff --git a/tests/active911.js b/tests/active911.js
new file mode 100644
index 0000000..309aafb
--- /dev/null
+++ b/tests/active911.js
@@ -0,0 +1,105 @@
+require('should');
+require('nock');
+Active911 = require('../lib/active911.js');
+
+var a911;
+
+var testDevicesResponse = require('replies/devices.json');
+var testAgencyResponse = require('replies/agency.json');
+var testDeviceResponse = require('replies/device.json');
+var testErrorResponse = require('replies/error.json');
+
+describe('Active911 API', function() {
+
+ beforeEach(function(done) {
+ a911 = new Active911();
+ });
+
+ describe('#getAgency', function() {
+
+ it('Should return correct agency data', function() {
+
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/')
+ .replyWithFile(200, __dirname + 'replies/agency.json'});
+
+ a911.getAgency(function(err, agency) {
+ should.not.exist(err);
+ agency.should.equal(testAgencyResponse.message.agency);
+ });
+ });
+
+ it('Should give an error if the API gives an error', function() {
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/')
+ .replyWithFile(400, __dirname + 'replies/error.json');
+
+ a911.getAgency(function(err, agency) {
+ err.should.equal(testErrorResponse.message);
+ should.not.exist(agency);
+ });
+ });
+
+ });
+
+ describe('#getDevices', function() {
+ it('Should return correct device data', function() {
+
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/')
+ .replyWithFile(400, __dirname + 'replies/agency.json');
+
+ a911.getDevices(function(err, devices) {
+ should.not.exist(err);
+ devices.should.equal(testDevicesResponse.message.devices);
+ });
+ });
+
+ it('Should give an error if the API gives an error', function() {
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/')
+ .replyWithFile(400, __dirname + 'replies/error.json');
+
+ a911.getDevices(function(err, devices) {
+ err.should.equal(testErrorResponse.message);
+ should.not.exist(devices);
+ });
+ });
+ });
+
+ describe('#getDevice', function() {
+ it('Should return correct device data (String id)', function() {
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/devices/1')
+ .replyWithFile(200, __dirname + 'replies/device.json');
+
+ a911.getDevice('1', function(err, device) {
+ should.not.exist(err);
+ device.should.equal(testDeviceResponse.message.device);
+ });
+ });
+
+ it('Should return correct device data (Number id)', function() {
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/devices/1')
+ .replyWithFile(200, __dirname + 'replies/device.json');
+
+ a911.getDevice(1, function(err, device) {
+ should.not.exist(err);
+ device.should.equal(testDeviceResponse.message.device);
+ });
+ });
+
+ it('Should give an error if the API gives an error', function() {
+ nock('https://access.active911.com')
+ .get('/interface/open_api/api/devices/1')
+ .replyWithFile(400, __dirname + 'replies/error.json');
+
+ a911.getDevice(1, function(err, device) {
+ err.should.equal(testErrorResponse.message);
+ should.not.exist(device);
+ });
+ });
+ });
+
+});
diff --git a/tests/replies/agency.json b/tests/replies/agency.json
new file mode 100644
index 0000000..6c1b365
--- /dev/null
+++ b/tests/replies/agency.json
@@ -0,0 +1,24 @@
+{
+ "result": "success",
+ "message": {
+ "agency": {
+ "id": "12345",
+ "name": "Test Agency",
+ "address": "123 Main St.",
+ "city": "City",
+ "state": "AZ",
+ "latitude": 40,
+ "longitude": 70,
+ "devices": [
+ {
+ "id": 1,
+ "uri": "https://access.active911.com/interface/open_api/api/devices/1"
+ },
+ {
+ "id": 2,
+ "uri": "https://access.active911.com/interface/open_api/api/devices/2"
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/replies/device.json b/tests/replies/device.json
new file mode 100644
index 0000000..b3dc1ee
--- /dev/null
+++ b/tests/replies/device.json
@@ -0,0 +1,19 @@
+{
+ "result": "success",
+ "message": {
+ "device": {
+ "id": 1,
+ "name": "Test Device",
+ "latitude": 41,
+ "longitude": 71,
+ "position_accuracy": "100",
+ "position_timestamp": "2014-01-01 00:00:00",
+ "agencies": [
+ {
+ "id": "12345",
+ "uri": "https://access.active911.com/interface/open_api/api/"
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/replies/devices.json b/tests/replies/devices.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/replies/devices.json
diff --git a/tests/replies/error.json b/tests/replies/error.json
new file mode 100644
index 0000000..c9ccbef
--- /dev/null
+++ b/tests/replies/error.json
@@ -0,0 +1,4 @@
+{
+ "result": "error",
+ "message": "Test Error Message"
+}