210 comments JS
This commit is contained in:
parent
f916b38b09
commit
8644399276
|
@ -12,6 +12,8 @@ var express = require('express.io');
|
|||
var namespace = require('node-namespace');
|
||||
|
||||
namespace("Cylon", function() {
|
||||
// The Cylon API Server provides an interface to communicate with master class
|
||||
// and retrieve information about the robots being controlled.
|
||||
this.ApiServer = (function() {
|
||||
var master;
|
||||
|
||||
|
@ -40,6 +42,9 @@ namespace("Cylon", function() {
|
|||
});
|
||||
}
|
||||
|
||||
// Parses req to extract params to be used for commands.
|
||||
//
|
||||
// Returns an array of params
|
||||
ApiServer.prototype.parseCommandParams = function(req) {
|
||||
var param_container, params, v, _;
|
||||
params = [];
|
||||
|
|
|
@ -12,6 +12,11 @@ require('./utils');
|
|||
var namespace = require('node-namespace');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
// Basestar is a base class to be used when writing external Cylon adaptors and
|
||||
// drivers. It provides some useful base methods and functionality
|
||||
//
|
||||
// It also extends EventEmitter, so child classes are capable of emitting events
|
||||
// for other parts of the system to handle.
|
||||
namespace("Cylon", function() {
|
||||
this.Basestar = (function(klass) {
|
||||
subclass(Basestar, klass);
|
||||
|
@ -20,6 +25,14 @@ namespace("Cylon", function() {
|
|||
this.self = this;
|
||||
}
|
||||
|
||||
// Public: Proxies calls from all methods in the object to a target object
|
||||
//
|
||||
// methods - array of methods to proxy
|
||||
// target - object to proxy methods to
|
||||
// source - object to proxy methods from
|
||||
// force - whether or not to overwrite existing method definitions
|
||||
//
|
||||
// Returns the klass where the methods have been proxied
|
||||
Basestar.prototype.proxyMethods = function(methods, target, source, force) {
|
||||
if (force == null) {
|
||||
force = false;
|
||||
|
@ -27,6 +40,17 @@ namespace("Cylon", function() {
|
|||
return proxyFunctionsToObject(methods, target, source, force);
|
||||
};
|
||||
|
||||
// Public: Defines an event handler that proxies events from a source object
|
||||
// to a target object
|
||||
//
|
||||
// opts - object containing options:
|
||||
// - targetEventName or eventName - event that should be emitted from the
|
||||
// target
|
||||
// - target - object to proxy event to
|
||||
// - source - object to proxy event from
|
||||
// - update - whether or not to send an 'update' event
|
||||
//
|
||||
// Returns the source
|
||||
Basestar.prototype.defineEvent = function(opts) {
|
||||
var sendUpdate, targetEventName,
|
||||
_this = this;
|
||||
|
@ -43,6 +67,13 @@ namespace("Cylon", function() {
|
|||
return opts.source;
|
||||
};
|
||||
|
||||
// Public: Creates an event handler that proxies events from an adaptor's
|
||||
// 'connector' (reference to whatever module is actually talking to the hw)
|
||||
// to the adaptor's associated connection.
|
||||
//
|
||||
// opts - hash of opts to be passed to defineEvent()
|
||||
//
|
||||
// Returns @connector
|
||||
Basestar.prototype.defineAdaptorEvent = function(opts) {
|
||||
opts['source'] = this.connector;
|
||||
opts['target'] = this.connection;
|
||||
|
@ -52,6 +83,13 @@ namespace("Cylon", function() {
|
|||
return this.defineEvent(opts);
|
||||
};
|
||||
|
||||
// Public: Creates an event handler that proxies events from an device's
|
||||
// 'connector' (reference to whatever module is actually talking to the hw)
|
||||
// to the device's associated connection.
|
||||
//
|
||||
// opts - hash of opts to be passed to defineEvent()
|
||||
//
|
||||
// Returns @connection
|
||||
Basestar.prototype.defineDriverEvent = function(opts) {
|
||||
opts['source'] = this.connection;
|
||||
opts['target'] = this.device;
|
||||
|
|
|
@ -10,6 +10,28 @@
|
|||
|
||||
var namespace = require('node-namespace');
|
||||
|
||||
|
||||
// Public: Fetches a variable from the environment, returning a provided value if
|
||||
// it's not set.
|
||||
//
|
||||
// variable - variable to fetch from the environment
|
||||
// defaultValue - value to return if the ENV variable isn't set
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// process.env["CYLON_TEST"] #=> undefined
|
||||
// fetch("CYLON_TEST", "not set")
|
||||
// #=> "not set"
|
||||
//
|
||||
// process.env["CYLON_TEST"] #=> false
|
||||
// fetch("CYLON_TEST", true)
|
||||
// #=> false
|
||||
//
|
||||
// process.env["CYLON_TEST"] #=> true
|
||||
// fetch("CYLON_TEST", false)
|
||||
// #=> true
|
||||
//
|
||||
// Returns the env var or default value
|
||||
var fetch = function(variable, defaultValue) {
|
||||
if (defaultValue == null) {
|
||||
defaultValue = false;
|
||||
|
|
|
@ -15,10 +15,24 @@ var namespace = require('node-namespace');
|
|||
var EventEmitter = require('events').EventEmitter;
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
|
||||
|
||||
|
||||
// The Connection class represents the interface to
|
||||
// a specific group of hardware devices. Examples would be an
|
||||
// Arduino, a Sphero, or an ARDrone.
|
||||
namespace("Cylon", function() {
|
||||
this.Connection = (function(klass) {
|
||||
subclass(Connection, klass);
|
||||
|
||||
// Public: Creates a new Connection
|
||||
//
|
||||
// opts - hash of acceptable params:
|
||||
// id - string ID for the connection
|
||||
// robot - Robot the Connection belongs to
|
||||
// name - name for the connection
|
||||
// adaptor - string module name of the adaptor to be set up
|
||||
// port - string port to use for the Connection
|
||||
//
|
||||
// Returns the newly set-up connection
|
||||
function Connection(opts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
|
@ -36,6 +50,9 @@ namespace("Cylon", function() {
|
|||
proxyFunctionsToObject(this.adaptor.commands(), this.adaptor, this.self);
|
||||
}
|
||||
|
||||
// Public: Exports basic data for the Connection
|
||||
//
|
||||
// Returns an Object containing Connection data
|
||||
Connection.prototype.data = function() {
|
||||
return {
|
||||
name: this.name,
|
||||
|
@ -45,6 +62,11 @@ namespace("Cylon", function() {
|
|||
};
|
||||
};
|
||||
|
||||
// Public: Connect the adaptor's connection
|
||||
//
|
||||
// callback - callback function to run when the adaptor is connected
|
||||
//
|
||||
// Returns the result of the supplied callback function
|
||||
Connection.prototype.connect = function(callback) {
|
||||
var msg;
|
||||
msg = "Connecting to '" + this.name + "'";
|
||||
|
@ -55,6 +77,9 @@ namespace("Cylon", function() {
|
|||
return this.adaptor.connect(callback);
|
||||
};
|
||||
|
||||
// Public: Disconnect the adaptor's connection
|
||||
//
|
||||
// Returns nothing
|
||||
Connection.prototype.disconnect = function() {
|
||||
var msg;
|
||||
msg = "Disconnecting from '" + this.name + "'";
|
||||
|
@ -65,6 +90,12 @@ namespace("Cylon", function() {
|
|||
return this.adaptor.disconnect();
|
||||
};
|
||||
|
||||
// Public: sets up adaptor with @robot
|
||||
//
|
||||
// opts - options for adaptor being initialized
|
||||
// adaptor - name of the adaptor
|
||||
//
|
||||
// Returns the set-up adaptor
|
||||
Connection.prototype.initAdaptor = function(opts) {
|
||||
Logger.debug("Loading adaptor '" + opts.adaptor + "'");
|
||||
return this.robot.initAdaptor(opts.adaptor, this.self, opts);
|
||||
|
|
64
lib/cylon.js
64
lib/cylon.js
|
@ -9,6 +9,7 @@
|
|||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var Cylon,
|
||||
__slice = [].slice,
|
||||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
@ -25,6 +26,8 @@
|
|||
|
||||
Logger.setup();
|
||||
|
||||
// Cylon is the global namespace for the project, and also in charge of
|
||||
// maintaining the Master singleton that controls all the robots.
|
||||
Cylon = (function() {
|
||||
var Master, instance;
|
||||
|
||||
|
@ -32,6 +35,10 @@
|
|||
|
||||
instance = null;
|
||||
|
||||
// Public: Fetches singleton instance of Master, or creates a new one if it
|
||||
// doesn't already exist
|
||||
//
|
||||
// Returns a Master instance
|
||||
Cylon.getInstance = function() {
|
||||
var args;
|
||||
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
||||
|
@ -42,6 +49,8 @@
|
|||
})(Master, args, function(){});
|
||||
};
|
||||
|
||||
// The Master class is our puppeteer that manages all the robots, as well as
|
||||
// starting them and the API.
|
||||
Master = (function() {
|
||||
var api, api_config, robots;
|
||||
|
||||
|
@ -54,6 +63,9 @@
|
|||
port: '3000'
|
||||
};
|
||||
|
||||
// Public: Creates a new Master
|
||||
//
|
||||
// Returns a Master instance
|
||||
function Master() {
|
||||
this.robot = __bind(this.robot, this);
|
||||
var readLine, rl;
|
||||
|
@ -74,6 +86,18 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Public: Creates a new Robot
|
||||
//
|
||||
// opts - hash of Robot attributes
|
||||
//
|
||||
// Returns a shiny new Robot
|
||||
// Examples:
|
||||
// Cylon.robot
|
||||
// connection: { name: 'arduino', adaptor: 'firmata' }
|
||||
// device: { name: 'led', driver: 'led', pin: 13 }
|
||||
//
|
||||
// work: (me) ->
|
||||
// me.led.toggle()
|
||||
Master.prototype.robot = function(opts) {
|
||||
var Robot, robot;
|
||||
Robot = require("./robot");
|
||||
|
@ -83,10 +107,20 @@
|
|||
return robot;
|
||||
};
|
||||
|
||||
// Public: Returns all Robots the Master knows about
|
||||
//
|
||||
// Returns an array of all Robot instances
|
||||
Master.prototype.robots = function() {
|
||||
return robots;
|
||||
};
|
||||
|
||||
// Public: Configures the API host and port based on passed options
|
||||
//
|
||||
// opts - object containing API options
|
||||
// host - host address API should serve from
|
||||
// port - port API should listen for requests on
|
||||
//
|
||||
// Returns the API configuration
|
||||
Master.prototype.api = function(opts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
|
@ -96,6 +130,12 @@
|
|||
return api_config;
|
||||
};
|
||||
|
||||
// Public: Finds a particular robot by name
|
||||
//
|
||||
// name - name of the robot to find
|
||||
// callback - optional callback to be executed
|
||||
//
|
||||
// Returns the found Robot or result of the callback if it's supplied
|
||||
Master.prototype.findRobot = function(name, callback) {
|
||||
var bot, error, robot, _i, _len;
|
||||
robot = null;
|
||||
|
@ -117,6 +157,13 @@
|
|||
}
|
||||
};
|
||||
|
||||
// Public: Finds a particular Robot's device by name
|
||||
//
|
||||
// robotid - name of the robot to find
|
||||
// deviceid - name of the device to find
|
||||
// callback - optional callback to be executed
|
||||
//
|
||||
// Returns the found Device or result of the callback if it's supplied
|
||||
Master.prototype.findRobotDevice = function(robotid, deviceid, callback) {
|
||||
return this.findRobot(robotid, function(err, robot) {
|
||||
var device, error;
|
||||
|
@ -140,6 +187,13 @@
|
|||
});
|
||||
};
|
||||
|
||||
// Public: Finds a particular Robot's connection by name
|
||||
//
|
||||
// robotid - name of the robot to find
|
||||
// connid - name of the device to find
|
||||
// callback - optional callback to be executed
|
||||
//
|
||||
// Returns the found Connection or result of the callback if it's supplied
|
||||
Master.prototype.findRobotConnection = function(robotid, connid, callback) {
|
||||
return this.findRobot(robotid, function(err, robot) {
|
||||
var connection, error;
|
||||
|
@ -163,6 +217,9 @@
|
|||
});
|
||||
};
|
||||
|
||||
// Public: Starts up the API and the robots
|
||||
//
|
||||
// Returns nothing
|
||||
Master.prototype.start = function() {
|
||||
var robot, _i, _len, _results;
|
||||
this.startAPI();
|
||||
|
@ -174,6 +231,9 @@
|
|||
return _results;
|
||||
};
|
||||
|
||||
// Public: Stops the API and the robots
|
||||
//
|
||||
// Returns nothing
|
||||
Master.prototype.stop = function() {
|
||||
var robot, _i, _len, _results;
|
||||
_results = [];
|
||||
|
@ -184,6 +244,10 @@
|
|||
return _results;
|
||||
};
|
||||
|
||||
// Creates a new instance of the Cylon API server, or returns the
|
||||
// already-existing one.
|
||||
//
|
||||
// Returns an Cylon.ApiServer instance
|
||||
Master.prototype.startAPI = function() {
|
||||
var server;
|
||||
server = require('./api');
|
||||
|
|
|
@ -14,10 +14,23 @@ var namespace = require('node-namespace');
|
|||
var EventEmitter = require('events').EventEmitter;
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
|
||||
|
||||
// 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
|
||||
namespace("Cylon", function() {
|
||||
this.Device = (function(klass) {
|
||||
subclass(Device, klass);
|
||||
|
||||
// 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
|
||||
function Device(opts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
|
@ -33,6 +46,11 @@ namespace("Cylon", function() {
|
|||
proxyFunctionsToObject(this.driver.commands(), this.driver, this.self);
|
||||
}
|
||||
|
||||
// Public: Starts the device driver
|
||||
//
|
||||
// callback - callback function to be executed by the driver start
|
||||
//
|
||||
// Returns result of supplied callback
|
||||
Device.prototype.start = function(callback) {
|
||||
var msg;
|
||||
msg = "Starting device '" + this.name + "'";
|
||||
|
@ -43,11 +61,17 @@ namespace("Cylon", function() {
|
|||
return this.driver.start(callback);
|
||||
};
|
||||
|
||||
// Public: Stops the device driver
|
||||
//
|
||||
// Returns result of supplied callback
|
||||
Device.prototype.stop = function() {
|
||||
Logger.info("Stopping device '" + this.name + "'");
|
||||
return this.driver.stop();
|
||||
};
|
||||
|
||||
// Public: Exports basic data for the Connection
|
||||
//
|
||||
// Returns an Object containing Connection data
|
||||
Device.prototype.data = function() {
|
||||
return {
|
||||
name: this.name,
|
||||
|
@ -58,12 +82,20 @@ namespace("Cylon", function() {
|
|||
};
|
||||
};
|
||||
|
||||
// Public: Retrieves the connections from the parent Robot instances
|
||||
//
|
||||
// c - name of the connection to fetch
|
||||
//
|
||||
// Returns a Connection instance
|
||||
Device.prototype.determineConnection = function(c) {
|
||||
if (c) {
|
||||
return this.robot.connections[c];
|
||||
}
|
||||
};
|
||||
|
||||
// Public: Returns a default Connection to use
|
||||
//
|
||||
// Returns a Connection instance
|
||||
Device.prototype.defaultConnection = function() {
|
||||
var first, k, v, _ref;
|
||||
first = 0;
|
||||
|
@ -75,6 +107,12 @@ namespace("Cylon", function() {
|
|||
return first;
|
||||
};
|
||||
|
||||
// Public: sets up driver with @robot
|
||||
//
|
||||
// opts - object containing options when initializing driver
|
||||
// driver - name of the driver to intt()
|
||||
//
|
||||
// Returns the set-up driver
|
||||
Device.prototype.initDriver = function(opts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
|
|
|
@ -12,6 +12,8 @@ var FS = require('fs');
|
|||
var EventEmitter = require('events').EventEmitter;
|
||||
var namespace = require('node-namespace');
|
||||
|
||||
// DigitalPin class offers an interface with the Linux GPIO system present in
|
||||
// single-board computers such as a Raspberry Pi, or a BeagleBone
|
||||
namespace("Cylon.IO", function() {
|
||||
this.DigitalPin = (function(klass) {
|
||||
subclass(DigitalPin, klass);
|
||||
|
@ -74,6 +76,12 @@ namespace("Cylon.IO", function() {
|
|||
return value;
|
||||
};
|
||||
|
||||
// Public: Reads the digial pin's value periodicly on a supplied interval,
|
||||
// and emits the result or an error
|
||||
//
|
||||
// interval - time (in milliseconds) to read from the pin at
|
||||
//
|
||||
// Returns the defined interval
|
||||
DigitalPin.prototype.digitalRead = function(interval) {
|
||||
var readData,
|
||||
_this = this;
|
||||
|
@ -109,6 +117,7 @@ namespace("Cylon.IO", function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Creates the GPIO file to read/write from
|
||||
DigitalPin.prototype._createGPIOPin = function() {
|
||||
var _this = this;
|
||||
return FS.writeFile(this._exportPath(), "" + this.pinNum, function(err) {
|
||||
|
@ -133,6 +142,7 @@ namespace("Cylon.IO", function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Sets the mode for the GPIO pin by writing the correct values to the pin reference files
|
||||
DigitalPin.prototype._setMode = function(mode, emitConnect) {
|
||||
var _this = this;
|
||||
if (emitConnect == null) {
|
||||
|
|
|
@ -11,10 +11,20 @@
|
|||
require('./basestar');
|
||||
var namespace = require('node-namespace');
|
||||
|
||||
// The Driver class is a base class for Driver classes in external Cylon
|
||||
// modules to use. It offers basic functions for starting/stopping that
|
||||
// descendant classes can.
|
||||
namespace("Cylon", function() {
|
||||
this.Driver = (function(klass) {
|
||||
subclass(Driver, klass);
|
||||
|
||||
// Public: Creates a new Driver
|
||||
//
|
||||
// opts - hash of acceptable params
|
||||
// name - name of the Driver, used when printing to console
|
||||
// device - Device the driver will use to proxy commands/events
|
||||
//
|
||||
// Returns a new Driver
|
||||
function Driver(opts) {
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
|
@ -26,10 +36,19 @@ namespace("Cylon", function() {
|
|||
this.commandList = [];
|
||||
}
|
||||
|
||||
// Public: Exposes all commands the driver will respond to/proxy
|
||||
//
|
||||
// Returns an array of string method names
|
||||
Driver.prototype.commands = function() {
|
||||
return this.commandList;
|
||||
};
|
||||
|
||||
// Public: Starts up the driver, and emits 'connect' from the @device
|
||||
// when done.
|
||||
//
|
||||
// callback - function to run when the driver is started
|
||||
//
|
||||
// Returns nothing
|
||||
Driver.prototype.start = function(callback) {
|
||||
Logger.info("Driver " + this.name + " started");
|
||||
callback(null);
|
||||
|
@ -37,6 +56,9 @@ namespace("Cylon", function() {
|
|||
return true;
|
||||
};
|
||||
|
||||
// Public: Stops the driver
|
||||
//
|
||||
// Returns nothing
|
||||
Driver.prototype.stop = function() {
|
||||
return Logger.info("Driver " + this.name + " stopped");
|
||||
};
|
||||
|
|
|
@ -11,7 +11,17 @@
|
|||
var BasicLogger, NullLogger,
|
||||
__slice = [].slice;
|
||||
|
||||
// The Logger is a global object to facilitate logging stuff to the console (or
|
||||
// other output) easily and consistently. It's available anywhere in Cylon, as
|
||||
// well as in external modules that are loaded into Cylon
|
||||
global.Logger = {
|
||||
|
||||
// Public: Creates a Logger instance and assigns it to @logger
|
||||
//
|
||||
// logger - logger object to use. Defaults to a BasicLogger, or a NullLogger if
|
||||
// false is supplied
|
||||
//
|
||||
// Returns the new logger instance
|
||||
setup: function(logger) {
|
||||
if (logger == null) {
|
||||
logger = new BasicLogger;
|
||||
|
@ -48,6 +58,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
// The BasicLogger pushes stuff to console.log. Nothing more, nothing less.
|
||||
BasicLogger = (function() {
|
||||
function BasicLogger() {}
|
||||
|
||||
|
@ -89,6 +100,9 @@
|
|||
|
||||
})();
|
||||
|
||||
|
||||
// The NullLogger is designed for cases where you want absolutely nothing to
|
||||
// print to anywhere. Every proxied method from the Logger returns a noo
|
||||
NullLogger = (function() {
|
||||
function NullLogger() {}
|
||||
|
||||
|
|
19
lib/port.js
19
lib/port.js
|
@ -10,27 +10,42 @@
|
|||
|
||||
var namespace = require('node-namespace');
|
||||
|
||||
// The Port class represents a port and/or host to be used to connect to
|
||||
// a specific hardware device
|
||||
namespace("Cylon", function() {
|
||||
return this.Port = (function() {
|
||||
// Public: Creates a new Port based on a passed String representation
|
||||
//
|
||||
// data - string representation of the Port
|
||||
//
|
||||
// Returns a new Port
|
||||
function Port(data) {
|
||||
this.self = this;
|
||||
this.isTcp = this.isSerial = this.isPortless = false;
|
||||
this.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.
|
||||
Port.prototype.parse = function(data) {
|
||||
var match;
|
||||
if (data === void 0) {
|
||||
this.port = void 0;
|
||||
return this.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)) {
|
||||
this.port = match[2];
|
||||
this.host = match[1];
|
||||
return this.isTcp = true;
|
||||
// is it a numeric port for localhost tcp?
|
||||
} else if (/^[0-9]{1,5}$/.exec(data)) {
|
||||
this.port = data;
|
||||
this.host = "localhost";
|
||||
return this.isTcp = true;
|
||||
// must be a serial port
|
||||
} else {
|
||||
this.port = data;
|
||||
this.host = void 0;
|
||||
|
@ -38,6 +53,10 @@ namespace("Cylon", function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Public: Returns a string representation of the port that can be used to
|
||||
// connect to it.
|
||||
//
|
||||
// Returns a string
|
||||
Port.prototype.toString = function() {
|
||||
if (this.isPortless) {
|
||||
return "none";
|
||||
|
|
99
lib/robot.js
99
lib/robot.js
|
@ -23,10 +23,35 @@ var EventEmitter = require('events').EventEmitter;
|
|||
|
||||
var namespace = require('node-namespace');
|
||||
|
||||
// A Robot is the primary interface for interacting with a collection of physical
|
||||
// computing capabilities.
|
||||
namespace("Cylon", function() {
|
||||
this.Robot = (function(klass) {
|
||||
subclass(Robot, klass);
|
||||
|
||||
// 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//
|
||||
function Robot(opts) {
|
||||
var func, n, reserved;
|
||||
if (opts == null) {
|
||||
|
@ -70,10 +95,16 @@ namespace("Cylon", function() {
|
|||
}
|
||||
}
|
||||
|
||||
// Public: Generates a random name for a Robot.
|
||||
//
|
||||
// Returns a string name
|
||||
Robot.randomName = function() {
|
||||
return "Robot " + (Math.floor(Math.random() * 100000));
|
||||
};
|
||||
|
||||
// Public: Exports basic data for the Robot
|
||||
//
|
||||
// Returns an Object containing Robot data
|
||||
Robot.prototype.data = function() {
|
||||
var connection, device, n;
|
||||
return {
|
||||
|
@ -102,6 +133,11 @@ namespace("Cylon", function() {
|
|||
};
|
||||
};
|
||||
|
||||
// Public: Initializes all connections for the robot
|
||||
//
|
||||
// connections - connections to initialize
|
||||
//
|
||||
// Returns initialized connections
|
||||
Robot.prototype.initConnections = function(connections) {
|
||||
var connection, _i, _len;
|
||||
Logger.info("Initializing connections...");
|
||||
|
@ -118,6 +154,11 @@ namespace("Cylon", function() {
|
|||
return this.connections;
|
||||
};
|
||||
|
||||
// Public: Initializes all devices for the robot
|
||||
//
|
||||
// devices - devices to initialize
|
||||
//
|
||||
// Returns initialized devices
|
||||
Robot.prototype.initDevices = function(devices) {
|
||||
var device, _i, _len, _results;
|
||||
Logger.info("Initializing devices...");
|
||||
|
@ -135,6 +176,11 @@ namespace("Cylon", function() {
|
|||
return _results;
|
||||
};
|
||||
|
||||
// Public: Starts the Robot working.
|
||||
//
|
||||
// Starts the connections, devices, and work.
|
||||
//
|
||||
// Returns the result of the work
|
||||
Robot.prototype.start = function() {
|
||||
var _this = this;
|
||||
return this.startConnections(function() {
|
||||
|
@ -147,6 +193,11 @@ namespace("Cylon", function() {
|
|||
});
|
||||
};
|
||||
|
||||
// Public: Starts the Robot's connections and triggers a callback
|
||||
//
|
||||
// callback - callback function to be triggered
|
||||
//
|
||||
// Returns nothing
|
||||
Robot.prototype.startConnections = function(callback) {
|
||||
var connection, n, starters, _ref;
|
||||
Logger.info("Starting connections...");
|
||||
|
@ -160,6 +211,11 @@ namespace("Cylon", function() {
|
|||
return Async.parallel(starters, callback);
|
||||
};
|
||||
|
||||
// Public: Starts the Robot's devices and triggers a callback
|
||||
//
|
||||
// callback - callback function to be triggered
|
||||
//
|
||||
// Returns nothing
|
||||
Robot.prototype.startDevices = function(callback) {
|
||||
var device, n, starters, _ref;
|
||||
Logger.info("Starting devices...");
|
||||
|
@ -173,6 +229,11 @@ namespace("Cylon", function() {
|
|||
return Async.parallel(starters, callback);
|
||||
};
|
||||
|
||||
// Public: Stops the Robot working.
|
||||
//
|
||||
// Stops the devices, disconnects the connections.
|
||||
//
|
||||
// Returns nothing
|
||||
Robot.prototype.stop = function() {
|
||||
var connection, device, n, _ref, _ref1, _results;
|
||||
_ref = this.devices;
|
||||
|
@ -189,6 +250,12 @@ namespace("Cylon", function() {
|
|||
return _results;
|
||||
};
|
||||
|
||||
// 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 adaptor
|
||||
Robot.prototype.initAdaptor = function(adaptorName, connection, opts) {
|
||||
var realAdaptor, testAdaptor;
|
||||
if (opts == null) {
|
||||
|
@ -211,6 +278,11 @@ namespace("Cylon", function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Public: Requires a hardware adaptor and adds it to @robot.adaptors
|
||||
//
|
||||
// adaptorName - module name of adaptor to require
|
||||
//
|
||||
// Returns the module for the adaptor
|
||||
Robot.prototype.requireAdaptor = function(adaptorName) {
|
||||
if (this.robot.adaptors[adaptorName] == null) {
|
||||
this.robot.registerAdaptor("cylon-" + adaptorName, adaptorName);
|
||||
|
@ -219,12 +291,25 @@ namespace("Cylon", function() {
|
|||
return this.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
|
||||
Robot.prototype.registerAdaptor = function(moduleName, adaptorName) {
|
||||
if (this.adaptors[adaptorName] == null) {
|
||||
return this.adaptors[adaptorName] = require(moduleName);
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
Robot.prototype.initDriver = function(driverName, device, opts) {
|
||||
var realDriver, testDriver;
|
||||
if (opts == null) {
|
||||
|
@ -247,6 +332,11 @@ namespace("Cylon", function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Public: Requires module for a driver and adds it to @robot.drivers
|
||||
//
|
||||
// driverName - module name of driver to require
|
||||
//
|
||||
// Returns the module for driver
|
||||
Robot.prototype.requireDriver = function(driverName) {
|
||||
if (this.robot.drivers[driverName] == null) {
|
||||
this.robot.registerDriver("cylon-" + driverName, driverName);
|
||||
|
@ -255,12 +345,21 @@ namespace("Cylon", function() {
|
|||
return this.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 nam//
|
||||
Robot.prototype.registerDriver = function(moduleName, driverName) {
|
||||
if (this.drivers[driverName] == null) {
|
||||
return this.drivers[driverName] = require(moduleName);
|
||||
}
|
||||
};
|
||||
|
||||
// Public: Returns basic info about the robot as a String
|
||||
//
|
||||
// Returns a String
|
||||
Robot.prototype.toString = function() {
|
||||
return "[Robot name='" + this.name + "']";
|
||||
};
|
||||
|
|
110
lib/utils.js
110
lib/utils.js
|
@ -10,18 +10,53 @@
|
|||
(function() {
|
||||
var __slice = [].slice;
|
||||
|
||||
// Public: Alias to setInterval, combined with Number monkeypatches below to
|
||||
// create an artoo-like syntax.
|
||||
//
|
||||
// interval - interval to run action on
|
||||
// action - action to perform at interval
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// every 5.seconds(), -> console.log("hello world (and again in 5 seconds)!")
|
||||
//
|
||||
// Returns an interval
|
||||
global.every = function(interval, action) {
|
||||
return setInterval(action, interval);
|
||||
};
|
||||
|
||||
// Public: Alias to setTimeout, combined with Number monkeypatches below to
|
||||
// create an artoo-like syntax.
|
||||
//
|
||||
// interval - interval to run action on
|
||||
// action - action to perform at interval
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// after 10.seconds(), -> console.log("hello world from ten seconds ago!")
|
||||
//
|
||||
// Returns an interval
|
||||
global.after = function(delay, action) {
|
||||
return setTimeout(action, delay);
|
||||
};
|
||||
|
||||
// Public: Alias to the `every` function, but passing 0
|
||||
// Examples
|
||||
//
|
||||
// constantly -> console.log("hello world (and again and again)!")
|
||||
//
|
||||
// Returns an interval
|
||||
global.constantly = function(action) {
|
||||
return every(0, action);
|
||||
};
|
||||
|
||||
// Public: Sleep - do nothing for some duration of time.
|
||||
//
|
||||
// ms - number of ms to sleep for
|
||||
//
|
||||
// Returns a function
|
||||
// Examples:
|
||||
// sleep 1.second()
|
||||
global.sleep = function(ms) {
|
||||
var i, start, _results;
|
||||
start = Date.now();
|
||||
|
@ -36,6 +71,18 @@
|
|||
|
||||
global.hasProp = {}.hasOwnProperty;
|
||||
|
||||
// Public: Function to use for class inheritance. Copy of a CoffeeScript helper
|
||||
// function.
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// var Sphero = (function(klass) {
|
||||
// subclass(Sphero, klass);
|
||||
// // Sphero is now a subclass of Parent, and can access it's methods through
|
||||
// // Sphero.__super__
|
||||
// })(Parent);
|
||||
//
|
||||
// Returns subclass
|
||||
global.subclass = function(child, parent) {
|
||||
var ctor, key;
|
||||
ctor = function() {
|
||||
|
@ -52,6 +99,16 @@
|
|||
return child;
|
||||
};
|
||||
|
||||
// Public: Proxies a list of methods from one object to another. It will not
|
||||
// overwrite existing methods unless told to.
|
||||
//
|
||||
// methods - array of functions to proxy
|
||||
// target - object to proxy the functions to
|
||||
// base - (optional) object that proxied functions will be declared on. Defaults
|
||||
// to this
|
||||
// force - (optional) boolean - whether or not to force method assignment
|
||||
//
|
||||
// Returns base
|
||||
global.proxyFunctionsToObject = function(methods, target, base, force) {
|
||||
var method, _fn, _i, _len;
|
||||
if (base == null) {
|
||||
|
@ -79,6 +136,13 @@
|
|||
return base;
|
||||
};
|
||||
|
||||
// Public: Proxies a list of methods for test stubbing.
|
||||
//
|
||||
// methods - array of functions to proxy
|
||||
// base - (optional) object that proxied functions will be declared on. Defaults
|
||||
// to this
|
||||
//
|
||||
// Returns base
|
||||
global.proxyTestStubs = function(methods, base) {
|
||||
var method, _i, _len;
|
||||
if (base == null) {
|
||||
|
@ -96,18 +160,64 @@
|
|||
return base;
|
||||
};
|
||||
|
||||
// Public: Monkey-patches Number to have Rails-like #seconds() function. Warning,
|
||||
// due to the way the Javascript parser works, applying functions on numbers is
|
||||
// kind of weird. See examples for details.
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// 2.seconds()
|
||||
// #=> SyntaxError: Unexpected token ILLEGAL
|
||||
//
|
||||
// 10..seconds()
|
||||
// #=> 10000
|
||||
//
|
||||
// (5).seconds()
|
||||
// #=> 5000
|
||||
//
|
||||
// Returns an integer representing time in milliseconds
|
||||
Number.prototype.seconds = function() {
|
||||
return this * 1000;
|
||||
};
|
||||
|
||||
// Public: Alias for Number::seconds, see comments for that method
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// 1.second()
|
||||
// #=> 1000
|
||||
//
|
||||
// Returns an integer representing time in milliseconds
|
||||
Number.prototype.second = function() {
|
||||
return this.seconds(this);
|
||||
};
|
||||
|
||||
// Public: Convert value from old scale (start, end) to (0..1) scale
|
||||
//
|
||||
// start - low point of scale to convert value from
|
||||
// end - high point of scale to convert value from
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// 5..fromScale(0, 10)
|
||||
// #=> 0.5
|
||||
//
|
||||
// Returns an integer representing the scaled value
|
||||
Number.prototype.fromScale = function(start, end) {
|
||||
return (this - Math.min(start, end)) / (Math.max(start, end) - Math.min(start, end));
|
||||
};
|
||||
|
||||
// Public: Convert value from (0..1) scale to new (start, end) scale
|
||||
//
|
||||
// start - low point of scale to convert value to
|
||||
// end - high point of scale to convert value to
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// 0.5.toScale(0, 10)
|
||||
// #=> 5
|
||||
//
|
||||
// Returns an integer representing the scaled value
|
||||
Number.prototype.toScale = function(start, end) {
|
||||
return Math.ceil(this * (Math.max(start, end) - Math.min(start, end)) + Math.min(start, end));
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue