-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added GpioPlugin with basic functionality (execute/listenEvents)
+ tests
- Loading branch information
Showing
2 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
* This module is used to handle tasks and events directly with GPIO Ports on Raspberry Pi. | ||
* It is used within pi@home. | ||
* | ||
* @class GpioPlugin | ||
*/ | ||
|
||
var onOff; | ||
|
||
/** | ||
* The constructor can be used to change settings of GpioPlugin by using options. | ||
* | ||
* @method GpioPlugin | ||
* @param {opts} opts The options: | ||
* - 'gpioPlugin' = Plugin for using onOff functionality (can be set for testing i.e.) | ||
*/ | ||
function GpioPlugin(opts) { | ||
if(opts==='undefined') { | ||
onOff = require('onoff').Gpio; | ||
} | ||
|
||
if(opts.gpioPlugin) { | ||
onOff = opts.gpioPlugin; | ||
} else { | ||
onOff = require('onoff').Gpio; | ||
} | ||
return this; | ||
} | ||
|
||
/** | ||
* This method is used to execute a pi@home command concerning GPIO Ports. | ||
* | ||
* @method execute | ||
* @param {opts} opts The options: | ||
* - 'direction' = 'in' or 'out' | ||
* - 'pin' = the pin number on RPi GPIOs | ||
* - 'value' = the value for direction 'out' | ||
*/ | ||
function execute(opts) { | ||
if(opts==='undefined') { | ||
throw new Error("arguments for execute missing"); | ||
} | ||
if(!opts.direction) { | ||
throw new Error("option 'direction' is missing"); | ||
} | ||
if(!opts.pin) { | ||
throw new Error("option 'pin' is missing"); | ||
} | ||
|
||
if(opts.direction === 'out') { | ||
if(!opts.value) { | ||
throw new Error("option 'value' is missing for pin output"); | ||
} | ||
this.sendOutput(opts.pin, opts.value); | ||
} | ||
} | ||
|
||
/** | ||
* This method is used to send a output to a GPIO pin. | ||
* | ||
* @method sendOutput | ||
* @param {int} pin The pin on which the signal/value should be send. | ||
* @param {int} value The value which should be send (1 = HIGH, 0 = LOW). | ||
*/ | ||
function sendOutput(pin, value) { | ||
var gpioPin = onOff.Gpio(pin, 'out'); | ||
gpioPin.writeSync(value); | ||
gpioPin.unexport(); | ||
} | ||
|
||
/** | ||
* This method listens on a GPIO pin and throws events with eventId when value of pin changes. | ||
* | ||
* @method listenEvents | ||
* @param {int} eventId The eventId like configured in event config. | ||
* @param {opts} opts The opts must contain 'pin' on which should be listened. | ||
*/ | ||
function listenEvents(eventId, opts) { | ||
if(!opts.pin) { | ||
throw new Error("option 'pin' is missing"); | ||
} | ||
//TODO check eventId = valid int | ||
var listenPort = new onOff.Gpio(opts.pin, 'in', 'both', {persistentWatch: true}); | ||
var eventIdString = eventId + ''; | ||
|
||
listenPort.watch(function(err, value) { | ||
process.emit(eventId+'', value); | ||
}); | ||
} | ||
|
||
// If we're running under Node, | ||
if(typeof exports !== 'undefined') { | ||
exports.execute = execute; | ||
exports.GpioPlugin = GpioPlugin; | ||
exports.sendOutput = sendOutput; | ||
exports.listenEvents = listenEvents; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
var gpioPlugin = require('./../../../src/plugins/GpioPlugin/GpioPlugin'); | ||
var assert = require('chai').assert; | ||
var sinon = require('sinon'); | ||
|
||
describe('GPIO-tests', function(){ | ||
|
||
it("should throw error because one or more options are missing", function() { | ||
var gpio = gpioPlugin.GpioPlugin({'GpioPlugin':null}); | ||
var error; | ||
//without arguments | ||
try { | ||
gpio.execute(); | ||
} catch (err) { | ||
error = err; | ||
} | ||
assert.include(error.message, "Cannot read property 'direction' of undefined"); | ||
|
||
//empty arguments | ||
error = null; | ||
try { | ||
gpio.execute({}); | ||
} catch (err) { | ||
error = err; | ||
} | ||
assert.include(error.message, "option 'direction' is missing"); | ||
|
||
//missing pin | ||
error = null; | ||
try { | ||
gpio.execute({'direction':'in'}); | ||
} catch (err) { | ||
error = err; | ||
} | ||
assert.include(error.message, "option 'pin' is missing"); | ||
|
||
//value missing | ||
error = null; | ||
try { | ||
gpio.execute({'direction':'out','pin':17}); | ||
} catch (err) { | ||
error = err; | ||
} | ||
assert.include(error.message, "option 'value' is missing"); | ||
}); | ||
|
||
it("should execute function 'sendOutput' with correct values", function() { | ||
//Preparation | ||
var onOff = require('onoff').Gpio; | ||
|
||
var gpioMock = { | ||
writeSync:function(value) { | ||
assert.equal(value,1); | ||
}, | ||
unexport:function() { | ||
} | ||
}; | ||
|
||
var onOffMock = { | ||
Gpio:function(pin,direction) { | ||
assert.equal(pin,18); | ||
assert.equal(direction,'out'); | ||
return gpioMock; | ||
} | ||
}; | ||
|
||
gpio = gpioPlugin.GpioPlugin({'gpioPlugin':onOffMock}); | ||
|
||
var spy1 = sinon.spy(onOffMock, "Gpio"); | ||
var spy2 = sinon.spy(gpioMock, "writeSync"); | ||
var spy3 = sinon.spy(gpioMock, "unexport"); | ||
|
||
//execution | ||
gpio.execute({'direction':'out','pin':18,'value':1}); | ||
|
||
//assertion | ||
assert(spy1.calledOnce, "method Gpio should be called"); | ||
assert(spy2.calledOnce, "method writeSync should be called"); | ||
assert(spy3.calledOnce, "method unexport should be called"); | ||
}); | ||
|
||
it("should check functionality of method 'listenEvents'", function() { | ||
//Preparation | ||
var eventId = 1234; | ||
var onOff = require('onoff').Gpio; | ||
var success = false; | ||
|
||
process.on("1234", function(value) { | ||
if(value===1) { | ||
success = true; | ||
} | ||
}); | ||
|
||
var gpioMock = { | ||
watch:function(callback) { | ||
callback(false, 1); | ||
} | ||
}; | ||
|
||
var onOffMock = { | ||
Gpio:function(pin,direction,edge,options) { | ||
assert.equal(pin,18); | ||
assert.equal(direction,'in'); | ||
assert.equal(edge,'both'); | ||
assert.equal(options.persistentWatch,true); | ||
return gpioMock; | ||
} | ||
}; | ||
|
||
gpio = gpioPlugin.GpioPlugin({'gpioPlugin':onOffMock}); | ||
|
||
var spy1 = sinon.spy(onOffMock, "Gpio"); | ||
var spy2 = sinon.spy(gpioMock, "watch"); | ||
|
||
|
||
//execution | ||
gpio.listenEvents(eventId, {'pin':18}); | ||
|
||
//assertion | ||
assert.equal(success, true, "should return correct event with correct value"); | ||
|
||
//after test | ||
process.removeAllListeners("1234"); | ||
}); | ||
}); |