From 9d48cba3cf6f8a16b65120d9a64b3c24b5a10811 Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Mon, 4 Nov 2013 11:57:27 -0800 Subject: [PATCH 1/4] Namespace Robot class --- dist/robot.js | 344 ++++++++++++++++--------------- src/robot.coffee | 336 +++++++++++++++--------------- test/dist/specs/robot.spec.js | 10 +- test/src/specs/robot.spec.coffee | 18 +- 4 files changed, 359 insertions(+), 349 deletions(-) diff --git a/dist/robot.js b/dist/robot.js index b2261b3..633ce96 100644 --- a/dist/robot.js +++ b/dist/robot.js @@ -9,7 +9,7 @@ (function() { 'use strict'; - var Async, Connection, Device, Robot, + var Async, Connection, Device, namespace, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; @@ -17,206 +17,212 @@ require('./basestar'); + namespace = require('node-namespace'); + Connection = require("./connection"); Device = require("./device"); Async = require("async"); - module.exports = Robot = (function() { - var klass; + namespace('Cylon', function() { + return this.Robot = (function() { + var klass; - klass = Robot; + klass = Robot; - function Robot(opts) { - var func, n, reserved; - if (opts == null) { - opts = {}; - } - this.registerDriver = __bind(this.registerDriver, this); - this.startDevices = __bind(this.startDevices, this); - this.startConnections = __bind(this.startConnections, this); - this.start = __bind(this.start, this); - this.initDevices = __bind(this.initDevices, this); - this.initConnections = __bind(this.initConnections, this); - this.robot = this; - this.name = opts.name || this.constructor.randomName(); - this.master = opts.master; - this.connections = {}; - this.devices = {}; - this.adaptors = {}; - this.drivers = {}; - this.registerAdaptor("./loopback", "loopback"); - this.registerDriver("./ping", "ping"); - this.initConnections(opts.connection || opts.connections); - this.initDevices(opts.device || opts.devices); - this.work = opts.work || function() { - return Logger.info("No work yet"); - }; - for (n in opts) { - func = opts[n]; - reserved = ['connection', 'connections', 'device', 'devices', 'work']; - if (__indexOf.call(reserved, n) < 0) { - this.robot[n] = func; + function Robot(opts) { + var func, n, reserved; + if (opts == null) { + opts = {}; + } + this.registerDriver = __bind(this.registerDriver, this); + this.startDevices = __bind(this.startDevices, this); + this.startConnections = __bind(this.startConnections, this); + this.start = __bind(this.start, this); + this.initDevices = __bind(this.initDevices, this); + this.initConnections = __bind(this.initConnections, this); + this.robot = this; + this.name = opts.name || this.constructor.randomName(); + this.master = opts.master; + this.connections = {}; + this.devices = {}; + this.adaptors = {}; + this.drivers = {}; + this.registerAdaptor("./loopback", "loopback"); + this.registerDriver("./ping", "ping"); + this.initConnections(opts.connection || opts.connections); + this.initDevices(opts.device || opts.devices); + this.work = opts.work || function() { + return Logger.info("No work yet"); + }; + for (n in opts) { + func = opts[n]; + reserved = ['connection', 'connections', 'device', 'devices', 'work']; + if (__indexOf.call(reserved, n) < 0) { + this.robot[n] = func; + } } } - } - Robot.randomName = function() { - return "Robot " + (Math.floor(Math.random() * 100000)); - }; - - Robot.prototype.data = function() { - var connection, device, n; - return { - name: this.name, - connections: (function() { - var _ref, _results; - _ref = this.connections; - _results = []; - for (n in _ref) { - connection = _ref[n]; - _results.push(connection.data()); - } - return _results; - }).call(this), - devices: (function() { - var _ref, _results; - _ref = this.devices; - _results = []; - for (n in _ref) { - device = _ref[n]; - _results.push(device.data()); - } - return _results; - }).call(this) + Robot.randomName = function() { + return "Robot " + (Math.floor(Math.random() * 100000)); }; - }; - Robot.prototype.initConnections = function(connections) { - var connection, _i, _len; - Logger.info("Initializing connections..."); - if (connections == null) { - return; - } - connections = [].concat(connections); - for (_i = 0, _len = connections.length; _i < _len; _i++) { - connection = connections[_i]; - Logger.info("Initializing connection '" + connection.name + "'..."); - connection['robot'] = this; - this.connections[connection.name] = new Connection(connection); - } - return this.connections; - }; + Robot.prototype.data = function() { + var connection, device, n; + return { + name: this.name, + connections: (function() { + var _ref, _results; + _ref = this.connections; + _results = []; + for (n in _ref) { + connection = _ref[n]; + _results.push(connection.data()); + } + return _results; + }).call(this), + devices: (function() { + var _ref, _results; + _ref = this.devices; + _results = []; + for (n in _ref) { + device = _ref[n]; + _results.push(device.data()); + } + return _results; + }).call(this) + }; + }; - Robot.prototype.initDevices = function(devices) { - var device, _i, _len, _results; - Logger.info("Initializing devices..."); - if (devices == null) { - return; - } - devices = [].concat(devices); - _results = []; - for (_i = 0, _len = devices.length; _i < _len; _i++) { - device = devices[_i]; - Logger.info("Initializing device '" + device.name + "'..."); - device['robot'] = this; - _results.push(this.devices[device.name] = new Device(device)); - } - return _results; - }; + Robot.prototype.initConnections = function(connections) { + var connection, _i, _len; + Logger.info("Initializing connections..."); + if (connections == null) { + return; + } + connections = [].concat(connections); + for (_i = 0, _len = connections.length; _i < _len; _i++) { + connection = connections[_i]; + Logger.info("Initializing connection '" + connection.name + "'..."); + connection['robot'] = this; + this.connections[connection.name] = new Connection(connection); + } + return this.connections; + }; - Robot.prototype.start = function() { - var _this = this; - return this.startConnections(function() { - return _this.robot.startDevices(function() { - return _this.robot.work.call(_this.robot, _this.robot); + Robot.prototype.initDevices = function(devices) { + var device, _i, _len, _results; + Logger.info("Initializing devices..."); + if (devices == null) { + return; + } + devices = [].concat(devices); + _results = []; + for (_i = 0, _len = devices.length; _i < _len; _i++) { + device = devices[_i]; + Logger.info("Initializing device '" + device.name + "'..."); + device['robot'] = this; + _results.push(this.devices[device.name] = new Device(device)); + } + return _results; + }; + + Robot.prototype.start = function() { + var _this = this; + return this.startConnections(function() { + return _this.robot.startDevices(function() { + return _this.robot.work.call(_this.robot, _this.robot); + }); }); - }); - }; + }; - Robot.prototype.startConnections = function(callback) { - var connection, n, starters, _ref; - Logger.info("Starting connections..."); - starters = {}; - _ref = this.connections; - for (n in _ref) { - connection = _ref[n]; - starters[n] = connection.connect; - } - return Async.parallel(starters, callback); - }; + Robot.prototype.startConnections = function(callback) { + var connection, n, starters, _ref; + Logger.info("Starting connections..."); + starters = {}; + _ref = this.connections; + for (n in _ref) { + connection = _ref[n]; + starters[n] = connection.connect; + } + return Async.parallel(starters, callback); + }; - Robot.prototype.startDevices = function(callback) { - var device, n, starters, _ref; - Logger.info("Starting devices..."); - starters = {}; - _ref = this.devices; - for (n in _ref) { - device = _ref[n]; - this.robot[n] = device; - starters[n] = device.start; - } - return Async.parallel(starters, callback); - }; + Robot.prototype.startDevices = function(callback) { + var device, n, starters, _ref; + Logger.info("Starting devices..."); + starters = {}; + _ref = this.devices; + for (n in _ref) { + device = _ref[n]; + this.robot[n] = device; + starters[n] = device.start; + } + return Async.parallel(starters, callback); + }; - Robot.prototype.requireAdaptor = function(adaptorName, connection) { - if (this.robot.adaptors[adaptorName] != null) { - if (typeof this.robot.adaptors[adaptorName] === 'string') { - this.robot.adaptors[adaptorName] = require(this.robot.adaptors[adaptorName]).adaptor({ + Robot.prototype.requireAdaptor = function(adaptorName, connection) { + 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 + }); + } + } else { + require("cylon-" + adaptorName).register(this); + this.robot.adaptors[adaptorName] = require("cylon-" + adaptorName).adaptor({ name: adaptorName, connection: connection }); } - } else { - require("cylon-" + adaptorName).register(this); - this.robot.adaptors[adaptorName] = require("cylon-" + adaptorName).adaptor({ - name: adaptorName, - connection: connection - }); - } - return this.robot.adaptors[adaptorName]; - }; + return this.robot.adaptors[adaptorName]; + }; - Robot.prototype.registerAdaptor = function(moduleName, adaptorName) { - if (this.adaptors[adaptorName] != null) { - return; - } - return this.adaptors[adaptorName] = moduleName; - }; + Robot.prototype.registerAdaptor = function(moduleName, adaptorName) { + if (this.adaptors[adaptorName] != null) { + return; + } + return this.adaptors[adaptorName] = moduleName; + }; - Robot.prototype.requireDriver = 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({ + Robot.prototype.requireDriver = 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 }); } - } else { - require("cylon-" + driverName).register(this); - this.robot.drivers[driverName] = require("cylon-" + driverName).driver({ - name: driverName, - device: device, - extraParams: opts - }); - } - return this.robot.drivers[driverName]; - }; + return this.robot.drivers[driverName]; + }; - Robot.prototype.registerDriver = function(moduleName, driverName) { - if (this.drivers[driverName] != null) { - return; - } - return this.drivers[driverName] = moduleName; - }; + Robot.prototype.registerDriver = function(moduleName, driverName) { + if (this.drivers[driverName] != null) { + return; + } + return this.drivers[driverName] = moduleName; + }; - return Robot; + return Robot; - })(); + })(); + }); + + module.exports = Cylon.Robot; }).call(this); diff --git a/src/robot.coffee b/src/robot.coffee index 62e0de3..f05ff07 100644 --- a/src/robot.coffee +++ b/src/robot.coffee @@ -8,191 +8,197 @@ 'use strict'; -require('./cylon') -require('./basestar') -Connection = require("./connection") -Device = require("./device") -Async = require("async") +require './cylon' +require './basestar' + +namespace = require 'node-namespace' + +Connection = require "./connection" +Device = require "./device" +Async = require "async" # A Robot is the primary interface for interacting with a collection of physical # computing capabilities. -module.exports = class Robot - klass = this +namespace 'Cylon', -> + class @Robot + klass = this - # Public: Creates a new Robot - # - # opts - object containing Robot options - # name - optional, string name of the robot - # master - Cylon.Master class that orchestrates robots - # connection/connections - object connections to connect to - # device/devices - object devices to connect to - # work - work to be performed when the Robot is started - # - # Returns a new Robot - # Example (CoffeeScript): - # Cylon.robot - # name: "Spherobot!" - # - # connection: - # name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0' - # - # device: - # name: 'sphero', driver: 'sphero' - # - # work: (me) -> - # every 1.second(), -> - # me.sphero.roll 60, Math.floor(Math.random() * 360) - constructor: (opts = {}) -> - @robot = this - @name = opts.name or @constructor.randomName() - @master = opts.master - @connections = {} - @devices = {} - @adaptors = {} - @drivers = {} + # Public: Creates a new Robot + # + # opts - object containing Robot options + # name - optional, string name of the robot + # master - Cylon.Master class that orchestrates robots + # connection/connections - object connections to connect to + # device/devices - object devices to connect to + # work - work to be performed when the Robot is started + # + # Returns a new Robot + # Example (CoffeeScript): + # Cylon.robot + # name: "Spherobot!" + # + # connection: + # name: 'sphero', adaptor: 'sphero', port: '/dev/rfcomm0' + # + # device: + # name: 'sphero', driver: 'sphero' + # + # work: (me) -> + # every 1.second(), -> + # me.sphero.roll 60, Math.floor(Math.random() * 360) + constructor: (opts = {}) -> + @robot = this + @name = opts.name or @constructor.randomName() + @master = opts.master + @connections = {} + @devices = {} + @adaptors = {} + @drivers = {} - @registerAdaptor "./loopback", "loopback" - @registerDriver "./ping", "ping" + @registerAdaptor "./loopback", "loopback" + @registerDriver "./ping", "ping" - @initConnections(opts.connection or opts.connections) - @initDevices(opts.device or opts.devices) - @work = opts.work or -> (Logger.info "No work yet") + @initConnections(opts.connection or opts.connections) + @initDevices(opts.device or opts.devices) + @work = opts.work or -> (Logger.info "No work yet") - for n, func of opts - reserved = ['connection', 'connections', 'device', 'devices', 'work'] - @robot[n] = func unless n in reserved + for n, func of opts + reserved = ['connection', 'connections', 'device', 'devices', 'work'] + @robot[n] = func unless n in reserved - # Public: Generates a random name for a Robot. - # - # Returns a string name - @randomName: -> - "Robot #{ Math.floor(Math.random() * 100000) }" + # Public: Generates a random name for a Robot. + # + # Returns a string name + @randomName: -> + "Robot #{ Math.floor(Math.random() * 100000) }" - # Public: Exports basic data for the Robot - # - # Returns an Object containing Robot data - data: -> - { - name: @name - connections: (connection.data() for n, connection of @connections) - devices: (device.data() for n, device of @devices) - } + # Public: Exports basic data for the Robot + # + # Returns an Object containing Robot data + data: -> + { + name: @name + connections: (connection.data() for n, connection of @connections) + devices: (device.data() for n, device of @devices) + } - # Public: Initializes all connections for the robot - # - # connections - connections to initialize - # - # Returns initialized connections - initConnections: (connections) => - Logger.info "Initializing connections..." - return unless connections? - connections = [].concat connections - for connection in connections - Logger.info "Initializing connection '#{ connection.name }'..." - connection['robot'] = this - @connections[connection.name] = new Connection(connection) + # Public: Initializes all connections for the robot + # + # connections - connections to initialize + # + # Returns initialized connections + initConnections: (connections) => + Logger.info "Initializing connections..." + return unless connections? + connections = [].concat connections + for connection in connections + Logger.info "Initializing connection '#{ connection.name }'..." + connection['robot'] = this + @connections[connection.name] = new Connection(connection) - @connections + @connections - # Public: Initializes all devices for the robot - # - # devices - devices to initialize - # - # Returns initialized devices - initDevices: (devices) => - Logger.info "Initializing devices..." - return unless devices? - devices = [].concat devices - for device in devices - Logger.info "Initializing device '#{ device.name }'..." - device['robot'] = this - @devices[device.name] = new Device(device) + # Public: Initializes all devices for the robot + # + # devices - devices to initialize + # + # Returns initialized devices + initDevices: (devices) => + Logger.info "Initializing devices..." + return unless devices? + devices = [].concat devices + for device in devices + Logger.info "Initializing device '#{ device.name }'..." + device['robot'] = this + @devices[device.name] = new Device(device) - # Public: Starts the Robot working. - # - # Starts the connections, devices, and work. - # - # Returns the result of the work - start: => - @startConnections => - @robot.startDevices => - @robot.work.call(@robot, @robot) + # Public: Starts the Robot working. + # + # Starts the connections, devices, and work. + # + # Returns the result of the work + start: => + @startConnections => + @robot.startDevices => + @robot.work.call(@robot, @robot) - # Public: Starts the Robot's connections and triggers a callback - # - # callback - callback function to be triggered - # - # Returns nothing - startConnections: (callback) => - Logger.info "Starting connections..." - starters = {} - for n, connection of @connections - starters[n] = connection.connect + # Public: Starts the Robot's connections and triggers a callback + # + # callback - callback function to be triggered + # + # Returns nothing + startConnections: (callback) => + Logger.info "Starting connections..." + starters = {} + for n, connection of @connections + starters[n] = connection.connect - Async.parallel starters, callback + Async.parallel starters, callback - # Public: Starts the Robot's devices and triggers a callback - # - # callback - callback function to be triggered - # - # Returns nothing - startDevices: (callback) => - Logger.info "Starting devices..." - starters = {} - for n, device of @devices - @robot[n] = device - starters[n] = device.start + # Public: Starts the Robot's devices and triggers a callback + # + # callback - callback function to be triggered + # + # Returns nothing + startDevices: (callback) => + Logger.info "Starting devices..." + starters = {} + for n, device of @devices + @robot[n] = device + starters[n] = device.start - Async.parallel starters, callback + Async.parallel starters, callback - # Public: Requires a hardware 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) -> - if @robot.adaptors[adaptorName]? - if typeof @robot.adaptors[adaptorName] is 'string' - @robot.adaptors[adaptorName] = require(@robot.adaptors[adaptorName]).adaptor(name: adaptorName, connection: connection) - else - require("cylon-#{adaptorName}").register(this) - @robot.adaptors[adaptorName] = require("cylon-#{adaptorName}").adaptor(name: adaptorName, connection: connection) + # Public: Requires a hardware 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) -> + if @robot.adaptors[adaptorName]? + if typeof @robot.adaptors[adaptorName] is 'string' + @robot.adaptors[adaptorName] = require(@robot.adaptors[adaptorName]).adaptor(name: adaptorName, connection: connection) + else + require("cylon-#{adaptorName}").register(this) + @robot.adaptors[adaptorName] = require("cylon-#{adaptorName}").adaptor(name: adaptorName, connection: connection) - return @robot.adaptors[adaptorName] + return @robot.adaptors[adaptorName] - # Public: Registers an Adaptor with the Robot - # - # moduleName - name of the Node module to require - # 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 + # Public: Registers an Adaptor with the Robot + # + # moduleName - name of the Node module to require + # 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 - # Public: Requires a hardware 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) + # Public: Requires a hardware 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) - return @robot.drivers[driverName] + return @robot.drivers[driverName] - # Public: Registers an Driver with the Robot - # - # moduleName - name of the Node module to require - # driverName - name of the driver to register the moduleName under - # - # Returns the registered module name - registerDriver: (moduleName, driverName) => - return if @drivers[driverName]? - @drivers[driverName] = moduleName + # Public: Registers an Driver with the Robot + # + # moduleName - name of the Node module to require + # driverName - name of the driver to register the moduleName under + # + # Returns the registered module name + registerDriver: (moduleName, driverName) => + return if @drivers[driverName]? + @drivers[driverName] = moduleName + +module.exports = Cylon.Robot diff --git a/test/dist/specs/robot.spec.js b/test/dist/specs/robot.spec.js index 9dc59a8..f1b5d33 100644 --- a/test/dist/specs/robot.spec.js +++ b/test/dist/specs/robot.spec.js @@ -1,8 +1,6 @@ (function() { 'use strict'; - var Robot; - - Robot = source("robot"); + source("robot"); source("logger"); @@ -16,7 +14,7 @@ whateverFunc = function() { return Logger.info("whatever!"); }; - robot = new Robot({ + robot = new Cylon.Robot({ name: "irobot", work: testWork, whatever: whateverFunc @@ -26,8 +24,8 @@ }); it("has a random name, if not given", function() { var r; - sinon.stub(Robot, 'randomName').returns('Electra'); - r = new Robot; + sinon.stub(Cylon.Robot, 'randomName').returns('Electra'); + r = new Cylon.Robot; return r.name.should.be.equal('Electra'); }); it("has work", function() { diff --git a/test/src/specs/robot.spec.coffee b/test/src/specs/robot.spec.coffee index d6ea4e2..927ba81 100644 --- a/test/src/specs/robot.spec.coffee +++ b/test/src/specs/robot.spec.coffee @@ -1,25 +1,25 @@ 'use strict'; -Robot = source("robot") +source("robot") source("logger") Logger.setup(false) # quiet logger for tests describe "Robot", -> - testWork = -> - Logger.info "hi" - - whateverFunc = -> - Logger.info "whatever!" + testWork = -> Logger.info "hi" + whateverFunc = -> Logger.info "whatever!" - robot = new Robot(name: "irobot", work: testWork, whatever: whateverFunc) + robot = new Cylon.Robot + name: "irobot" + work: testWork + whatever: whateverFunc it "has a name, if given", -> robot.name.should.be.equal 'irobot' it "has a random name, if not given", -> - sinon.stub(Robot, 'randomName').returns('Electra') - r = new Robot + sinon.stub(Cylon.Robot, 'randomName').returns('Electra') + r = new Cylon.Robot r.name.should.be.equal 'Electra' it "has work", -> From ae666f67dd57375b50089d3abd210ab1ec1c4e2c Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Mon, 4 Nov 2013 12:13:40 -0800 Subject: [PATCH 2/4] Namespace Connection class --- dist/connection.js | 104 +++++++++++----------- src/connection.coffee | 120 +++++++++++++------------- test/dist/specs/connection.spec.js | 6 +- test/src/specs/connection.spec.coffee | 7 +- 4 files changed, 125 insertions(+), 112 deletions(-) diff --git a/dist/connection.js b/dist/connection.js index 8c3c3d9..c0f9ccb 100644 --- a/dist/connection.js +++ b/dist/connection.js @@ -9,73 +9,79 @@ (function() { 'use strict'; - var Connection, EventEmitter, Port, + var EventEmitter, Port, namespace, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; require("./robot"); + namespace = require('node-namespace'); + Port = require("./port"); EventEmitter = require('events').EventEmitter; - module.exports = Connection = (function(_super) { - __extends(Connection, _super); + namespace('Cylon', function() { + return this.Connection = (function(_super) { + __extends(Connection, _super); - function Connection(opts) { - if (opts == null) { - opts = {}; + function Connection(opts) { + if (opts == null) { + opts = {}; + } + this.connect = __bind(this.connect, this); + if (opts.id == null) { + opts.id = Math.floor(Math.random() * 10000); + } + this.self = this; + this.robot = opts.robot; + this.name = opts.name; + this.connection_id = opts.id; + this.adaptor = this.requireAdaptor(opts.adaptor); + this.port = new Port(opts.port); + proxyFunctionsToObject(this.adaptor.commands(), this.adaptor, Connection); } - this.connect = __bind(this.connect, this); - if (opts.id == null) { - opts.id = Math.floor(Math.random() * 10000); - } - this.self = this; - this.robot = opts.robot; - this.name = opts.name; - this.connection_id = opts.id; - this.adaptor = this.requireAdaptor(opts.adaptor); - this.port = new Port(opts.port); - proxyFunctionsToObject(this.adaptor.commands(), this.adaptor, Connection); - } - Connection.prototype.data = function() { - return { - name: this.name, - port: this.port.toString(), - adaptor: this.adaptor.constructor.name || this.adaptor.name, - connection_id: this.connection_id + Connection.prototype.data = function() { + return { + name: this.name, + port: this.port.toString(), + adaptor: this.adaptor.constructor.name || this.adaptor.name, + connection_id: this.connection_id + }; }; - }; - Connection.prototype.connect = function(callback) { - var msg; - msg = "Connecting to '" + this.name + "'"; - if (this.port != null) { - msg += " on port '" + (this.port.toString()) + "'"; - } - Logger.info(msg); - return this.adaptor.connect(callback); - }; + Connection.prototype.connect = function(callback) { + var msg; + msg = "Connecting to '" + this.name + "'"; + if (this.port != null) { + msg += " on port '" + (this.port.toString()) + "'"; + } + Logger.info(msg); + return this.adaptor.connect(callback); + }; - Connection.prototype.disconnect = function() { - var msg; - msg = "Disconnecting from '" + this.name + "'"; - if (this.port != null) { - msg += " on port '" + (this.port.toString()) + "'"; - } - Logger.info(msg); - return this.adaptor.disconnect(); - }; + Connection.prototype.disconnect = function() { + var msg; + msg = "Disconnecting from '" + this.name + "'"; + if (this.port != null) { + msg += " on port '" + (this.port.toString()) + "'"; + } + Logger.info(msg); + return this.adaptor.disconnect(); + }; - Connection.prototype.requireAdaptor = function(adaptorName) { - Logger.debug("Loading adaptor '" + adaptorName + "'"); - return this.robot.requireAdaptor(adaptorName, this.self); - }; + Connection.prototype.requireAdaptor = function(adaptorName) { + Logger.debug("Loading adaptor '" + adaptorName + "'"); + return this.robot.requireAdaptor(adaptorName, this.self); + }; - return Connection; + return Connection; - })(EventEmitter); + })(EventEmitter); + }); + + module.exports = Cylon.Connection; }).call(this); diff --git a/src/connection.coffee b/src/connection.coffee index 175e96c..f1b71a1 100644 --- a/src/connection.coffee +++ b/src/connection.coffee @@ -8,72 +8,76 @@ 'use strict'; -require("./robot") +require "./robot" -Port = require("./port") +namespace = require 'node-namespace' + +Port = require "./port" EventEmitter = require('events').EventEmitter - # The Connection class represents the interface to # a specific group of hardware devices. Examples would be an # Arduino, a Sphero, or an ARDrone. -module.exports = class Connection extends EventEmitter +namespace 'Cylon', -> + class @Connection extends EventEmitter - # Public: Creates a new Connection - # @opts - a hash of acceptable params: - # - id - a string ID for the connection - # - name - a name for the connection - # - robot - Robot the Connection belongs to - # - adaptor - the string module of the adaptor to be set up - # - port - a port to use for the Connection - # - # Returns the newly set-up connection - constructor: (opts = {}) -> - opts.id ?= Math.floor(Math.random() * 10000) - @self = this - @robot = opts.robot - @name = opts.name - @connection_id = opts.id - @adaptor = @requireAdaptor(opts.adaptor) # or 'loopback') - @port = new Port(opts.port) - proxyFunctionsToObject @adaptor.commands(), @adaptor, Connection + # Public: Creates a new Connection + # @opts - a hash of acceptable params: + # - id - a string ID for the connection + # - name - a name for the connection + # - robot - Robot the Connection belongs to + # - adaptor - the string module of the adaptor to be set up + # - port - a port to use for the Connection + # + # Returns the newly set-up connection + constructor: (opts = {}) -> + opts.id ?= Math.floor(Math.random() * 10000) + @self = this + @robot = opts.robot + @name = opts.name + @connection_id = opts.id + @adaptor = @requireAdaptor(opts.adaptor) # or 'loopback') + @port = new Port(opts.port) + proxyFunctionsToObject @adaptor.commands(), @adaptor, Connection - # Public: Exports basic data for the Connection - # - # Returns an Object containing Connection data - data: -> - { - name: @name, - port: @port.toString() - adaptor: @adaptor.constructor.name || @adaptor.name - connection_id: @connection_id - } + # Public: Exports basic data for the Connection + # + # Returns an Object containing Connection data + data: -> + { + name: @name, + port: @port.toString() + adaptor: @adaptor.constructor.name || @adaptor.name + connection_id: @connection_id + } - # Public: Creates the adaptor connection - # - # callback - callback function to run when the adaptor is connected - # - # Returns the result of the supplied callback function - connect: (callback) => - msg = "Connecting to '#{@name}'" - msg += " on port '#{@port.toString()}'" if @port? - Logger.info msg - @adaptor.connect(callback) + # Public: Creates the adaptor connection + # + # callback - callback function to run when the adaptor is connected + # + # Returns the result of the supplied callback function + connect: (callback) => + msg = "Connecting to '#{@name}'" + msg += " on port '#{@port.toString()}'" if @port? + Logger.info msg + @adaptor.connect(callback) - # Public: Closes the adaptor connection - # - # Returns nothing - disconnect: -> - msg = "Disconnecting from '#{@name}'" - msg += " on port '#{@port.toString()}'" if @port? - Logger.info msg - @adaptor.disconnect() + # Public: Closes the adaptor connection + # + # Returns nothing + disconnect: -> + msg = "Disconnecting from '#{@name}'" + msg += " on port '#{@port.toString()}'" if @port? + Logger.info msg + @adaptor.disconnect() - # Public: sets up adaptor with @robot - # - # adaptorName - module name of adaptor to require - # - # Returns the set-up adaptor - requireAdaptor: (adaptorName) -> - Logger.debug "Loading adaptor '#{adaptorName}'" - @robot.requireAdaptor(adaptorName, @self) + # Public: sets up adaptor with @robot + # + # adaptorName - module name of adaptor to require + # + # Returns the set-up adaptor + requireAdaptor: (adaptorName) -> + Logger.debug "Loading adaptor '#{adaptorName}'" + @robot.requireAdaptor(adaptorName, @self) + +module.exports = Cylon.Connection diff --git a/test/dist/specs/connection.spec.js b/test/dist/specs/connection.spec.js index 324e2d6..4a62854 100644 --- a/test/dist/specs/connection.spec.js +++ b/test/dist/specs/connection.spec.js @@ -1,8 +1,8 @@ (function() { 'use strict'; - var Adaptor, Connection, Robot; + var Adaptor, Robot; - Connection = source("connection"); + source("connection"); Adaptor = source("adaptor"); @@ -17,7 +17,7 @@ name: 'loopback' }); requireAdaptor = sinon.stub(robot, 'requireAdaptor').returns(adaptor); - connection = new Connection({ + connection = new Cylon.Connection({ name: "connective", adaptor: "loopback", robot: robot diff --git a/test/src/specs/connection.spec.coffee b/test/src/specs/connection.spec.coffee index bf25977..7e83263 100644 --- a/test/src/specs/connection.spec.coffee +++ b/test/src/specs/connection.spec.coffee @@ -1,6 +1,6 @@ 'use strict'; -Connection = source("connection") +source("connection") Adaptor = source("adaptor") Robot = source("robot") @@ -8,7 +8,10 @@ describe "Connection", -> robot = new Robot(name: 'me') adaptor = new Adaptor(name: 'loopback') requireAdaptor = sinon.stub(robot, 'requireAdaptor').returns(adaptor) - connection = new Connection(name: "connective", adaptor: "loopback", robot: robot) + connection = new Cylon.Connection + name: "connective" + adaptor: "loopback" + robot: robot it "should belong to a robot", -> connection.robot.name.should.be.equal 'me' From eda6f9db76c5cb85d2e06843bd905e9d914cf676 Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Mon, 4 Nov 2013 12:16:42 -0800 Subject: [PATCH 3/4] Namespace Device class --- dist/device.js | 120 +++++++++++++------------- src/device.coffee | 134 +++++++++++++++--------------- test/dist/specs/device.spec.js | 12 +-- test/src/specs/device.spec.coffee | 8 +- 4 files changed, 142 insertions(+), 132 deletions(-) diff --git a/dist/device.js b/dist/device.js index ea9e1ba..e5a8c0e 100644 --- a/dist/device.js +++ b/dist/device.js @@ -9,79 +9,85 @@ (function() { 'use strict'; - var Device, EventEmitter, + var EventEmitter, namespace, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; require('./cylon'); + namespace = require('node-namespace'); + EventEmitter = require('events').EventEmitter; - module.exports = Device = (function(_super) { - __extends(Device, _super); + namespace('Cylon', function() { + return this.Device = (function(_super) { + __extends(Device, _super); - function Device(opts) { - if (opts == null) { - opts = {}; + function Device(opts) { + if (opts == null) { + opts = {}; + } + this.start = __bind(this.start, this); + this.self = this; + this.robot = opts.robot; + this.name = opts.name; + this.pin = opts.pin; + this.connection = this.determineConnection(opts.connection) || this.defaultConnection(); + this.driver = this.requireDriver(opts); + proxyFunctionsToObject(this.driver.commands(), this.driver, Device); } - this.start = __bind(this.start, this); - this.self = this; - this.robot = opts.robot; - this.name = opts.name; - this.pin = opts.pin; - this.connection = this.determineConnection(opts.connection) || this.defaultConnection(); - this.driver = this.requireDriver(opts); - proxyFunctionsToObject(this.driver.commands(), this.driver, Device); - } - Device.prototype.start = function(callback) { - var msg; - msg = "Starting device '" + this.name + "'"; - if (this.pin != null) { - msg += " on pin " + this.pin; - } - Logger.info(msg); - return this.driver.start(callback); - }; - - Device.prototype.data = function() { - return { - name: this.name, - driver: this.driver.constructor.name || this.driver.name, - pin: this.pin != null ? this.pin.toString : null, - connection: this.connection.data(), - commands: this.driver.commands() + Device.prototype.start = function(callback) { + var msg; + msg = "Starting device '" + this.name + "'"; + if (this.pin != null) { + msg += " on pin " + this.pin; + } + Logger.info(msg); + return this.driver.start(callback); }; - }; - Device.prototype.determineConnection = function(c) { - if (c) { - return this.robot.connections[c]; - } - }; + Device.prototype.data = function() { + return { + name: this.name, + driver: this.driver.constructor.name || this.driver.name, + pin: this.pin != null ? this.pin.toString : null, + connection: this.connection.data(), + commands: this.driver.commands() + }; + }; - Device.prototype.defaultConnection = function() { - var first, k, v, _ref; - first = 0; - _ref = this.robot.connections; - for (k in _ref) { - v = _ref[k]; - first || (first = v); - } - return first; - }; + Device.prototype.determineConnection = function(c) { + if (c) { + return this.robot.connections[c]; + } + }; - Device.prototype.requireDriver = function(opts) { - if (opts == null) { - opts = {}; - } - Logger.debug("Loading driver '" + opts.driver + "'"); - return this.robot.requireDriver(opts.driver, this.self, opts); - }; + Device.prototype.defaultConnection = function() { + var first, k, v, _ref; + first = 0; + _ref = this.robot.connections; + for (k in _ref) { + v = _ref[k]; + first || (first = v); + } + return first; + }; - return Device; + Device.prototype.requireDriver = function(opts) { + if (opts == null) { + opts = {}; + } + Logger.debug("Loading driver '" + opts.driver + "'"); + return this.robot.requireDriver(opts.driver, this.self, opts); + }; - })(EventEmitter); + return Device; + + })(EventEmitter); + }); + + module.exports = Cylon.Device; }).call(this); diff --git a/src/device.coffee b/src/device.coffee index b6cedb2..85dcf2c 100644 --- a/src/device.coffee +++ b/src/device.coffee @@ -8,79 +8,83 @@ 'use strict'; -require('./cylon') +require './cylon' +namespace = require 'node-namespace' EventEmitter = require('events').EventEmitter # The Artoo::Device class represents the interface to # a specific individual hardware devices. Examples would be a digital # thermometer connected to an Arduino, or a Sphero's accelerometer. -module.exports = class Device extends EventEmitter +namespace 'Cylon', -> + class @Device extends EventEmitter - # Public: Creates a new Device - # - # opts - object containing Device params - # name - string name of the device - # pin - string pin of the device - # robot - parent Robot to the device - # connection - connection to the device - # driver - string name of the module the device driver logic lives in - # - # Returns a new Device - constructor: (opts = {}) -> - @self = this - @robot = opts.robot - @name = opts.name - @pin = opts.pin - @connection = @determineConnection(opts.connection) or @defaultConnection() - @driver = @requireDriver(opts) - proxyFunctionsToObject @driver.commands(), @driver, Device + # Public: Creates a new Device + # + # opts - object containing Device params + # name - string name of the device + # pin - string pin of the device + # robot - parent Robot to the device + # connection - connection to the device + # driver - string name of the module the device driver logic lives in + # + # Returns a new Device + constructor: (opts = {}) -> + @self = this + @robot = opts.robot + @name = opts.name + @pin = opts.pin + @connection = @determineConnection(opts.connection) or @defaultConnection() + @driver = @requireDriver(opts) + proxyFunctionsToObject @driver.commands(), @driver, Device - # Public: Starts the device driver - # - # callback - callback function to be executed by the driver start - # - # Returns result of supplied callback - start: (callback) => - msg = "Starting device '#{ @name }'" - msg += " on pin #{@pin}" if @pin? - Logger.info msg - @driver.start(callback) + # Public: Starts the device driver + # + # callback - callback function to be executed by the driver start + # + # Returns result of supplied callback + start: (callback) => + msg = "Starting device '#{ @name }'" + msg += " on pin #{@pin}" if @pin? + Logger.info msg + @driver.start(callback) - # Public: Exports basic data for the Connection - # - # Returns an Object containing Connection data - data: -> - { - name: @name - driver: @driver.constructor.name || @driver.name - pin: if @pin? then @pin.toString else null - connection: @connection.data() - commands: @driver.commands() - } + # Public: Exports basic data for the Connection + # + # Returns an Object containing Connection data + data: -> + { + name: @name + driver: @driver.constructor.name || @driver.name + pin: if @pin? then @pin.toString else null + connection: @connection.data() + commands: @driver.commands() + } - # Public: Retrieves the connections from the parent Robot instances - # - # c - name of the connection to fetch - # - # Returns a Connection instance - determineConnection: (c) -> - @robot.connections[c] if c + # Public: Retrieves the connections from the parent Robot instances + # + # c - name of the connection to fetch + # + # Returns a Connection instance + determineConnection: (c) -> + @robot.connections[c] if c - # Public: Returns a default Connection to use - # - # Returns a Connection instance - defaultConnection: -> - first = 0 - for k, v of @robot.connections - first or= v - first + # Public: Returns a default Connection to use + # + # Returns a Connection instance + defaultConnection: -> + first = 0 + for k, v of @robot.connections + first or= v + first - # Public: sets up driver with @robot - # - # opts - object containing options when requiring driver - # driver - name of the module to require() - # - # Returns the set-up driver - requireDriver: (opts = {}) -> - Logger.debug "Loading driver '#{ opts.driver }'" - @robot.requireDriver(opts.driver, @self, opts) + # Public: sets up driver with @robot + # + # opts - object containing options when requiring driver + # driver - name of the module to require() + # + # Returns the set-up driver + requireDriver: (opts = {}) -> + Logger.debug "Loading driver '#{ opts.driver }'" + @robot.requireDriver(opts.driver, @self, opts) + +module.exports = Cylon.Device diff --git a/test/dist/specs/device.spec.js b/test/dist/specs/device.spec.js index bdcbe77..d5bf56c 100644 --- a/test/dist/specs/device.spec.js +++ b/test/dist/specs/device.spec.js @@ -1,23 +1,23 @@ (function() { 'use strict'; - var Device, Driver, Robot; + var Driver; - Device = source("device"); + source("device"); + + source("robot"); Driver = source("driver"); - Robot = source("robot"); - describe("Device", function() { var device, driver, requireDriver, robot; - robot = new Robot({ + robot = new Cylon.Robot({ name: 'me' }); driver = new Driver({ name: 'driving' }); requireDriver = sinon.stub(robot, 'requireDriver').returns(driver); - device = new Device({ + device = new Cylon.Device({ name: "devisive", driver: 'driving', robot: robot diff --git a/test/src/specs/device.spec.coffee b/test/src/specs/device.spec.coffee index da7f1fd..5a4a641 100644 --- a/test/src/specs/device.spec.coffee +++ b/test/src/specs/device.spec.coffee @@ -1,14 +1,14 @@ 'use strict'; -Device = source("device") +source("device") +source("robot") Driver = source("driver") -Robot = source("robot") describe "Device", -> - robot = new Robot(name: 'me') + robot = new Cylon.Robot(name: 'me') driver = new Driver(name: 'driving') requireDriver = sinon.stub(robot, 'requireDriver').returns(driver) - device = new Device(name: "devisive", driver: 'driving', robot: robot) + device = new Cylon.Device(name: "devisive", driver: 'driving', robot: robot) it "should belong to a robot", -> device.robot.name.should.be.equal 'me' From fb8c8acca80e12d1547b7c1766378bbdeae1246d Mon Sep 17 00:00:00 2001 From: Andrew Stewart Date: Mon, 4 Nov 2013 12:21:36 -0800 Subject: [PATCH 4/4] Namespace Port class --- dist/port.js | 78 +++++++++++++++++++++------------------- src/port.coffee | 95 ++++++++++++++++++++++++++----------------------- 2 files changed, 92 insertions(+), 81 deletions(-) diff --git a/dist/port.js b/dist/port.js index b7aa252..786294b 100644 --- a/dist/port.js +++ b/dist/port.js @@ -9,47 +9,53 @@ (function() { 'use strict'; - var Port; + var namespace; - module.exports = Port = (function() { - function Port(data) { - this.self = this; - this.isTcp = this.isSerial = this.isPortless = false; - this.parse(data); - } + namespace = require('node-namespace'); - Port.prototype.parse = function(data) { - var match; - if (data === void 0) { - this.port = void 0; - return this.isPortless = true; - } else if (match = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/.exec(data)) { - this.port = match[2]; - this.host = match[1]; - return this.isTcp = true; - } else if (/^[0-9]{1,5}$/.exec(data)) { - this.port = data; - this.host = "localhost"; - return this.isTcp = true; - } else { - this.port = data; - this.host = void 0; - return this.isSerial = true; + namespace('Cylon', function() { + return this.Port = (function() { + function Port(data) { + this.self = this; + this.isTcp = this.isSerial = this.isPortless = false; + this.parse(data); } - }; - Port.prototype.toString = function() { - if (this.isPortless) { - return "none"; - } else if (this.isSerial) { - return this.port; - } else { - return "" + this.host + ":" + this.port; - } - }; + Port.prototype.parse = function(data) { + var match; + if (data === void 0) { + this.port = void 0; + return this.isPortless = true; + } else if (match = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/.exec(data)) { + this.port = match[2]; + this.host = match[1]; + return this.isTcp = true; + } else if (/^[0-9]{1,5}$/.exec(data)) { + this.port = data; + this.host = "localhost"; + return this.isTcp = true; + } else { + this.port = data; + this.host = void 0; + return this.isSerial = true; + } + }; - return Port; + Port.prototype.toString = function() { + if (this.isPortless) { + return "none"; + } else if (this.isSerial) { + return this.port; + } else { + return "" + this.host + ":" + this.port; + } + }; - })(); + return Port; + + })(); + }); + + module.exports = Cylon.Port; }).call(this); diff --git a/src/port.coffee b/src/port.coffee index e86d869..c09837b 100644 --- a/src/port.coffee +++ b/src/port.coffee @@ -8,55 +8,60 @@ 'use strict'; +namespace = require 'node-namespace' + # The Port class represents a port and/or host to be used to connect to # a specific hardware device -module.exports = class Port - # Public: Creates a new Port based on a passed String representation - # - # data - string representation of the Port - # - # Returns a new Port - constructor: (data) -> - @self = this - @isTcp = @isSerial = @isPortless = false - @parse(data) +namespace 'Cylon', -> + class @Port + # Public: Creates a new Port based on a passed String representation + # + # data - string representation of the Port + # + # Returns a new Port + constructor: (data) -> + @self = this + @isTcp = @isSerial = @isPortless = false + @parse(data) - # Public: Parses the Port's data to determine what kind of port it is - # - # data - string representation of the port to parse - # - # Returns nothing. - parse: (data) -> - if data is undefined - @port = undefined - @isPortless = true + # Public: Parses the Port's data to determine what kind of port it is + # + # data - string representation of the port to parse + # + # Returns nothing. + parse: (data) -> + if data is undefined + @port = undefined + @isPortless = true - # is TCP host/port? - else if match = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/.exec(data) - @port = match[2] - @host = match[1] - @isTcp = true + # is TCP host/port? + else if match = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/.exec(data) + @port = match[2] + @host = match[1] + @isTcp = true - # is it a numeric port for localhost tcp? - else if /^[0-9]{1,5}$/.exec(data) - @port = data - @host = "localhost" - @isTcp = true + # is it a numeric port for localhost tcp? + else if /^[0-9]{1,5}$/.exec(data) + @port = data + @host = "localhost" + @isTcp = true - # must be a serial port - else - @port = data - @host = undefined - @isSerial = true + # must be a serial port + else + @port = data + @host = undefined + @isSerial = true - # Public: Returns a string representation of the port that can be used to - # connect to it. - # - # Returns a string - toString: -> - if @isPortless - "none" - else if @isSerial - @port - else - "#{@host}:#{@port}" + # Public: Returns a string representation of the port that can be used to + # connect to it. + # + # Returns a string + toString: -> + if @isPortless + "none" + else if @isSerial + @port + else + "#{@host}:#{@port}" + +module.exports = Cylon.Port