Merge branch 'master' into literate-coffeescript
* master: (21 commits) Removes unnecessary IO class. Fixes raspi button example typo. Updated DigitalPin and raspi_button example. Adding interval reads to digitalRead. Added new Digital read example for raspi, updated digitalRead in lib. Refactored DigitalRead and setup mode to only emit connection event on connect. Added new DigitalPin to Cylon core to use in adaptors, for real. Added new DigitalPin to Cylon core to use in adaptors. Added new example for raspi adaptor. Updated digital pin lib and example. Fixed missing mode variable in digital pin. Remove logging and update example. Change events and update example in digital pin. Added close for GPIO and updated negative ifs Change event triggers in callbacks to fat arrows to keep obj scope. Removed self and changed example. Updated IO and digital pin to use events. Fix bug in GPIO example. Adde pure GPIO example and updated digital pin lib Added new LinuxIO DigitalPin library. ...
This commit is contained in:
commit
7543f834e4
|
@ -9,7 +9,7 @@
|
|||
|
||||
(function() {
|
||||
'use strict';
|
||||
var Cylon, Robot,
|
||||
var Cylon, Robot, readLine,
|
||||
__slice = [].slice,
|
||||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
|||
|
||||
require('./api');
|
||||
|
||||
readLine = require("readline");
|
||||
|
||||
Logger.setup();
|
||||
|
||||
Cylon = (function() {
|
||||
|
@ -49,7 +51,21 @@
|
|||
|
||||
function Master() {
|
||||
this.robot = __bind(this.robot, this);
|
||||
var rl;
|
||||
this.self = this;
|
||||
if (process.platform === "win32") {
|
||||
rl = readLine.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
rl.on("SIGINT", function() {
|
||||
return process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
process.on("SIGINT", function() {
|
||||
Cylon.getInstance().stop();
|
||||
return process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
Master.prototype.robot = function(opts) {
|
||||
|
@ -140,6 +156,16 @@
|
|||
return _results;
|
||||
};
|
||||
|
||||
Master.prototype.stop = function() {
|
||||
var robot, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = robots.length; _i < _len; _i++) {
|
||||
robot = robots[_i];
|
||||
_results.push(robot.stop());
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
Master.prototype.startAPI = function() {
|
||||
return api != null ? api : api = new Api.Server({
|
||||
master: this.self
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
this.stop = __bind(this.stop, this);
|
||||
this.start = __bind(this.start, this);
|
||||
this.self = this;
|
||||
this.robot = opts.robot;
|
||||
|
@ -48,6 +49,11 @@
|
|||
return this.driver.start(callback);
|
||||
};
|
||||
|
||||
Device.prototype.stop = function() {
|
||||
Logger.info("Stopping device '" + this.name + "'");
|
||||
return this.driver.stop();
|
||||
};
|
||||
|
||||
Device.prototype.data = function() {
|
||||
return {
|
||||
name: this.name,
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Linux IO DigitalPin
|
||||
* cylonjs.com
|
||||
*
|
||||
* Copyright (c) 2013 The Hybrid Group
|
||||
* Licensed under the Apache 2.0 license.
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
var EventEmitter, FS, namespace,
|
||||
__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; };
|
||||
|
||||
FS = require('fs');
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
namespace = require('node-namespace');
|
||||
|
||||
namespace('Cylon.IO', function() {
|
||||
return this.DigitalPin = (function(_super) {
|
||||
var GPIO_DIRECTION_READ, GPIO_DIRECTION_WRITE, GPIO_PATH, HIGH, LOW;
|
||||
|
||||
__extends(DigitalPin, _super);
|
||||
|
||||
GPIO_PATH = "/sys/class/gpio";
|
||||
|
||||
GPIO_DIRECTION_READ = "in";
|
||||
|
||||
GPIO_DIRECTION_WRITE = "out";
|
||||
|
||||
HIGH = 1;
|
||||
|
||||
LOW = 0;
|
||||
|
||||
function DigitalPin(opts) {
|
||||
this.self = this;
|
||||
this.pinNum = opts.pin;
|
||||
this.status = 'low';
|
||||
this.ready = false;
|
||||
this.mode = opts.mode;
|
||||
}
|
||||
|
||||
DigitalPin.prototype.connect = function(mode) {
|
||||
var _this = this;
|
||||
if (mode == null) {
|
||||
mode = null;
|
||||
}
|
||||
if (this.mode == null) {
|
||||
this.mode = mode;
|
||||
}
|
||||
return FS.writeFile("" + GPIO_PATH + "/export", "" + this.pinNum, function(err) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', 'Error while creating pin files');
|
||||
} else {
|
||||
_this.self._setMode(_this.mode, true);
|
||||
return _this.self.emit('open');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
DigitalPin.prototype.close = function() {
|
||||
var _this = this;
|
||||
return FS.writeFile("" + GPIO_PATH + "/unexport", "" + this.pinNum, function(err) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', 'Error while closing pin files');
|
||||
} else {
|
||||
return _this.self.emit('close');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
DigitalPin.prototype.digitalWrite = function(value) {
|
||||
var _this = this;
|
||||
if (this.mode !== 'w') {
|
||||
this.self._setMode('w');
|
||||
}
|
||||
this.status = value === 1 ? 'high' : 'low';
|
||||
return FS.writeFile(this.pinFile, value, function(err) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', "Error occurred while writing value " + value + " to pin " + _this.pinNum);
|
||||
} else {
|
||||
return _this.self.emit('digitalWrite', value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
DigitalPin.prototype.digitalRead = function(interval) {
|
||||
var readData,
|
||||
_this = this;
|
||||
if (this.mode !== 'r') {
|
||||
this.self._setMode('r');
|
||||
}
|
||||
readData = null;
|
||||
return setInterval(function() {
|
||||
return FS.readFile(_this.pinFile, function(err, data) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', "Error occurred while reading from pin " + _this.pinNum);
|
||||
} else {
|
||||
readData = data;
|
||||
return _this.self.emit('digitalRead', data);
|
||||
}
|
||||
});
|
||||
}, interval);
|
||||
};
|
||||
|
||||
DigitalPin.prototype._setMode = function(mode, emitConnect) {
|
||||
var _this = this;
|
||||
if (emitConnect == null) {
|
||||
emitConnect = false;
|
||||
}
|
||||
if (mode === 'w') {
|
||||
return FS.writeFile("" + GPIO_PATH + "/gpio" + this.pinNum + "/direction", GPIO_DIRECTION_WRITE, function(err) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', "Setting up pin direction failed");
|
||||
} else {
|
||||
_this.pinFile = "" + GPIO_PATH + "/gpio" + _this.pinNum + "/value";
|
||||
_this.ready = true;
|
||||
if (emitConnect) {
|
||||
return _this.self.emit('connect', mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (mode === 'r') {
|
||||
return FS.writeFile("" + GPIO_PATH + "/gpio" + this.pinNum + "/direction", GPIO_DIRECTION_READ, function(err) {
|
||||
if (err) {
|
||||
return _this.self.emit('error', "Setting up pin direction failed");
|
||||
} else {
|
||||
_this.pinFile = "" + GPIO_PATH + "/gpio" + _this.pinNum + "/value";
|
||||
_this.ready = true;
|
||||
if (emitConnect) {
|
||||
return _this.self.emit('connect', mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DigitalPin.prototype.setHigh = function() {
|
||||
return this.self.digitalWrite(1);
|
||||
};
|
||||
|
||||
DigitalPin.prototype.setLow = function() {
|
||||
return this.self.digitalWrite(0);
|
||||
};
|
||||
|
||||
DigitalPin.prototype.toggle = function() {
|
||||
if (this.status === 'low') {
|
||||
return this.self.setHigh();
|
||||
} else {
|
||||
return this.self.setLow();
|
||||
}
|
||||
};
|
||||
|
||||
return DigitalPin;
|
||||
|
||||
})(EventEmitter);
|
||||
});
|
||||
|
||||
}).call(this);
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
require('./basestar');
|
||||
|
||||
require('./digital-pin');
|
||||
|
||||
namespace = require('node-namespace');
|
||||
|
||||
Connection = require("./connection");
|
||||
|
@ -37,6 +39,7 @@
|
|||
opts = {};
|
||||
}
|
||||
this.registerDriver = __bind(this.registerDriver, this);
|
||||
this.stop = __bind(this.stop, this);
|
||||
this.startDevices = __bind(this.startDevices, this);
|
||||
this.startConnections = __bind(this.startConnections, this);
|
||||
this.start = __bind(this.start, this);
|
||||
|
@ -163,6 +166,22 @@
|
|||
return Async.parallel(starters, callback);
|
||||
};
|
||||
|
||||
Robot.prototype.stop = function() {
|
||||
var connection, device, n, _ref, _ref1, _results;
|
||||
_ref = this.devices;
|
||||
for (n in _ref) {
|
||||
device = _ref[n];
|
||||
device.stop();
|
||||
}
|
||||
_ref1 = this.connections;
|
||||
_results = [];
|
||||
for (n in _ref1) {
|
||||
connection = _ref1[n];
|
||||
_results.push(connection.disconnect());
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
Robot.prototype.requireAdaptor = function(adaptorName, connection) {
|
||||
if (this.robot.adaptors[adaptorName] != null) {
|
||||
if (typeof this.robot.adaptors[adaptorName] === 'string') {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
require('../dist/digital-pin')
|
||||
|
||||
pin4 = new Cylon.IO.DigitalPin(pin: 4, mode: 'w')
|
||||
|
||||
pin4.on('open', (data) ->
|
||||
console.log("Pin files have been created")
|
||||
)
|
||||
|
||||
pin4.on('digitalWrite', (value) ->
|
||||
console.log("Value writen to pin -> #{ value }")
|
||||
)
|
||||
|
||||
pin4.on('connect', (data) ->
|
||||
console.log("Pin mode has been setup!")
|
||||
pin4.setHigh()
|
||||
)
|
||||
|
||||
pin4.connect()
|
|
@ -0,0 +1,15 @@
|
|||
Cylon = require('..')
|
||||
|
||||
# Initialize the robot
|
||||
Cylon.robot
|
||||
connection:
|
||||
name: 'raspi', adaptor: 'raspi'
|
||||
|
||||
device:
|
||||
name: 'led', driver: 'led', pin: 11
|
||||
|
||||
work: (my) ->
|
||||
# we do our thing here
|
||||
every 1.second(), -> my.led.toggle()
|
||||
|
||||
.start()
|
|
@ -0,0 +1,17 @@
|
|||
Cylon = require('..')
|
||||
|
||||
# Initialize the robot
|
||||
Cylon.robot
|
||||
connection:
|
||||
name: 'raspi', adaptor: 'raspi'
|
||||
|
||||
devices:
|
||||
[
|
||||
{name: 'led', driver: 'led', pin: 11},
|
||||
{name: 'button', driver: 'button', pin: 7}
|
||||
]
|
||||
|
||||
work: (my) ->
|
||||
my.button.on 'push', () -> my.led.toggle()
|
||||
|
||||
.start()
|
|
@ -14,6 +14,8 @@ require('./utils')
|
|||
require('./logger')
|
||||
require('./api')
|
||||
|
||||
readLine = require "readline"
|
||||
|
||||
Logger.setup()
|
||||
|
||||
# Cylon is the global namespace for the project, and also in charge of
|
||||
|
@ -39,6 +41,17 @@ class Cylon
|
|||
# Returns a Master instance
|
||||
constructor: ->
|
||||
@self = this
|
||||
if process.platform is "win32"
|
||||
rl = readLine.createInterface
|
||||
input: process.stdin
|
||||
output: process.stdout
|
||||
|
||||
rl.on "SIGINT", ->
|
||||
process.emit "SIGINT"
|
||||
|
||||
process.on "SIGINT", ->
|
||||
Cylon.getInstance().stop()
|
||||
process.exit()
|
||||
|
||||
# Public: Creates a new Robot
|
||||
#
|
||||
|
@ -119,6 +132,15 @@ class Cylon
|
|||
do @startAPI
|
||||
robot.start() for robot in robots
|
||||
|
||||
|
||||
# Public: Stops the API and the robots
|
||||
#
|
||||
# Returns nothing
|
||||
stop: ->
|
||||
#do @stopAPI
|
||||
robot.stop() for robot in robots
|
||||
|
||||
|
||||
# Creates a new instance of the Cylon API server, or returns the
|
||||
# already-existing one.
|
||||
#
|
||||
|
|
|
@ -48,6 +48,13 @@ namespace 'Cylon', ->
|
|||
Logger.info msg
|
||||
@driver.start(callback)
|
||||
|
||||
# Public: Stops the device driver
|
||||
#
|
||||
# Returns result of supplied callback
|
||||
stop: =>
|
||||
Logger.info "Stopping device '#{ @name }'"
|
||||
@driver.stop()
|
||||
|
||||
# Public: Exports basic data for the Connection
|
||||
#
|
||||
# Returns an Object containing Connection data
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
###
|
||||
* Linux IO DigitalPin
|
||||
* cylonjs.com
|
||||
*
|
||||
* Copyright (c) 2013 The Hybrid Group
|
||||
* Licensed under the Apache 2.0 license.
|
||||
###
|
||||
|
||||
'use strict';
|
||||
|
||||
FS = require('fs')
|
||||
EventEmitter = require('events').EventEmitter
|
||||
|
||||
namespace = require 'node-namespace'
|
||||
|
||||
# DigitalPin class to interface with linux GPIO in raspi and beaglebone
|
||||
#
|
||||
namespace 'Cylon.IO', ->
|
||||
class @DigitalPin extends EventEmitter
|
||||
|
||||
GPIO_PATH = "/sys/class/gpio"
|
||||
GPIO_DIRECTION_READ = "in"
|
||||
GPIO_DIRECTION_WRITE = "out"
|
||||
HIGH = 1
|
||||
LOW = 0
|
||||
|
||||
constructor: (opts) ->
|
||||
@self = this
|
||||
@pinNum = opts.pin
|
||||
@status = 'low'
|
||||
@ready = false
|
||||
@mode = opts.mode
|
||||
|
||||
connect: (mode = null) ->
|
||||
@mode ?= mode
|
||||
# Creates the GPIO file to read/write from
|
||||
FS.writeFile("#{ GPIO_PATH }/export", "#{ @pinNum }", (err) =>
|
||||
if(err)
|
||||
@self.emit('error', 'Error while creating pin files')
|
||||
else
|
||||
@self._setMode(@mode, true)
|
||||
@self.emit('open')
|
||||
)
|
||||
|
||||
|
||||
close: ->
|
||||
FS.writeFile("#{ GPIO_PATH }/unexport", "#{ @pinNum }", (err) =>
|
||||
if(err)
|
||||
@self.emit('error', 'Error while closing pin files')
|
||||
else
|
||||
@self.emit('close')
|
||||
)
|
||||
|
||||
digitalWrite: (value) ->
|
||||
@self._setMode('w') unless @mode == 'w'
|
||||
@status = if (value == 1) then 'high' else 'low'
|
||||
|
||||
FS.writeFile(@pinFile, value, (err) =>
|
||||
if (err)
|
||||
@self.emit('error', "Error occurred while writing value #{ value } to pin #{ @pinNum }")
|
||||
else
|
||||
@self.emit('digitalWrite', value)
|
||||
)
|
||||
|
||||
digitalRead: (interval) ->
|
||||
@self._setMode('r') unless @mode == 'r'
|
||||
readData = null
|
||||
|
||||
setInterval(() =>
|
||||
FS.readFile(@pinFile, (err, data) =>
|
||||
if err
|
||||
@self.emit('error', "Error occurred while reading from pin #{ @pinNum }")
|
||||
else
|
||||
readData = data
|
||||
@self.emit('digitalRead', data)
|
||||
)
|
||||
, interval)
|
||||
|
||||
# Sets the mode for the GPIO pin by writing the correct values to the pin reference files
|
||||
_setMode: (mode, emitConnect = false) ->
|
||||
if mode == 'w'
|
||||
FS.writeFile("#{ GPIO_PATH }/gpio#{ @pinNum }/direction", GPIO_DIRECTION_WRITE, (err) =>
|
||||
if (err)
|
||||
@self.emit('error', "Setting up pin direction failed")
|
||||
else
|
||||
@pinFile = "#{ GPIO_PATH }/gpio#{ @pinNum }/value"
|
||||
@ready = true
|
||||
@self.emit('connect', mode) if emitConnect
|
||||
)
|
||||
else if mode =='r'
|
||||
FS.writeFile("#{ GPIO_PATH }/gpio#{ @pinNum }/direction", GPIO_DIRECTION_READ, (err) =>
|
||||
if (err)
|
||||
@self.emit('error', "Setting up pin direction failed")
|
||||
else
|
||||
@pinFile = "#{ GPIO_PATH }/gpio#{ @pinNum }/value"
|
||||
@ready = true
|
||||
@self.emit('connect', mode) if emitConnect
|
||||
)
|
||||
|
||||
setHigh: ->
|
||||
@self.digitalWrite(1)
|
||||
|
||||
setLow: ->
|
||||
@self.digitalWrite(0)
|
||||
|
||||
toggle: ->
|
||||
if @status == 'low'
|
||||
@self.setHigh()
|
||||
else
|
||||
@self.setLow()
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
require './cylon'
|
||||
require './basestar'
|
||||
require './digital-pin'
|
||||
|
||||
namespace = require 'node-namespace'
|
||||
|
||||
|
@ -149,6 +150,18 @@ namespace 'Cylon', ->
|
|||
|
||||
Async.parallel starters, callback
|
||||
|
||||
# Public: Stops the Robot working.
|
||||
#
|
||||
# Stops the devices, disconnects the connections.
|
||||
#
|
||||
# Returns nothing
|
||||
stop: =>
|
||||
for n, device of @devices
|
||||
device.stop()
|
||||
|
||||
for n, connection of @connections
|
||||
connection.disconnect()
|
||||
|
||||
# Public: Requires a hardware adaptor and adds it to @robot.adaptors
|
||||
#
|
||||
# adaptorName - module name of adaptor to require
|
||||
|
|
Loading…
Reference in New Issue