Merge pull request #253 from hybridgroup/feature/cppp-io-updates
Add event listings to API
This commit is contained in:
commit
fe4c899f7f
|
@ -35,7 +35,7 @@ var Adaptor = module.exports = function Adaptor(opts) {
|
||||||
this.details = {};
|
this.details = {};
|
||||||
|
|
||||||
_.forEach(opts, function(opt, name) {
|
_.forEach(opts, function(opt, name) {
|
||||||
if (_.include(["robot", "name", "adaptor"], name)) {
|
if (_.include(["robot", "name", "adaptor", "events"], name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,12 @@ var Cylon = require("../cylon");
|
||||||
|
|
||||||
var router = module.exports = require("express").Router();
|
var router = module.exports = require("express").Router();
|
||||||
|
|
||||||
|
var eventHeaders = {
|
||||||
|
"Content-Type": "text/event-stream",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Cache-Control": "no-cache"
|
||||||
|
};
|
||||||
|
|
||||||
// Loads up the appropriate Robot/Device/Connection instances, if they are
|
// Loads up the appropriate Robot/Device/Connection instances, if they are
|
||||||
// present in the route params.
|
// present in the route params.
|
||||||
var load = function load(req, res, next) {
|
var load = function load(req, res, next) {
|
||||||
|
@ -55,6 +61,26 @@ router.get("/", function(req, res) {
|
||||||
res.json({ MCP: Cylon.toJSON() });
|
res.json({ MCP: Cylon.toJSON() });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/events", function(req, res) {
|
||||||
|
res.json({ events: Cylon.events });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/events/:event", function(req, res) {
|
||||||
|
var event = req.params.event;
|
||||||
|
|
||||||
|
res.writeHead(200, eventHeaders);
|
||||||
|
|
||||||
|
var writeData = function(data) {
|
||||||
|
res.write("data: " + JSON.stringify(data) + "\n\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
Cylon.on(event, writeData);
|
||||||
|
|
||||||
|
res.on("close", function() {
|
||||||
|
Cylon.removeListener(event, writeData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/commands", function(req, res) {
|
router.get("/commands", function(req, res) {
|
||||||
res.json({ commands: Object.keys(Cylon.commands) });
|
res.json({ commands: Object.keys(Cylon.commands) });
|
||||||
});
|
});
|
||||||
|
@ -81,6 +107,26 @@ router.all("/robots/:robot/commands/:command", load, function(req, res) {
|
||||||
router.runCommand(req, res, req.robot, command);
|
router.runCommand(req, res, req.robot, command);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/robots/:robot/events", load, function(req, res) {
|
||||||
|
res.json({ events: req.robot.events });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.all("/robots/:robot/events/:event", load, function(req, res) {
|
||||||
|
var event = req.params.event;
|
||||||
|
|
||||||
|
res.writeHead(200, eventHeaders);
|
||||||
|
|
||||||
|
var writeData = function(data) {
|
||||||
|
res.write("data: " + JSON.stringify(data) + "\n\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
req.robot.on(event, writeData);
|
||||||
|
|
||||||
|
res.on("close", function() {
|
||||||
|
req.robot.removeListener(event, writeData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/robots/:robot/devices", load, function(req, res) {
|
router.get("/robots/:robot/devices", load, function(req, res) {
|
||||||
res.json({ devices: req.robot.toJSON().devices });
|
res.json({ devices: req.robot.toJSON().devices });
|
||||||
});
|
});
|
||||||
|
@ -89,14 +135,14 @@ router.get("/robots/:robot/devices/:device", load, function(req, res) {
|
||||||
res.json({ device: req.device });
|
res.json({ device: req.device });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/robots/:robot/devices/:device/events", load, function(req, res) {
|
||||||
|
res.json({ events: req.device.events });
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/robots/:robot/devices/:device/events/:event", load, function(req, res) {
|
router.get("/robots/:robot/devices/:device/events/:event", load, function(req, res) {
|
||||||
var event = req.params.event;
|
var event = req.params.event;
|
||||||
|
|
||||||
res.writeHead(200, {
|
res.writeHead(200, eventHeaders);
|
||||||
"Content-Type": "text/event-stream",
|
|
||||||
"Connection": "keep-alive",
|
|
||||||
"Cache-Control": "no-cache"
|
|
||||||
});
|
|
||||||
|
|
||||||
var writeData = function(data) {
|
var writeData = function(data) {
|
||||||
res.write("data: " + JSON.stringify(data) + "\n\n");
|
res.write("data: " + JSON.stringify(data) + "\n\n");
|
||||||
|
|
33
lib/cylon.js
33
lib/cylon.js
|
@ -16,23 +16,27 @@ var Logger = require("./logger"),
|
||||||
Utils = require("./utils"),
|
Utils = require("./utils"),
|
||||||
_ = require("./lodash");
|
_ = require("./lodash");
|
||||||
|
|
||||||
var Cylon = module.exports = {
|
var EventEmitter = require("events").EventEmitter;
|
||||||
Logger: Logger,
|
|
||||||
Driver: require("./driver"),
|
|
||||||
Adaptor: require("./adaptor"),
|
|
||||||
Utils: Utils,
|
|
||||||
|
|
||||||
IO: {
|
var Cylon = module.exports = new EventEmitter();
|
||||||
DigitalPin: require("./io/digital-pin"),
|
|
||||||
Utils: require("./io/utils")
|
|
||||||
},
|
|
||||||
|
|
||||||
api_instance: null,
|
Cylon.Logger = Logger;
|
||||||
|
Cylon.Driver = require("./driver");
|
||||||
|
Cylon.Adaptor = require("./adaptor");
|
||||||
|
Cylon.Utils = Utils;
|
||||||
|
|
||||||
robots: {},
|
Cylon.IO = {
|
||||||
commands: {}
|
DigitalPin: require("./io/digital-pin"),
|
||||||
|
Utils: require("./io/utils")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Cylon.api_instance = null;
|
||||||
|
|
||||||
|
Cylon.robots = {};
|
||||||
|
Cylon.commands = {};
|
||||||
|
|
||||||
|
Cylon.events = [ "robot_added", "robot_removed" ];
|
||||||
|
|
||||||
// Public: Creates a new Robot
|
// Public: Creates a new Robot
|
||||||
//
|
//
|
||||||
// opts - hash of Robot attributes
|
// opts - hash of Robot attributes
|
||||||
|
@ -61,6 +65,8 @@ Cylon.robot = function robot(opts) {
|
||||||
|
|
||||||
var bot = new Robot(opts);
|
var bot = new Robot(opts);
|
||||||
this.robots[bot.name] = bot;
|
this.robots[bot.name] = bot;
|
||||||
|
this.emit("robot_added", bot.name);
|
||||||
|
|
||||||
return bot;
|
return bot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -134,7 +140,8 @@ Cylon.halt = function halt(callback) {
|
||||||
Cylon.toJSON = function() {
|
Cylon.toJSON = function() {
|
||||||
return {
|
return {
|
||||||
robots: _.invoke(this.robots, "toJSON"),
|
robots: _.invoke(this.robots, "toJSON"),
|
||||||
commands: _.keys(this.commands)
|
commands: _.keys(this.commands),
|
||||||
|
events: this.events
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ var Driver = module.exports = function Driver(opts) {
|
||||||
this.connection = opts.connection;
|
this.connection = opts.connection;
|
||||||
|
|
||||||
this.commands = {};
|
this.commands = {};
|
||||||
|
this.events = [];
|
||||||
|
|
||||||
// some default options
|
// some default options
|
||||||
this.pin = opts.pin;
|
this.pin = opts.pin;
|
||||||
|
@ -36,7 +37,7 @@ var Driver = module.exports = function Driver(opts) {
|
||||||
this.details = {};
|
this.details = {};
|
||||||
|
|
||||||
_.forEach(opts, function(opt, name) {
|
_.forEach(opts, function(opt, name) {
|
||||||
if (_.include(["robot", "name", "connection", "driver"], name)) {
|
if (_.include(["robot", "name", "connection", "driver", "events"], name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ Driver.prototype.toJSON = function() {
|
||||||
driver: this.constructor.name || this.name,
|
driver: this.constructor.name || this.name,
|
||||||
connection: this.connection.name,
|
connection: this.connection.name,
|
||||||
commands: _.keys(this.commands),
|
commands: _.keys(this.commands),
|
||||||
|
events: this.events,
|
||||||
details: this.details
|
details: this.details
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,8 @@ Robot.prototype.toJSON = function() {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
connections: _.invoke(this.connections, "toJSON"),
|
connections: _.invoke(this.connections, "toJSON"),
|
||||||
devices: _.invoke(this.devices, "toJSON"),
|
devices: _.invoke(this.devices, "toJSON"),
|
||||||
commands: _.keys(this.commands)
|
commands: _.keys(this.commands),
|
||||||
|
events: _.isArray(this.events) ? this.events : []
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ var Ping = module.exports = function Ping() {
|
||||||
this.commands = {
|
this.commands = {
|
||||||
ping: this.ping
|
ping: this.ping
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.events = ["ping"];
|
||||||
};
|
};
|
||||||
|
|
||||||
Utils.subclass(Ping, Driver);
|
Utils.subclass(Ping, Driver);
|
||||||
|
|
|
@ -181,5 +181,9 @@ describe("Cylon", function() {
|
||||||
it("contains an array of MCP commands", function() {
|
it("contains an array of MCP commands", function() {
|
||||||
expect(json.commands).to.be.eql(["echo"]);
|
expect(json.commands).to.be.eql(["echo"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("contains an array of MCP events", function() {
|
||||||
|
expect(json.events).to.be.eql(["robot_added", "robot_removed"]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,6 +30,10 @@ describe("Driver", function() {
|
||||||
expect(driver.commands).to.be.eql({});
|
expect(driver.commands).to.be.eql({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("sets @events to an empty array by default", function() {
|
||||||
|
expect(driver.events).to.be.eql([]);
|
||||||
|
});
|
||||||
|
|
||||||
it("sets @interval to 10ms by default, or the provided value", function() {
|
it("sets @interval to 10ms by default, or the provided value", function() {
|
||||||
expect(driver.interval).to.be.eql(10);
|
expect(driver.interval).to.be.eql(10);
|
||||||
|
|
||||||
|
@ -43,6 +47,46 @@ describe("Driver", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#toJSON", function() {
|
||||||
|
var driver, json;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
driver = new Driver({
|
||||||
|
connection: { name: "conn" },
|
||||||
|
name: "name",
|
||||||
|
port: "3000"
|
||||||
|
});
|
||||||
|
|
||||||
|
json = driver.toJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns an object", function() {
|
||||||
|
expect(json).to.be.a("object");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("contains the driver's name", function() {
|
||||||
|
expect(json.name).to.eql("name");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("contains the driver's constructor name", function() {
|
||||||
|
expect(json.driver).to.eql("Driver");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("contains the driver's connection name", function() {
|
||||||
|
expect(json.connection).to.eql("conn");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("contains the driver's commands", function() {
|
||||||
|
expect(json.commands).to.eql(Object.keys(driver.commands));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("contains the driver's events, or an empty array", function() {
|
||||||
|
expect(json.events).to.eql([]);
|
||||||
|
driver.events = ["hello", "world"];
|
||||||
|
expect(driver.toJSON().events).to.be.eql(["hello", "world"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("#setupCommands", function() {
|
describe("#setupCommands", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
driver.proxyMethods = spy();
|
driver.proxyMethods = spy();
|
||||||
|
|
|
@ -215,7 +215,9 @@ describe("Robot", function() {
|
||||||
|
|
||||||
devices: {
|
devices: {
|
||||||
ping: { driver: "ping" }
|
ping: { driver: "ping" }
|
||||||
}
|
},
|
||||||
|
|
||||||
|
events: ["hello", "world"]
|
||||||
});
|
});
|
||||||
|
|
||||||
var json = bot.toJSON();
|
var json = bot.toJSON();
|
||||||
|
@ -239,6 +241,13 @@ describe("Robot", function() {
|
||||||
it("contains the robot's connections", function() {
|
it("contains the robot's connections", function() {
|
||||||
expect(json.connections).to.eql([bot.connections.loopback.toJSON()]);
|
expect(json.connections).to.eql([bot.connections.loopback.toJSON()]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("contains the robot's events, or an empty array", function() {
|
||||||
|
expect(json.events).to.eql(["hello", "world"]);
|
||||||
|
|
||||||
|
var bot = new Robot();
|
||||||
|
expect(bot.toJSON().events).to.be.eql([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#connection", function() {
|
describe("#connection", function() {
|
||||||
|
|
Loading…
Reference in New Issue