Add JavaScript mraaStub project
Signed-off-by: David Antler <david.a.antler@intel.com> Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
committed by
Brendan Le Foll
parent
a321d6707f
commit
1cfdfcddc6
17
jsstub/Gruntfile.js
Normal file
17
jsstub/Gruntfile.js
Normal file
@@ -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']);
|
||||
};
|
||||
52
jsstub/README.md
Normal file
52
jsstub/README.md
Normal file
@@ -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.
|
||||
223
jsstub/index.js
Normal file
223
jsstub/index.js
Normal file
@@ -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;
|
||||
34
jsstub/package.json
Normal file
34
jsstub/package.json
Normal file
@@ -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 <david.a.antler@intel.com>",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
32
jsstub/test/index.js
Normal file
32
jsstub/test/index.js
Normal file
@@ -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);
|
||||
})
|
||||
});
|
||||
|
||||
32
jsstub/test/lightbulb.js
Normal file
32
jsstub/test/lightbulb.js
Normal file
@@ -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;
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user