Merge branch 'master' into literate

* master:
  Update to version 0.6.0
  Execute robot commands from api
  Replace api.litcoffee with api.coffee
  Replace api.litcoffee with api.coffee
  Docs corrections
  Refactoring adaptor and driver initialization to simplify, and fix init overwrite error

Conflicts:
	src/api.coffee
This commit is contained in:
Andrew Stewart 2013-11-26 10:07:15 -08:00
commit dbfa4f859e
14 changed files with 152 additions and 115 deletions

View File

@ -108,6 +108,8 @@ In lieu of a formal styleguide, take care to maintain the existing coding style.
[![NPM](https://nodei.co/npm/cylon.png?compact=true)](https://nodei.co/npm/cylon/)
Version 0.6.0 - API exposes robot commands, fixes issues in driver/adaptor init
Version 0.5.0 - Improve API, add GPIO support for reuse in adaptors
Version 0.4.0 - Refactor proxy in Cylon.Basestar, improve API

26
dist/api.js vendored
View File

@ -61,6 +61,32 @@
return res.json(err ? err : robot.data());
});
});
this.server.get("/robots/:robotname/commands", function(req, res) {
return master.findRobot(req.params.robotname, function(err, robot) {
return res.json(err ? err : robot.data().commands);
});
});
this.server.all("/robots/:robotname/commands/:commandname", function(req, res) {
var key, params, value, _ref;
params = [];
if (typeof req.body === 'object') {
_ref = req.body;
for (key in _ref) {
value = _ref[key];
params.push(value);
}
}
return master.findRobot(req.params.robotname, function(err, robot) {
var result;
if (err) {
return res.json(err);
}
result = robot[req.params.commandname].apply(robot, params);
return res.json({
result: result
});
});
});
this.server.get("/robots/:robotname/devices", function(req, res) {
return master.findRobot(req.params.robotname, function(err, robot) {
return res.json(err ? err : robot.data().devices);

6
dist/connection.js vendored
View File

@ -38,7 +38,7 @@
this.robot = opts.robot;
this.name = opts.name;
this.connection_id = opts.id;
this.adaptor = this.requireAdaptor(opts);
this.adaptor = this.initAdaptor(opts);
this.port = new Cylon.Port(opts.port);
proxyFunctionsToObject(this.adaptor.commands(), this.adaptor, this.self);
}
@ -72,9 +72,9 @@
return this.adaptor.disconnect();
};
Connection.prototype.requireAdaptor = function(opts) {
Connection.prototype.initAdaptor = function(opts) {
Logger.debug("Loading adaptor '" + opts.adaptor + "'");
return this.robot.requireAdaptor(opts.adaptor, this.self, opts);
return this.robot.initAdaptor(opts.adaptor, this.self, opts);
};
return Connection;

6
dist/device.js vendored
View File

@ -35,7 +35,7 @@
this.name = opts.name;
this.pin = opts.pin;
this.connection = this.determineConnection(opts.connection) || this.defaultConnection();
this.driver = this.requireDriver(opts);
this.driver = this.initDriver(opts);
proxyFunctionsToObject(this.driver.commands(), this.driver, this.self);
}
@ -81,12 +81,12 @@
return first;
};
Device.prototype.requireDriver = function(opts) {
Device.prototype.initDriver = function(opts) {
if (opts == null) {
opts = {};
}
Logger.debug("Loading driver '" + opts.driver + "'");
return this.robot.requireDriver(opts.driver, this.self, opts);
return this.robot.initDriver(opts.driver, this.self, opts);
};
return Device;

73
dist/robot.js vendored
View File

@ -39,6 +39,9 @@
opts = {};
}
this.registerDriver = __bind(this.registerDriver, this);
this.requireDriver = __bind(this.requireDriver, this);
this.registerAdaptor = __bind(this.registerAdaptor, this);
this.requireAdaptor = __bind(this.requireAdaptor, this);
this.stop = __bind(this.stop, this);
this.startDevices = __bind(this.startDevices, this);
this.startConnections = __bind(this.startConnections, this);
@ -52,6 +55,7 @@
this.devices = {};
this.adaptors = {};
this.drivers = {};
this.commands = [];
this.registerAdaptor("./loopback", "loopback");
this.registerDriver("./ping", "ping");
this.initConnections(opts.connection || opts.connections);
@ -95,7 +99,8 @@
_results.push(device.data());
}
return _results;
}).call(this)
}).call(this),
commands: this.commands
};
};
@ -182,64 +187,54 @@
return _results;
};
Robot.prototype.requireAdaptor = function(adaptorName, connection, opts) {
Robot.prototype.initAdaptor = function(adaptorName, connection, opts) {
if (opts == null) {
opts = {};
}
if (this.robot.adaptors[adaptorName] != null) {
if (typeof this.robot.adaptors[adaptorName] === 'string') {
this.robot.adaptors[adaptorName] = require(this.robot.adaptors[adaptorName]).adaptor({
name: adaptorName,
connection: connection,
extraParams: opts
});
}
} else {
require("cylon-" + adaptorName).register(this);
this.robot.adaptors[adaptorName] = require("cylon-" + adaptorName).adaptor({
name: adaptorName,
connection: connection,
extraParams: opts
});
return this.robot.requireAdaptor(adaptorName).adaptor({
name: adaptorName,
connection: connection,
extraParams: opts
});
};
Robot.prototype.requireAdaptor = function(adaptorName) {
if (this.robot.adaptors[adaptorName] == null) {
this.robot.registerAdaptor("cylon-" + adaptorName, adaptorName);
this.robot.adaptors[adaptorName].register(this);
}
return this.robot.adaptors[adaptorName];
};
Robot.prototype.registerAdaptor = function(moduleName, adaptorName) {
if (this.adaptors[adaptorName] != null) {
return;
if (this.adaptors[adaptorName] == null) {
return this.adaptors[adaptorName] = require(moduleName);
}
return this.adaptors[adaptorName] = moduleName;
};
Robot.prototype.requireDriver = function(driverName, device, opts) {
Robot.prototype.initDriver = function(driverName, device, opts) {
if (opts == null) {
opts = {};
}
if (this.robot.drivers[driverName] != null) {
if (typeof this.robot.drivers[driverName] === 'string') {
this.robot.drivers[driverName] = require(this.robot.drivers[driverName]).driver({
name: driverName,
device: device,
extraParams: opts
});
}
} else {
require("cylon-" + driverName).register(this);
this.robot.drivers[driverName] = require("cylon-" + driverName).driver({
name: driverName,
device: device,
extraParams: opts
});
return this.robot.requireDriver(driverName).driver({
name: driverName,
device: device,
extraParams: opts
});
};
Robot.prototype.requireDriver = function(driverName) {
if (this.robot.drivers[driverName] == null) {
this.robot.registerDriver("cylon-" + driverName, driverName);
this.robot.drivers[driverName].register(this);
}
return this.robot.drivers[driverName];
};
Robot.prototype.registerDriver = function(moduleName, driverName) {
if (this.drivers[driverName] != null) {
return;
if (this.drivers[driverName] == null) {
return this.drivers[driverName] = require(moduleName);
}
return this.drivers[driverName] = moduleName;
};
return Robot;

View File

@ -0,0 +1,20 @@
Cylon = require '..'
Cylon.api host: '0.0.0.0', port: '8080'
class MyRobot
commands:
["relax"]
relax: ->
return "#{this.name} says relax"
work: (me) ->
every 1.seconds(), ->
Logger.info me.name
robot = new MyRobot
robot.name = "frankie"
Cylon.robot robot
Cylon.start()

View File

@ -1,6 +1,6 @@
{
"name": "cylon",
"version": "0.5.0",
"version": "0.6.0",
"main": "dist/cylon.js",
"description": "A JavaScript robotics framework using Node.js",
"homepage": "http://cylonjs.com",

View File

@ -35,7 +35,7 @@ namespace 'Cylon', ->
@robot = opts.robot
@name = opts.name
@connection_id = opts.id
@adaptor = @requireAdaptor opts
@adaptor = @initAdaptor opts
@port = new Cylon.Port opts.port
proxyFunctionsToObject @adaptor.commands(), @adaptor, @self
@ -50,7 +50,7 @@ namespace 'Cylon', ->
connection_id: @connection_id
}
# Public: Creates the adaptor connection
# Public: Connect the adaptor's connection
#
# callback - callback function to run when the adaptor is connected
#
@ -61,7 +61,7 @@ namespace 'Cylon', ->
Logger.info msg
@adaptor.connect(callback)
# Public: Closes the adaptor connection
# Public: Disconnect the adaptor's connection
#
# Returns nothing
disconnect: ->
@ -72,11 +72,12 @@ namespace 'Cylon', ->
# Public: sets up adaptor with @robot
#
# adaptorName - module name of adaptor to require
# opts - options for adaptor being initialized
# adaptor - name of the adaptor
#
# Returns the set-up adaptor
requireAdaptor: (opts) ->
initAdaptor: (opts) ->
Logger.debug "Loading adaptor '#{opts.adaptor}'"
@robot.requireAdaptor(opts.adaptor, @self, opts)
@robot.initAdaptor(opts.adaptor, @self, opts)
module.exports = Cylon.Connection

View File

@ -34,7 +34,7 @@ namespace 'Cylon', ->
@name = opts.name
@pin = opts.pin
@connection = @determineConnection(opts.connection) or @defaultConnection()
@driver = @requireDriver(opts)
@driver = @initDriver(opts)
proxyFunctionsToObject @driver.commands(), @driver, @self
# Public: Starts the device driver
@ -86,12 +86,12 @@ namespace 'Cylon', ->
# Public: sets up driver with @robot
#
# opts - object containing options when requiring driver
# driver - name of the module to require()
# opts - object containing options when initializing driver
# driver - name of the driver to intt()
#
# Returns the set-up driver
requireDriver: (opts = {}) ->
initDriver: (opts = {}) ->
Logger.debug "Loading driver '#{ opts.driver }'"
@robot.requireDriver(opts.driver, @self, opts)
@robot.initDriver(opts.driver, @self, opts)
module.exports = Cylon.Device

View File

@ -55,6 +55,7 @@ namespace 'Cylon', ->
@devices = {}
@adaptors = {}
@drivers = {}
@commands = []
@registerAdaptor "./loopback", "loopback"
@registerDriver "./ping", "ping"
@ -81,6 +82,7 @@ namespace 'Cylon', ->
name: @name
connections: (connection.data() for n, connection of @connections)
devices: (device.data() for n, device of @devices)
commands: @commands
}
# Public: Initializes all connections for the robot
@ -162,31 +164,27 @@ namespace 'Cylon', ->
for n, connection of @connections
connection.disconnect()
# Public: Requires a hardware adaptor and adds it to @robot.adaptors
# Public: Initialize an adaptor and adds it to @robot.adaptors
#
# adaptorName - module name of adaptor to require
# connection - the Connection that requested the adaptor be required
#
# Returns the set-up adaptor
requireAdaptor: (adaptorName, connection, opts = {}) ->
if @robot.adaptors[adaptorName]?
if typeof @robot.adaptors[adaptorName] is 'string'
@robot.adaptors[adaptorName] = require(
@robot.adaptors[adaptorName]
).adaptor(
name: adaptorName,
connection: connection,
extraParams: opts
)
else
require("cylon-#{adaptorName}").register(this)
@robot.adaptors[adaptorName] = require(
"cylon-#{adaptorName}"
).adaptor(
name: adaptorName,
connection: connection,
extraParams: opts
)
# Returns the adaptor
initAdaptor: (adaptorName, connection, opts = {}) ->
@robot.requireAdaptor(adaptorName).adaptor
name: adaptorName,
connection: connection,
extraParams: opts
# Public: Requires a hardware adaptor and adds it to @robot.adaptors
#
# adaptorName - module name of adaptor to require
#
# Returns the module for the adaptor
requireAdaptor: (adaptorName) =>
unless @robot.adaptors[adaptorName]?
@robot.registerAdaptor "cylon-#{adaptorName}", adaptorName
@robot.adaptors[adaptorName].register this
return @robot.adaptors[adaptorName]
@ -196,35 +194,31 @@ namespace 'Cylon', ->
# adaptorName - name of the adaptor to register the moduleName under
#
# Returns the registered module name
registerAdaptor: (moduleName, adaptorName) ->
return if @adaptors[adaptorName]?
@adaptors[adaptorName] = moduleName
registerAdaptor: (moduleName, adaptorName) =>
@adaptors[adaptorName] = require(moduleName) unless @adaptors[adaptorName]?
# Public: Requires a hardware driver and adds it to @robot.drivers
# Public: Init a hardware driver
#
# driverName - driver name
# device - the Device that requested the driver be initialized
# opts - object containing options when initializing driver
#
# Returns the new driver
initDriver: (driverName, device, opts = {}) ->
@robot.requireDriver(driverName).driver
name: driverName,
device: device,
extraParams: opts
# Public: Requires module for a driver and adds it to @robot.drivers
#
# driverName - module name of driver to require
# connection - the Connection that requested the driver be required
#
# Returns the set-up driver
requireDriver: (driverName, device, opts = {}) ->
if @robot.drivers[driverName]?
if typeof @robot.drivers[driverName] is 'string'
@robot.drivers[driverName] = require(
@robot.drivers[driverName]
).driver(
name: driverName,
device: device,
extraParams: opts
)
else
require("cylon-#{driverName}").register(this)
@robot.drivers[driverName] = require(
"cylon-#{driverName}"
).driver(
name: driverName,
device: device,
extraParams: opts
)
# Returns the module for driver
requireDriver: (driverName) =>
unless @robot.drivers[driverName]?
@robot.registerDriver "cylon-#{driverName}", driverName
@robot.drivers[driverName].register this
return @robot.drivers[driverName]
@ -235,7 +229,6 @@ namespace 'Cylon', ->
#
# Returns the registered module name
registerDriver: (moduleName, driverName) =>
return if @drivers[driverName]?
@drivers[driverName] = moduleName
@drivers[driverName] = require(moduleName) unless @drivers[driverName]?
module.exports = Cylon.Robot

View File

@ -7,14 +7,14 @@
source("robot");
describe("Connection", function() {
var adaptor, connection, requireAdaptor, robot;
var adaptor, connection, initAdaptor, robot;
robot = new Cylon.Robot({
name: 'me'
});
adaptor = new Cylon.Adaptor({
name: 'loopback'
});
requireAdaptor = sinon.stub(robot, 'requireAdaptor').returns(adaptor);
initAdaptor = sinon.stub(robot, 'initAdaptor').returns(adaptor);
connection = new Cylon.Connection({
name: "connective",
adaptor: "loopback",

View File

@ -7,14 +7,14 @@
source("test/driver");
describe("Device", function() {
var device, driver, requireDriver, robot;
var device, driver, initDriver, robot;
robot = new Cylon.Robot({
name: 'me'
});
driver = new Cylon.Driver({
name: 'driving'
});
requireDriver = sinon.stub(robot, 'requireDriver').returns(driver);
initDriver = sinon.stub(robot, 'initDriver').returns(driver);
device = new Cylon.Device({
name: "devisive",
driver: 'driving',
@ -28,8 +28,8 @@
});
it("should use default connection if none specified");
it("should use connection if one is specified");
return it("should require a driver", function() {
return requireDriver.should.be.called;
return it("should init a driver", function() {
return initDriver.should.be.called;
});
});

View File

@ -7,7 +7,7 @@ source "robot"
describe "Connection", ->
robot = new Cylon.Robot(name: 'me')
adaptor = new Cylon.Adaptor(name: 'loopback')
requireAdaptor = sinon.stub(robot, 'requireAdaptor').returns(adaptor)
initAdaptor = sinon.stub(robot, 'initAdaptor').returns(adaptor)
connection = new Cylon.Connection
name: "connective"
adaptor: "loopback"

View File

@ -7,7 +7,7 @@ source "test/driver"
describe "Device", ->
robot = new Cylon.Robot(name: 'me')
driver = new Cylon.Driver(name: 'driving')
requireDriver = sinon.stub(robot, 'requireDriver').returns(driver)
initDriver = sinon.stub(robot, 'initDriver').returns(driver)
device = new Cylon.Device(name: "devisive", driver: 'driving', robot: robot)
it "should belong to a robot", ->
@ -19,5 +19,5 @@ describe "Device", ->
it "should use default connection if none specified"
it "should use connection if one is specified"
it "should require a driver", ->
requireDriver.should.be.called
it "should init a driver", ->
initDriver.should.be.called