forked from eclipse/mraa
-
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.
Signed-off-by: David Antler <[email protected]> Signed-off-by: Brendan Le Foll <[email protected]>
- Loading branch information
Showing
6 changed files
with
390 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,17 @@ | ||
module.exports = function(grunt) { | ||
grunt.loadNpmTasks('grunt-mocha-test'); | ||
// Project configuration. | ||
grunt.initConfig({ | ||
pkg: grunt.file.readJSON('package.json'), | ||
mochaTest: { | ||
test: { | ||
options: { | ||
reporter: 'spec' | ||
}, | ||
src: ['test/*.js'] | ||
} | ||
} | ||
}); | ||
|
||
grunt.registerTask('test', ['mochaTest:test']); | ||
}; |
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,52 @@ | ||
mraaStub - JavaScript simulation and stubs for mraa | ||
==================== | ||
|
||
This project enables simulation of a device which might be accessed via mraa. | ||
Currently this library supports I2c, SPI, and GPIO. This project provides | ||
several benefits: | ||
|
||
1. Prevent crashes in nodejs applications using mraa on unsuported or | ||
misconfigured hardware. | ||
2. Enable basic simulation of mraa-accessible devices for unit testing. | ||
|
||
## Examples | ||
|
||
The following example is based on an imaginary 'light bulb' device abstraction, | ||
which exposes a value of brightness over a mraa-provided interface. Please see | ||
the `test/index.js` file for an example. | ||
|
||
## Installation | ||
|
||
mraaStub is not yet in npm so has to be installed from git. In the future | ||
you'll be able to install `mraaStub` from npm like this: | ||
|
||
``` | ||
npm install mraaStub | ||
``` | ||
|
||
Since we often switch between a mraaStub and the real mraa library, we | ||
suggest creating an `index.js` file inside a `lib/mraaSwitcher` folder. | ||
|
||
```js | ||
/* index.js - file for switching between mraa and mraaStub | ||
*/ | ||
|
||
// Define the conditions under which the mraaStub should be loaded | ||
var platform = require('os').platform(); | ||
var m; | ||
|
||
if (platform === 'win32') { | ||
m = require('mraaStub'); | ||
} else { | ||
m = require('mraa'); | ||
} | ||
|
||
module.exports = m; | ||
``` | ||
|
||
You can add this to your project in its own `lib/mraaSwitcher/index.js` file | ||
and use `require('../mraaSwitcher')` everywhere! | ||
|
||
## License | ||
|
||
See [COPYING file](../COPYING) in the root of this repository. |
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,223 @@ | ||
/** | ||
* @fileoverview This file implements a fake mraa stub which enables testing | ||
* as well as the ability to run on Windows. | ||
*/ | ||
|
||
var m; | ||
var winston = require('winston'); | ||
var logger = new winston.Logger({ | ||
transports: [ | ||
new winston.transports.Console({ | ||
level: 'error', | ||
handleExceptions: false, | ||
json: false, | ||
colorize: true}) | ||
], | ||
exitOnError: false | ||
}); | ||
|
||
/** | ||
* @class mraaStub | ||
* @classdesc This class is designed to stub out libmraa so we can run | ||
* test code on unsupported platforms (specifically Windows). | ||
*/ | ||
var mraaStub = function() { | ||
var verison = '0.0.1'; | ||
var self = this; | ||
self.EDGE_BOTH = 1; | ||
self.EDGE_NONE = 2; | ||
self.EDGE_RISING = 3; | ||
self.EDGE_FALLING = 4; | ||
self.DIR_IN = 1; | ||
self.DIR_OUT = 2; | ||
|
||
self.getVersion = function() { | ||
return "mraaStub " + version; | ||
}; | ||
|
||
// Stub out GPIO | ||
function Gpio(num) { | ||
this.num = num; | ||
this._callback = null; | ||
this._dir = null; | ||
this._isr_mode = self.EDGE_NONE; | ||
} | ||
|
||
var logGpio = false; | ||
Gpio.prototype._callIsr = function() { | ||
if(this.isr_mode === self.EDGE_NONE) { | ||
logger.log('info',"Could not call ISR. Not set up for triggering"); | ||
} | ||
this._callback(); | ||
}; | ||
|
||
Gpio.prototype.isr = function(mode, handler){ | ||
if(logGpio) { | ||
logger.log('info',"GPIO " + this.num + " isr stub invoked."); | ||
} | ||
this._isr_mode = self.EDGE_NONE; | ||
this._callback = handler; | ||
}; | ||
|
||
Gpio.prototype.dir = function(d) { | ||
if(logGpio) { | ||
logger.log('info',"GPIO " + this.num + " dir stub invoked."); | ||
} | ||
this._dir = d; | ||
}; | ||
Gpio.prototype.write = function(z) { | ||
if(logGpio) { | ||
logger.log('logger',"GPIO " + this.num + " write stub invoked."); | ||
} | ||
if(this._dir !== self.DIR_OUT) { | ||
logger.log('info',"GPIO " + this.num + " write called without DIR_OUT set."); | ||
} | ||
}; | ||
Gpio.prototype.read = function() { | ||
if(logGpio) { | ||
logger.log('info',"GPIO " + this.num + " read stub invoked."); | ||
} | ||
return 0; | ||
}; | ||
|
||
// Stub out SPI | ||
function Spi(num) { | ||
var self = this; | ||
this.num = num; | ||
this._buffer = new Buffer(29); | ||
this._buffer.fill(0); | ||
this._loopback = false; | ||
} | ||
|
||
Spi.prototype._setOutput = function(buf) { | ||
this._buffer = buf; | ||
}; | ||
|
||
Spi.prototype._enableLoopback = function(x) { | ||
if(x === true) { | ||
this._loopback = true; | ||
} else { | ||
this._loopback = false; | ||
} | ||
}; | ||
|
||
Spi.prototype.write = function(b) { | ||
logger.log('info',"SPI write stub invoked."); | ||
if(this._loopback === true) { | ||
return b; | ||
} | ||
return new Buffer(this._buffer); | ||
}; | ||
|
||
Spi.prototype.frequency = function(f) { | ||
logger.log('info',"SPI frequency stub invoked."); | ||
return f; | ||
}; | ||
|
||
Spi.prototype.lsbmode = function(t) { | ||
logger.log('info',"SPI lsbmode stub invoked."); | ||
}; | ||
|
||
Spi.prototype.mode = function(x) { | ||
logger.log('info',"SPI mode stub invoked."); | ||
}; | ||
|
||
function I2c(num) { | ||
this._num = num; | ||
this._regMapInitialized = false; | ||
} | ||
|
||
/* This function sets an internal register map for the I2c device. | ||
*/ | ||
I2c.prototype._setRegisterMapInternal = function(buffer) { | ||
this._regMapInitialized = true; | ||
this._buffer = buffer; | ||
}; | ||
|
||
I2c.prototype.frequency = function(freq) { | ||
// Do nothing. We don't care. | ||
}; | ||
|
||
I2c.prototype.address = function(address) { | ||
var self = this; | ||
self.address = address; | ||
}; | ||
|
||
I2c.prototype.readReg = function(regAddr) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
return this._buffer.readUInt8(regAddr); | ||
}; | ||
|
||
I2c.prototype.readWordReg = function(regAddr) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
return this._buffer.readUInt16LE(regAddr); | ||
}; | ||
|
||
I2c.prototype.readBytesReg = function(regAddr, len) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
return this._buffer.slice(regAddr,regAddr+len); | ||
}; | ||
|
||
I2c.prototype.write = function(buf) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
var regAddr = buf[0]; | ||
var newBuf = buf.slice(1); | ||
newBuf.copy(this._buffer, regAddr); | ||
}; | ||
|
||
I2c.prototype.writeReg = function(regAddr, data) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
this._buffer.writeUInt8(regAddr,data); | ||
}; | ||
|
||
I2c.prototype.writeWordReg = function(regAddr, dataWord) { | ||
if(!this._regMapInitialized) { | ||
logger.log('error', "Need to set reg map"); | ||
} | ||
if(!this.address) { | ||
logger.log('error', "Need to set address"); | ||
} | ||
|
||
this._buffer.writeUInt16LE(regAddr,data); | ||
}; | ||
|
||
// Export our stubs | ||
self.Gpio = Gpio; | ||
self.Spi = Spi; | ||
self.I2c = I2c; | ||
|
||
}; | ||
|
||
m = new mraaStub(); | ||
|
||
module.exports = m; |
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,34 @@ | ||
{ | ||
"name": "mraaStub", | ||
"version": "0.0.1", | ||
"description": "Enables simulation of mraa interfaces for testing purposes", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "grunt test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/intel-iot-devkit/mraa.git" | ||
}, | ||
"keywords": [ | ||
"mraa", | ||
"iot", | ||
"intel", | ||
"libmraa", | ||
"test", | ||
"galileo", | ||
"edison" | ||
], | ||
"author": "David A Antler <[email protected]>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/intel-iot-devkit/mraa/issues" | ||
}, | ||
"homepage": "https://github.com/intel-iot-devkit/mraa#readme", | ||
"devDependencies": { | ||
"expect.js": "^0.3.1", | ||
"grunt": "^1.0.1", | ||
"grunt-mocha-test": "^0.12.7", | ||
"mocha": "^2.4.5" | ||
} | ||
} |
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,32 @@ | ||
var expect = require('expect.js'); | ||
var m = require('../index'); | ||
var LightBulb = require('./lightbulb'); | ||
|
||
describe('LightBulb', function() { | ||
|
||
/** Model the internal data of LightBulb as a buffer */ | ||
var bufferFullBrightness = new Buffer( | ||
[ 'N', // Four bytes allocated for name | ||
'a', | ||
'm', | ||
'e', | ||
95 // One byte allocated for brightness. Stuff in '95' value! | ||
]); | ||
|
||
it('getBrightness() function should return 95', function() { | ||
|
||
// Create a fake I2c bus based on the 'full brightness' data model | ||
var testI2cBus = new m.I2c(0); | ||
testI2cBus._setRegisterMapInternal(bufferFullBrightness); | ||
|
||
// Create a new LightBulb that opens the testI2cBus, instead of a real | ||
// mraa I2c bus. | ||
var lightBulbI2c = new LightBulb(testI2cBus); | ||
|
||
// presumably getBrightness will gather data from I2C and get '95' | ||
var brightness = lightBulbI2c.getBrightness(); | ||
|
||
expect(brightness).to.be(95); | ||
}) | ||
}); | ||
|
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,32 @@ | ||
/** | ||
* @fileoverview Implementation of a LightBulb class abstraction | ||
* | ||
*/ | ||
|
||
module.exports = (function() { | ||
"use strict"; | ||
var m = require('../index'); | ||
|
||
/** | ||
* Constructor for a new LightBulb | ||
* @class LightBulb | ||
* | ||
* @classdesc This class abstracts access to the control and data registers | ||
* on an imaginary lightbulb. | ||
* @param {Object} A libmraa I2c object, initialized | ||
*/ | ||
function LightBulb (i2cInterface) { | ||
var self = this; | ||
self._i2cInterface = i2cInterface; | ||
|
||
self.getBrightness = function() { | ||
// Presume our brightness data is one byte at offset 4 | ||
return self._i2cInterface.readReg(4); | ||
} | ||
|
||
return self; | ||
} | ||
|
||
return LightBulb; | ||
})(); | ||
|