cylon/lib/digital-pin.js

184 lines
4.9 KiB
JavaScript
Raw Normal View History

/*
* Linux IO DigitalPin
* cylonjs.com
*
2014-02-28 03:28:13 +08:00
* Copyright (c) 2013-2014 The Hybrid Group
* Licensed under the Apache 2.0 license.
*/
"use strict";
2014-02-28 03:28:13 +08:00
var FS = require('fs'),
EventEmitter = require('events').EventEmitter,
namespace = require('node-namespace');
2014-02-28 03:28:13 +08:00
2014-02-28 06:42:33 +08:00
// DigitalPin class offers an interface with the Linux GPIO system present in
// single-board computers such as a Raspberry Pi, or a BeagleBone
2014-02-28 03:28:13 +08:00
namespace("Cylon.IO", function() {
this.DigitalPin = (function(klass) {
subclass(DigitalPin, klass);
var GPIO_PATH = "/sys/class/gpio";
2014-02-28 03:28:13 +08:00
var GPIO_READ = "in";
var GPIO_WRITE = "out";
2014-02-28 03:28:13 +08:00
var HIGH = 1;
var LOW = 0;
function DigitalPin(opts) {
this.pinNum = opts.pin;
this.status = 'low';
this.ready = false;
this.mode = opts.mode;
}
DigitalPin.prototype.connect = function(mode) {
var self = this;
if (this.mode == null) { this.mode = mode; }
FS.exists(this._pinPath(), function(exists) {
exists ? self._openPin() : self._createGPIOPin();
2014-02-28 03:28:13 +08:00
});
};
DigitalPin.prototype.close = function() {
var self = this,
num = this.pinNum.toString();
FS.writeFile(this._unexportPath(), num, function(err) {
self._closeCallback(err);
2014-02-28 03:28:13 +08:00
});
};
DigitalPin.prototype.closeSync = function() {
var num = this.pinNum.toString();
FS.writeFileSync(this._unexportPath(), num);
this._closeCallback(false);
2014-02-28 03:28:13 +08:00
};
DigitalPin.prototype.digitalWrite = function(value) {
if (this.mode !== 'w') { this._setMode('w'); }
var self = this;
2014-02-28 03:28:13 +08:00
this.status = value === 1 ? 'high' : 'low';
2014-02-28 03:28:13 +08:00
FS.writeFile(this._valuePath(), value, function(err) {
if (err) {
self.emit('error', "Error occurred while writing value " + value + " to pin " + self.pinNum);
2013-11-13 01:47:25 +08:00
} else {
self.emit('digitalWrite', value);
2013-11-13 01:47:25 +08:00
}
2014-02-28 03:28:13 +08:00
});
2014-02-28 03:28:13 +08:00
return value;
};
2014-02-28 06:42:33 +08:00
// 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
2014-02-28 03:28:13 +08:00
DigitalPin.prototype.digitalRead = function(interval) {
var self = this;
if (this.mode !== 'r') { this._setMode('r'); }
every(interval, function() {
FS.readFile(self._valuePath(), function(err, data) {
2013-11-13 01:47:25 +08:00
if (err) {
var error = "Error occurred while reading from pin " + self.pinNum;
self.emit('error', error);
2013-11-13 01:47:25 +08:00
} else {
var readData = parseInt(data.toString());
self.emit('digitalRead', readData);
2013-11-13 01:47:25 +08:00
}
});
2014-02-28 03:28:13 +08:00
});
};
DigitalPin.prototype.setHigh = function() { return this.digitalWrite(1); };
DigitalPin.prototype.setLow = function() { return this.digitalWrite(0); };
2014-02-28 03:28:13 +08:00
DigitalPin.prototype.toggle = function() {
return (this.status === 'low') ? this.setHigh() : this.setLow();
2014-02-28 03:28:13 +08:00
};
2013-11-13 01:47:25 +08:00
2014-02-28 06:42:33 +08:00
// Creates the GPIO file to read/write from
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._createGPIOPin = function() {
var self = this,
num = this.pinNum.toString();
FS.writeFile(this._exportPath(), num, function(err) {
2013-11-13 01:47:25 +08:00
if (err) {
self.emit('error', 'Error while creating pin files');
2013-11-13 01:47:25 +08:00
} else {
self._openPin();
2013-11-13 01:47:25 +08:00
}
2014-02-28 03:28:13 +08:00
});
};
DigitalPin.prototype._openPin = function() {
this._setMode(this.mode, true);
this.emit('open');
2014-02-28 03:28:13 +08:00
};
DigitalPin.prototype._closeCallback = function(err) {
if (err) {
this.emit('error', 'Error while closing pin files');
2014-02-28 03:28:13 +08:00
} else {
this.emit('close', this.pinNum);
2014-02-28 03:28:13 +08:00
}
};
2013-11-12 03:44:48 +08:00
2014-02-28 06:42:33 +08:00
// Sets the mode for the GPIO pin by writing the correct values to the pin reference files
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._setMode = function(mode, emitConnect) {
if (emitConnect == null) { emitConnect = false; }
2014-02-28 03:28:13 +08:00
this.mode = mode;
var self = this,
data = (mode === 'w') ? GPIO_WRITE : GPIO_READ;
FS.writeFile(this._directionPath(), data, function(err) {
self._setModeCallback(err, emitConnect);
});
2014-02-28 03:28:13 +08:00
};
DigitalPin.prototype._setModeCallback = function(err, emitConnect) {
if (err) {
this.emit('error', "Setting up pin direction failed");
2014-02-28 03:28:13 +08:00
} else {
this.ready = true;
if (emitConnect) { this.emit('connect', this.mode); }
2014-02-28 03:28:13 +08:00
}
};
2013-11-12 03:44:48 +08:00
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._directionPath = function() {
return this._pinPath() + "/direction";
2014-02-28 03:28:13 +08:00
};
2013-11-12 03:44:48 +08:00
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._valuePath = function() {
return this._pinPath() + "/value";
2014-02-28 03:28:13 +08:00
};
2013-11-12 03:44:48 +08:00
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._pinPath = function() {
return GPIO_PATH + "/gpio" + this.pinNum;
2014-02-28 03:28:13 +08:00
};
2013-11-12 03:44:48 +08:00
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._exportPath = function() {
return GPIO_PATH + "/export";
2014-02-28 03:28:13 +08:00
};
2014-02-28 03:28:13 +08:00
DigitalPin.prototype._unexportPath = function() {
return GPIO_PATH + "/unexport";
2014-02-28 03:28:13 +08:00
};
2014-02-28 03:28:13 +08:00
return DigitalPin;
2014-02-28 03:28:13 +08:00
})(EventEmitter);
});