Comparar commits
38 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 3f42be4df6 | |||
| 2523f72059 | |||
| af9f08642e | |||
| a2b4d73847 | |||
| c2958f408e | |||
| 0dd0eceb46 | |||
| 70a6165366 | |||
| 2d7547ce79 | |||
| de381a80de | |||
| 888be5d60f | |||
| 57e6d9f7c2 | |||
| fb3d722fc8 | |||
| 2728617126 | |||
| dd7639829a | |||
| b11775ecde | |||
| f96cdd94ec | |||
| 4ce630dc4c | |||
| 8557444c55 | |||
| c2c75fe9d8 | |||
| 13d4f57003 | |||
| b9d0a466f8 | |||
| 4428040a06 | |||
| f7e5c4988e | |||
| d4799dd45a | |||
| 212db205f2 | |||
| 47b2df5802 | |||
| d06b6101e3 | |||
| eb0510be6f | |||
| c696d4f5ca | |||
| 677517715a | |||
| 600b1b2b28 | |||
| 32d011d1f9 | |||
| ee6c50294c | |||
| 34be4c9fe3 | |||
| 57dc399742 | |||
| 5d989f6ea4 | |||
| 2eebde6053 | |||
| f7f8517c28 |
+69
-5
@@ -14,6 +14,8 @@ We are proud to support all functionality of the OpenBCI 8 and 16 Channel boards
|
||||
|
||||
The purpose of this module is to **get connected** and **start streaming** as fast as possible.
|
||||
|
||||
Python researcher or developer? Check out how easy it is to [get access to the entire API in the Python example](examples/python)!
|
||||
|
||||
### Table of Contents:
|
||||
---
|
||||
|
||||
@@ -28,7 +30,7 @@ The purpose of this module is to **get connected** and **start streaming** as fa
|
||||
4. [Constants](#constants)
|
||||
6. [Interfacing With Other Tools](#interfacing-with-other-tools)
|
||||
7. [Developing](#developing)
|
||||
8. [Testing](#testing)
|
||||
8. [Testing](#developing-testing)
|
||||
9. [Contribute](#contribute)
|
||||
10. [License](#license)
|
||||
11. [Roadmap](#roadmap)
|
||||
@@ -38,7 +40,7 @@ The purpose of this module is to **get connected** and **start streaming** as fa
|
||||
npm install openbci
|
||||
```
|
||||
### <a name="tldr"></a> TL;DR:
|
||||
Get connected and start streaming right now
|
||||
Get connected and [start streaming right now with the example code](examples/getStreaming/getStreaming.js).
|
||||
|
||||
```js
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
@@ -71,7 +73,9 @@ Want to know if the module really works? Check out some projects and organizatio
|
||||
|
||||
Still not satisfied it works?? Check out this [detailed report](http://s132342840.onlinehome.us/pushtheworld/files/voltageVerificationTestPlanAndResults.pdf) that scientifically validates the output voltages of this module.
|
||||
|
||||
How are you still doubting and not using this already? Fine, go look at some of the [700 **_automatic_** tests](https://codecov.io/gh/OpenBCI/OpenBCI_NodeJS) written for it!
|
||||
How are you still doubting and not using this already? Fine, go look at some of the [800 **_automatic_** tests](https://codecov.io/gh/OpenBCI/OpenBCI_NodeJS) written for it!
|
||||
|
||||
Python researcher or developer? Check out how easy it is to [get access to the entire API in the Python example](examples/python)!
|
||||
|
||||
### <a name="general-overview"></a> General Overview:
|
||||
|
||||
@@ -84,6 +88,7 @@ Initializing the board:
|
||||
var OpenBCIBoard = require('openbci');
|
||||
var ourBoard = new OpenBCIBoard.OpenBCIBoard();
|
||||
```
|
||||
Go [checkout out the get streaming example](examples/getStreaming/getStreaming.js)!
|
||||
|
||||
For initializing with options, such as verbose print outs:
|
||||
|
||||
@@ -103,6 +108,16 @@ var ourBoard = new OpenBCIBoard({
|
||||
});
|
||||
```
|
||||
|
||||
Have a daisy?:
|
||||
```js
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
boardType: `daisy`,
|
||||
hardSet: true
|
||||
});
|
||||
```
|
||||
Go [checkout out the get streaming with daisy example](examples/getStreamingDaisy/getStreamingDaisy.js)!
|
||||
|
||||
Another useful way to start the simulator:
|
||||
```js
|
||||
var openBCIBoard = require('openbci');
|
||||
@@ -118,6 +133,15 @@ ourBoard.connect(k.OBCISimulatorPortName) // This will set `simulate` to true
|
||||
});
|
||||
```
|
||||
|
||||
To debug, it's amazing, do:
|
||||
|
||||
```js
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
simulate: true
|
||||
});
|
||||
```
|
||||
Go [checkout out the debug example](examples/debug/debug.js)!
|
||||
|
||||
'ready' event
|
||||
------------
|
||||
@@ -382,6 +406,7 @@ Board optional configurations.
|
||||
* `daisy` - 8 Channel board with Daisy Module - 16 Channels
|
||||
* `ganglion` - 4 Channel board
|
||||
(NOTE: THIS IS IN-OP TIL RELEASE OF GANGLION BOARD 08/2016)
|
||||
* `hardSet` {Boolean} - Recommended if using `daisy` board! For some reason, the `daisy` is sometimes not picked up by the module so you can set `hardSet` to true which will ensure the daisy is picked up. (Default `false`)
|
||||
* `simulate` {Boolean} - Full functionality, just mock data. Must attach Daisy module by setting `simulatorDaisyModuleAttached` to `true` in order to get 16 channels. (Default `false`)
|
||||
* `simulatorBoardFailure` {Boolean} - Simulates board communications failure. This occurs when the RFduino on the board is not polling the RFduino on the dongle. (Default `false`)
|
||||
* `simulatorDaisyModuleAttached` {Boolean} - Simulates a daisy module being attached to the OpenBCI board. This is useful if you want to test how your application reacts to a user requesting 16 channels but there is no daisy module actually attached, or vice versa, where there is a daisy module attached and the user only wants to use 8 channels. (Default `false`)
|
||||
@@ -501,6 +526,12 @@ Closes the serial port opened by [`.connect()`](#method-connect). Waits for sto
|
||||
|
||||
**_Returns_** a promise, fulfilled by a successful close of the serial port object, rejected otherwise.
|
||||
|
||||
### <a name="method-get-info"></a> .getInfo()
|
||||
|
||||
Get the core info object. It's the object that actually drives the parsing of data.
|
||||
|
||||
**_Returns_** Object - {{boardType: string, sampleRate: number, firmware: string, numberOfChannels: number, missedPackets: number}}
|
||||
|
||||
### <a name="method-get-settings-for-channel"></a> .getSettingsForChannel(channelNumber)
|
||||
|
||||
Gets the specified channelSettings register data from printRegisterSettings call.
|
||||
@@ -513,6 +544,21 @@ A number specifying which channel you want to get data on. Only 1-8 at this time
|
||||
|
||||
**_Returns_** a promise, fulfilled if the command was sent to the board and the `.processBytes()` function is ready to reach for the specified channel.
|
||||
|
||||
### <a name="method-hard-set-board-type"></a> .hardSetBoardType(boardType)
|
||||
|
||||
Used to sync the module and board to `boardType`.
|
||||
|
||||
**Note: This has the potential to change the way data is parsed**
|
||||
|
||||
**_boardType_**
|
||||
|
||||
A String indicating the number of channels.
|
||||
|
||||
* `default` - Default board: Sample rate is `250Hz` and number of channels is `8`.
|
||||
* `daisy` - Daisy board: Sample rate is `125Hz` and number of channels is `16`.
|
||||
|
||||
**_Returns_** a promise, fulfilled if both the board and module are the requested `boardType`, rejects otherwise.
|
||||
|
||||
### <a name="method-impedance-test-all-channels"></a> .impedanceTestAllChannels()
|
||||
|
||||
To apply test signals to the channels on the OpenBCI board used to test for impedance. This can take a little while to actually run (<8 seconds)!
|
||||
@@ -702,6 +748,19 @@ Get the current number of channels available to use. (i.e. 8 or 16).
|
||||
|
||||
**_Returns_** a number, the total number of available channels.
|
||||
|
||||
### <a name="method-override-info-for-board-type"></a> .overrideInfoForBoardType(boardType)
|
||||
|
||||
Set the info property for board type.
|
||||
|
||||
**Note: This has the potential to change the way data is parsed**
|
||||
|
||||
**_boardType_**
|
||||
|
||||
A String indicating the number of channels.
|
||||
|
||||
* `default` - Default board: Sample rate is `250Hz` and number of channels is `8`.
|
||||
* `daisy` - Daisy board: Sample rate is `125Hz` and number of channels is `16`.
|
||||
|
||||
### <a name="method-print-bytes-in"></a> .printBytesIn()
|
||||
|
||||
Prints the total number of bytes that were read in this session to the console.
|
||||
@@ -846,7 +905,7 @@ To leave simulate mode.
|
||||
|
||||
### <a name="method-sntp"></a> .sntp
|
||||
|
||||
Extends the popular STNP package on [npmjs](https://www.npmjs.com/package/sntp)
|
||||
Extends the popular SNTP package on [npmjs](https://www.npmjs.com/package/sntp)
|
||||
|
||||
### <a name="method-sntp-get-offset"></a> .sntpGetOffset()
|
||||
|
||||
@@ -1067,6 +1126,10 @@ Emitted when a packet (or packets) are dropped. Returns an array.
|
||||
|
||||
Emitted when there is an on the serial port.
|
||||
|
||||
### <a name="event-hard-set"></a> .on('hardSet', callback)
|
||||
|
||||
Emitted when the module detects the board is not configured as the options for the module intended and tries to save itself. i.e. when the `daisy` option is `true` and a soft reset message is parsed and the module determines that a daisy was not detected, the module will emit `hardSet` then send an attach daisy command to recover. Either `error` will be emitted if unable to attach or `ready` will be emitted if success.
|
||||
|
||||
### <a name="event-impedance-array"></a> .on('impedanceArray', callback)
|
||||
|
||||
Emitted when there is a new impedanceArray available. Returns an array.
|
||||
@@ -1166,13 +1229,14 @@ npm test
|
||||
## <a name="contribute"></a> Contribute:
|
||||
|
||||
1. Fork it!
|
||||
2. Branch off of `development`: `git checkout development`
|
||||
2. Create your feature branch: `git checkout -b my-new-feature`
|
||||
3. Make changes
|
||||
4. If adding a feature, please add test coverage.
|
||||
5. Ensure tests all pass. (`npm test`)
|
||||
6. Commit your changes: `git commit -m 'Add some feature'`
|
||||
7. Push to the branch: `git push origin my-new-feature`
|
||||
8. Submit a pull request :D
|
||||
8. Submit a pull request. Make sure it is based off of the `development` branch when submitting! :D
|
||||
|
||||
## <a name="license"></a> License:
|
||||
|
||||
|
||||
@@ -1,3 +1,49 @@
|
||||
# 1.5.0
|
||||
|
||||
### New Features
|
||||
* New simulator option `simulatorDaisyModuleCanBeAttached` - Boolean, deafults to true, allows the simulation of the a hot swapped daisy board or simulates a misinformed module.
|
||||
* New `EventEmitter` - `hardSet` - for when the module detects the board is not configured as the options for the module intended and tries to save itself. i.e. when the `daisy` option is `true` and a soft reset message is parsed and the module determines that a daisy was not detected, the module will emit `hardSet` then send an attach daisy command to recover. Either `error` will be emitted if unable to attach or `ready` will be emitted if success.
|
||||
* Add example for streaming with `daisy` and `hardSet`.
|
||||
|
||||
### Breaking changes
|
||||
* `.setInfoForBoardType()` changed to `.overrideInfoForBoardType()` to elevate it's dangerous nature.
|
||||
* `.setMaxChannels()` changed to `.hardSetBoardType()` and input changed from numerical to string: 8 and 16 to `default` and `daisy` respectively.
|
||||
|
||||
### Bug Fixes
|
||||
* Fixes #131 - 16 chan not working by sending a channel command and parsing the return.
|
||||
* Fixed bug where end of transmission characters would not be ejected from buffer.
|
||||
|
||||
### Enhancements
|
||||
* Separated radio tests from main board test file.
|
||||
|
||||
# 1.4.4
|
||||
|
||||
### New Features
|
||||
* Set max number of channels for the board to use with `.setMaxChannels()` see readme.md
|
||||
* Set the core info object that drives the module with `.overrideInfoForBoardType()` see readme.md
|
||||
* Get info for the core object that drives the module with `.getInfo()` see readme.md
|
||||
|
||||
### Work In Progress
|
||||
* Bug where daisy would sometimes not be recognized which destroyed all data.
|
||||
|
||||
# 1.4.3
|
||||
|
||||
### New examples
|
||||
* Add example of node to python
|
||||
|
||||
# 1.4.2
|
||||
|
||||
### New examples
|
||||
* Add example of debug
|
||||
* Add example of get streaming
|
||||
|
||||
# 1.4.1
|
||||
|
||||
### Bug Fixes
|
||||
* Fixes bug where extra data after EOT (`$$$`) was dumped by preserving the poriton after the EOT for further decomposition.
|
||||
* Fixes bug where any calls to channel set would actually break the openBCISample code as the channelSettingsArray contained an undefined.
|
||||
* Writes promises resolve when they are actually sent over the serial port.
|
||||
|
||||
# 1.4.0
|
||||
|
||||
### New Features
|
||||
@@ -22,6 +68,7 @@
|
||||
* The `.streaming` property has been removed, replaced by `.isStreaming()`. Removed from docs.
|
||||
* An error event will be emitted if sntp fails to initialize on construction
|
||||
* The simulator will no longer communicate when disconnected
|
||||
* Promises returned by writes will now only resolve after the write has been sent
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* This is an example of debugging the board. Thanks to Karl @baffo32
|
||||
* On windows you should run with PowerShell not git bash.
|
||||
* Install
|
||||
* [nodejs](https://nodejs.org/en/)
|
||||
*
|
||||
* To run:
|
||||
* change directory to this file `cd examples/debug`
|
||||
* do `npm install`
|
||||
* then `npm start`
|
||||
*/
|
||||
|
||||
var stream = true;
|
||||
var debug = true; // Pretty print any bytes in and out... it's amazing...
|
||||
var verbose = true; // Adds verbosity to functions
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
debug: debug,
|
||||
verbose: verbose
|
||||
});
|
||||
|
||||
ourBoard.autoFindOpenBCIBoard().then(portName => {
|
||||
if (portName) {
|
||||
/**
|
||||
* Connect to the board with portName
|
||||
* Only works if one board is plugged in
|
||||
* i.e. ourBoard.connect(portName).....
|
||||
*/
|
||||
// Call to connect
|
||||
ourBoard.connect(portName).then(() => {
|
||||
console.log(`connected`);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(`connect: ${err}`);
|
||||
});
|
||||
} else {
|
||||
/** Unable to auto find OpenBCI board */
|
||||
console.log('Unable to auto find OpenBCI board');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The board is ready to start streaming after the ready function is fired.
|
||||
*/
|
||||
var readyFunc = () => {
|
||||
// Get the sample rate after 'ready'
|
||||
sampleRate = ourBoard.sampleRate();
|
||||
if (stream) {
|
||||
ourBoard.streamStart()
|
||||
.catch(err => {
|
||||
console.log(`stream start: ${err}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var sampleFunc = sample => {
|
||||
/**
|
||||
* Checkout the README.md for all other API functions.
|
||||
* We support every feature.
|
||||
* */
|
||||
};
|
||||
|
||||
// Subscribe to your functions
|
||||
ourBoard.on('ready', readyFunc);
|
||||
ourBoard.on('sample', sampleFunc);
|
||||
|
||||
|
||||
function exitHandler (options, err) {
|
||||
if (options.cleanup) {
|
||||
if (verbose) console.log('clean');
|
||||
/** Do additional clean up here */
|
||||
}
|
||||
if (err) console.log(err.stack);
|
||||
if (options.exit) {
|
||||
if (verbose) console.log('exit');
|
||||
if (stream) {
|
||||
ourBoard.streamStop().catch(console.log);
|
||||
}
|
||||
ourBoard.disconnect().catch(console.log);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.on("SIGINT", function () {
|
||||
process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
// do something when app is closing
|
||||
process.on('exit', exitHandler.bind(null, {
|
||||
cleanup: true
|
||||
}));
|
||||
|
||||
// catches ctrl+c event
|
||||
process.on('SIGINT', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
|
||||
// catches uncaught exceptions
|
||||
process.on('uncaughtException', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "debug",
|
||||
"version": "1.0.0",
|
||||
"description": "Debug example",
|
||||
"main": "debug.js",
|
||||
"scripts": {
|
||||
"start": "node debug.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"debug"
|
||||
],
|
||||
"author": "AJ Keller",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"openbci": "^1.4.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* This is an example from the readme.md
|
||||
* On windows you should run with PowerShell not git bash.
|
||||
* Install
|
||||
* [nodejs](https://nodejs.org/en/)
|
||||
*
|
||||
* To run:
|
||||
* change directory to this file `cd examples/debug`
|
||||
* do `npm install`
|
||||
* then `npm start`
|
||||
*/
|
||||
var debug = false; // Pretty print any bytes in and out... it's amazing...
|
||||
var verbose = true; // Adds verbosity to functions
|
||||
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
debug: debug,
|
||||
verbose: verbose
|
||||
});
|
||||
|
||||
ourBoard.autoFindOpenBCIBoard().then(portName => {
|
||||
if (portName) {
|
||||
/**
|
||||
* Connect to the board with portName
|
||||
* Only works if one board is plugged in
|
||||
* i.e. ourBoard.connect(portName).....
|
||||
*/
|
||||
ourBoard.connect(portName) // Port name is a serial port name, see `.listPorts()`
|
||||
.then(() => {
|
||||
ourBoard.on('ready',() => {
|
||||
ourBoard.streamStart();
|
||||
ourBoard.on('sample',(sample) => {
|
||||
/** Work with sample */
|
||||
for (var i = 0; i < ourBoard.numberOfChannels(); i++) {
|
||||
console.log("Channel " + (i + 1) + ": " + sample.channelData[i].toFixed(8) + " Volts.");
|
||||
// prints to the console
|
||||
// "Channel 1: 0.00001987 Volts."
|
||||
// "Channel 2: 0.00002255 Volts."
|
||||
// ...
|
||||
// "Channel 8: -0.00001875 Volts."
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
/** Unable to auto find OpenBCI board */
|
||||
console.log('Unable to auto find OpenBCI board');
|
||||
}
|
||||
});
|
||||
|
||||
function exitHandler (options, err) {
|
||||
if (options.cleanup) {
|
||||
if (verbose) console.log('clean');
|
||||
/** Do additional clean up here */
|
||||
}
|
||||
if (err) console.log(err.stack);
|
||||
if (options.exit) {
|
||||
if (verbose) console.log('exit');
|
||||
ourBoard.disconnect().catch(console.log);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.on("SIGINT", function () {
|
||||
process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
// do something when app is closing
|
||||
process.on('exit', exitHandler.bind(null, {
|
||||
cleanup: true
|
||||
}));
|
||||
|
||||
// catches ctrl+c event
|
||||
process.on('SIGINT', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
|
||||
// catches uncaught exceptions
|
||||
process.on('uncaughtException', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "get-streaming",
|
||||
"version": "1.0.0",
|
||||
"description": "Get streaming example",
|
||||
"main": "getStreaming.js",
|
||||
"scripts": {
|
||||
"start": "node getStreaming.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"get"
|
||||
],
|
||||
"author": "AJ Keller",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"openbci": "^1.4.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* This is an example from the readme.md
|
||||
* On windows you should run with PowerShell not git bash.
|
||||
* Install
|
||||
* [nodejs](https://nodejs.org/en/)
|
||||
*
|
||||
* To run:
|
||||
* change directory to this file `cd examples/debug`
|
||||
* do `npm install`
|
||||
* then `npm start`
|
||||
*/
|
||||
var debug = false; // Pretty print any bytes in and out... it's amazing...
|
||||
var verbose = true; // Adds verbosity to functions
|
||||
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
boardType: 'daisy',
|
||||
debug: debug,
|
||||
hardSet: true,
|
||||
verbose: verbose
|
||||
});
|
||||
|
||||
ourBoard.on('error', (err) => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
ourBoard.autoFindOpenBCIBoard().then(portName => {
|
||||
if (portName) {
|
||||
/**
|
||||
* Connect to the board with portName
|
||||
* Only works if one board is plugged in
|
||||
* i.e. ourBoard.connect(portName).....
|
||||
*/
|
||||
ourBoard.connect(portName) // Port name is a serial port name, see `.listPorts()`
|
||||
.then(() => {
|
||||
ourBoard.once('ready',() => {
|
||||
ourBoard.streamStart();
|
||||
ourBoard.on('sample',(sample) => {
|
||||
/** Work with sample */
|
||||
for (var i = 0; i < ourBoard.numberOfChannels(); i++) {
|
||||
console.log("Channel " + (i + 1) + ": " + sample.channelData[i].toFixed(8) + " Volts.");
|
||||
// prints to the console
|
||||
// "Channel 1: 0.00001987 Volts."
|
||||
// "Channel 2: 0.00002255 Volts."
|
||||
// ...
|
||||
// "Channel 16: -0.00001875 Volts."
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
/** Unable to auto find OpenBCI board */
|
||||
console.log('Unable to auto find OpenBCI board');
|
||||
}
|
||||
});
|
||||
|
||||
function exitHandler (options, err) {
|
||||
if (options.cleanup) {
|
||||
if (verbose) console.log('clean');
|
||||
/** Do additional clean up here */
|
||||
}
|
||||
if (err) console.log(err.stack);
|
||||
if (options.exit) {
|
||||
if (verbose) console.log('exit');
|
||||
ourBoard.disconnect().catch(console.log);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.on("SIGINT", function () {
|
||||
process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
// do something when app is closing
|
||||
process.on('exit', exitHandler.bind(null, {
|
||||
cleanup: true
|
||||
}));
|
||||
|
||||
// catches ctrl+c event
|
||||
process.on('SIGINT', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
|
||||
// catches uncaught exceptions
|
||||
process.on('uncaughtException', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "get-streaming-daisy",
|
||||
"version": "1.0.0",
|
||||
"description": "Get streaming with hard set daisy example",
|
||||
"main": "getStreaming.js",
|
||||
"scripts": {
|
||||
"start": "node getStreamingDaisy.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"get"
|
||||
],
|
||||
"author": "AJ Keller",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"openbci": "^1.5.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import json
|
||||
import sys
|
||||
import numpy as np
|
||||
import time
|
||||
import zmq
|
||||
|
||||
|
||||
class Interface:
|
||||
def __init__(self, verbose=False):
|
||||
context = zmq.Context()
|
||||
self._socket = context.socket(zmq.PAIR)
|
||||
self._socket.connect("tcp://localhost:3004")
|
||||
|
||||
self.verbose = verbose
|
||||
|
||||
if self.verbose:
|
||||
print "Client Ready!"
|
||||
|
||||
# Send a quick message to tell node process we are up and running
|
||||
self.send(json.dumps({
|
||||
'action': 'started',
|
||||
'command': 'status',
|
||||
'message': time.time()*1000.0
|
||||
}))
|
||||
|
||||
def send(self, msg):
|
||||
"""
|
||||
Sends a message to TCP server
|
||||
:param msg: str
|
||||
A string to send to node TCP server, could be a JSON dumps...
|
||||
:return: None
|
||||
"""
|
||||
if self.verbose:
|
||||
print '<- out ' + msg
|
||||
self._socket.send(msg)
|
||||
return
|
||||
|
||||
def recv(self):
|
||||
"""
|
||||
Checks the ZeroMQ for data
|
||||
:return: str
|
||||
String of data
|
||||
"""
|
||||
return self._socket.recv()
|
||||
|
||||
|
||||
class RingBuffer(np.ndarray):
|
||||
"""A multidimensional ring buffer."""
|
||||
|
||||
def __new__(cls, input_array):
|
||||
obj = np.asarray(input_array).view(cls)
|
||||
return obj
|
||||
|
||||
def __array_finalize__(self, obj):
|
||||
if obj is None:
|
||||
return
|
||||
|
||||
def __array_wrap__(self, out_arr, context=None):
|
||||
return np.ndarray.__array_wrap__(self, out_arr, context)
|
||||
|
||||
def append(self, x):
|
||||
"""Adds element x to the ring buffer."""
|
||||
x = np.asarray(x)
|
||||
self[:, :-1] = self[:, 1:]
|
||||
self[:, -1] = x
|
||||
|
||||
|
||||
def main(argv):
|
||||
nb_chan = 8
|
||||
verbose = True
|
||||
|
||||
# Create a new python interface.
|
||||
interface = Interface(verbose=verbose)
|
||||
# Signal buffer
|
||||
signal = RingBuffer(np.zeros((nb_chan + 1, 2500)))
|
||||
|
||||
while True:
|
||||
msg = interface.recv()
|
||||
try:
|
||||
dicty = json.loads(msg)
|
||||
action = dicty.get('action')
|
||||
command = dicty.get('command')
|
||||
message = dicty.get('message')
|
||||
|
||||
if command == 'sample':
|
||||
if action == 'process':
|
||||
# Do sample processing here
|
||||
try:
|
||||
if type(message) is not dict:
|
||||
print "sample is not a dict", message
|
||||
raise ValueError
|
||||
# Get keys of sample
|
||||
data = np.zeros(9)
|
||||
|
||||
data[:-1] = message.get('channelData')
|
||||
data[-1] = message.get('timeStamp')
|
||||
|
||||
# Add data to end of ring buffer
|
||||
signal.append(data)
|
||||
|
||||
print message.get('sampleNumber')
|
||||
except ValueError as e:
|
||||
print e
|
||||
elif command == 'status':
|
||||
if action == 'active':
|
||||
interface.send(json.dumps({
|
||||
'action': 'alive',
|
||||
'command': 'status',
|
||||
'message': time.time() * 1000.0
|
||||
}))
|
||||
|
||||
except BaseException as e:
|
||||
print e
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* This is an example from the readme.md
|
||||
* On windows you should run with PowerShell not git bash.
|
||||
* Install
|
||||
* [nodejs](https://nodejs.org/en/)
|
||||
*
|
||||
* To run:
|
||||
* change directory to this file `cd examples/debug`
|
||||
* do `npm install`
|
||||
* then `npm start`
|
||||
*/
|
||||
var OpenBCIBoard = require('openbci').OpenBCIBoard;
|
||||
var port_pub = 'tcp://127.0.0.1:3004';
|
||||
var zmq = require('zmq-prebuilt');
|
||||
var socket = zmq.socket('pair');
|
||||
var simulate = true; // Sends synthetic data
|
||||
var debug = false; // Pretty print any bytes in and out... it's amazing...
|
||||
var verbose = true; // Adds verbosity to functions
|
||||
|
||||
var ourBoard = new OpenBCIBoard({
|
||||
// simulate: simulate, // Uncomment to see how it works with simulator!
|
||||
simulatorFirmwareVersion: 'v2',
|
||||
debug: debug,
|
||||
verbose: verbose
|
||||
});
|
||||
|
||||
var sampleRate = 250; // Default to 250, ALWAYS verify with a call to `.sampleRate()` after 'ready' event!
|
||||
var timeSyncPossible = false;
|
||||
var resyncPeriodMin = 1;
|
||||
var secondsInMinute = 60;
|
||||
var resyncPeriod = ourBoard.sampleRate() * resyncPeriodMin * secondsInMinute;
|
||||
|
||||
ourBoard.autoFindOpenBCIBoard().then(portName => {
|
||||
if (portName) {
|
||||
/**
|
||||
* Connect to the board with portName
|
||||
* i.e. ourBoard.connect(portName).....
|
||||
*/
|
||||
// Call to connect
|
||||
ourBoard.connect(portName)
|
||||
.then(() => {
|
||||
ourBoard.on('ready', () => {
|
||||
|
||||
// Get the sample rate after 'ready'
|
||||
sampleRate = ourBoard.sampleRate();
|
||||
// Find out if you can even time sync, you must be using v2 and this is only accurate after a `.softReset()` call which is called internally on `.connect()`. We parse the `.softReset()` response for the presence of firmware version 2 properties.
|
||||
timeSyncPossible = ourBoard.usingVersionTwoFirmware();
|
||||
|
||||
if (timeSyncPossible) {
|
||||
ourBoard.streamStart()
|
||||
.catch(err => {
|
||||
console.log(`stream start: ${err}`);
|
||||
});
|
||||
} else {
|
||||
console.log('not able to time sync');
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(`connect: ${err}`);
|
||||
});
|
||||
} else {
|
||||
/** Unable to auto find OpenBCI board */
|
||||
console.log('Unable to auto find OpenBCI board');
|
||||
}
|
||||
});
|
||||
|
||||
var sampleFunc = sample => {
|
||||
if (sample._count % resyncPeriod === 0) {
|
||||
ourBoard.syncClocksFull()
|
||||
.then(syncObj => {
|
||||
// Sync was successful
|
||||
if (syncObj.valid) {
|
||||
// Log the object to check it out!
|
||||
console.log(`timeOffset`, syncObj.timeOffsetMaster);
|
||||
} else {
|
||||
// Retry it
|
||||
console.log(`Was not able to sync... retry!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (sample.timeStamp) { // true after the first successful sync
|
||||
if (sample.timeStamp < 10 * 60 * 60 * 1000) { // Less than 10 hours
|
||||
console.log(`Bad time sync ${sample.timeStamp}`);
|
||||
} else {
|
||||
sendToPython({
|
||||
action: 'process',
|
||||
command: 'sample',
|
||||
message: sample
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Subscribe to your functions
|
||||
ourBoard.on('sample', sampleFunc);
|
||||
|
||||
// ZMQ fun
|
||||
|
||||
socket.bind(port_pub, function (err) {
|
||||
if (err) throw err;
|
||||
console.log(`bound to ${port_pub}`);
|
||||
});
|
||||
|
||||
/**
|
||||
* Used to send a message to the Python process.
|
||||
* @param {Object} interProcessObject The standard inter-process object.
|
||||
* @return {None}
|
||||
*/
|
||||
var sendToPython = (interProcessObject, verbose) => {
|
||||
if (verbose) {
|
||||
console.log(`<- out ${JSON.stringify(interProcessObject)}`);
|
||||
}
|
||||
if (socket) {
|
||||
socket.send(JSON.stringify(interProcessObject));
|
||||
}
|
||||
};
|
||||
|
||||
var receiveFromPython = (raw_data) => {
|
||||
try {
|
||||
let body = JSON.parse(raw_data); // five because `resp `
|
||||
processInterfaceObject(body);
|
||||
} catch (err) {
|
||||
console.log('in -> ' + 'bad json');
|
||||
}
|
||||
};
|
||||
|
||||
socket.on('message', receiveFromPython);
|
||||
|
||||
var sendStatus = () => {
|
||||
sendToPython({'action': 'active', 'message': 'ready', 'command': 'status'}, true);
|
||||
};
|
||||
|
||||
sendStatus();
|
||||
|
||||
/**
|
||||
* Process an incoming message
|
||||
* @param {String} body A stringify JSON object that shall be parsed.
|
||||
* @return {None}
|
||||
*/
|
||||
var processInterfaceObject = (body) => {
|
||||
switch (body.command) {
|
||||
case 'status':
|
||||
processStatus(body);
|
||||
break;
|
||||
default:
|
||||
unrecognizedCommand(body);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to process a status related command from TCP IPC.
|
||||
* @param {Object} body
|
||||
* @return {None}
|
||||
*/
|
||||
var processStatus = (body) => {
|
||||
switch (body.action) {
|
||||
case 'started':
|
||||
console.log(`python started @ ${body.message}ms`);
|
||||
break;
|
||||
case 'alive':
|
||||
console.log(`python duplex communication test completed @ ${body.message}ms`);
|
||||
break;
|
||||
default:
|
||||
unrecognizedCommand(body);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function unrecognizedCommand (body) {
|
||||
console.log(`unrecognizedCommand ${body}`);
|
||||
}
|
||||
|
||||
function exitHandler (options, err) {
|
||||
if (options.cleanup) {
|
||||
if (verbose) console.log('clean');
|
||||
/** Do additional clean up here */
|
||||
}
|
||||
if (err) console.log(err.stack);
|
||||
if (options.exit) {
|
||||
if (verbose) console.log('exit');
|
||||
ourBoard.disconnect().catch(console.log);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.on("SIGINT", function () {
|
||||
process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
// do something when app is closing
|
||||
process.on('exit', exitHandler.bind(null, {
|
||||
cleanup: true
|
||||
}));
|
||||
|
||||
// catches ctrl+c event
|
||||
process.on('SIGINT', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
|
||||
// catches uncaught exceptions
|
||||
process.on('uncaughtException', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "python",
|
||||
"version": "1.0.0",
|
||||
"description": "node to python example",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "concurrently --kill-others \"python handoff.py\" \"node index.js\"",
|
||||
"start-node": "node index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"python",
|
||||
"openbci",
|
||||
"node"
|
||||
],
|
||||
"author": "AJ Keller",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"openbci": "^1.4.2",
|
||||
"zmq-prebuilt": "^2.1.0"
|
||||
},
|
||||
"devEngines": {
|
||||
"node": "<=6.x",
|
||||
"npm": ">=3.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# OpenBCI Node SDK to Python
|
||||
|
||||
## About
|
||||
|
||||
Written to end the struggles of python researchers and developers. ~ written with love by [Push The World!](http://www.pushtheworldllc.com)
|
||||
|
||||
This module has every feature available on the OpenBCI Board.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* [Python 2.7](https://www.python.org/downloads/)
|
||||
* [ZeroMQ](http://zeromq.org/bindings:python)
|
||||
|
||||
```py
|
||||
pip install pyzmq
|
||||
```
|
||||
* [Node.js LTS](https://nodejs.org/en/)
|
||||
|
||||
|
||||
## Installation
|
||||
For Python 2.7 do:
|
||||
```bash
|
||||
python setup.py install
|
||||
```
|
||||
For Node:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## Running
|
||||
```
|
||||
npm start
|
||||
```
|
||||
For running just the node, for example if you were running the python in a separate ide and debugging, it's useful.
|
||||
```python
|
||||
npm run start-node
|
||||
```
|
||||
|
||||
## Contributing
|
||||
Please PR if you have code to contribute!
|
||||
@@ -0,0 +1,12 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(name='openbci-node-python',
|
||||
version='0.0.1',
|
||||
description='Node to Python the right way',
|
||||
url='',
|
||||
author='AJ Keller',
|
||||
author_email='pushtheworldllc@gmail.com',
|
||||
license='MIT',
|
||||
packages=find_packages(),
|
||||
install_requires=['numpy', 'pyzmq'],
|
||||
zip_safe=False)
|
||||
@@ -29,6 +29,7 @@ ourBoard.autoFindOpenBCIBoard().then(portName => {
|
||||
});
|
||||
} else {
|
||||
/** Unable to auto find OpenBCI board */
|
||||
console.log('Unable to auto find OpenBCI board');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -86,3 +87,41 @@ var sampleFunc = sample => {
|
||||
// Subscribe to your functions
|
||||
ourBoard.on('ready', readyFunc);
|
||||
ourBoard.on('sample', sampleFunc);
|
||||
|
||||
function exitHandler (options, err) {
|
||||
if (options.cleanup) {
|
||||
if (verbose) console.log('clean');
|
||||
/** Do additional clean up here */
|
||||
}
|
||||
if (err) console.log(err.stack);
|
||||
if (options.exit) {
|
||||
if (verbose) console.log('exit');
|
||||
ourBoard.disconnect().catch(console.log);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "win32") {
|
||||
const rl = require("readline").createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.on("SIGINT", function () {
|
||||
process.emit("SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
// do something when app is closing
|
||||
process.on('exit', exitHandler.bind(null, {
|
||||
cleanup: true
|
||||
}));
|
||||
|
||||
// catches ctrl+c event
|
||||
process.on('SIGINT', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
|
||||
// catches uncaught exceptions
|
||||
process.on('uncaughtException', exitHandler.bind(null, {
|
||||
exit: true
|
||||
}));
|
||||
+346
-202
@@ -20,9 +20,11 @@ function OpenBCIFactory () {
|
||||
var _options = {
|
||||
boardType: [k.OBCIBoardDefault, k.OBCIBoardDaisy, k.OBCIBoardGanglion],
|
||||
baudRate: 115200,
|
||||
hardSet: false,
|
||||
simulate: false,
|
||||
simulatorBoardFailure: false,
|
||||
simulatorDaisyModuleAttached: false,
|
||||
simulatorDaisyModuleCanBeAttached: true,
|
||||
simulatorFirmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2],
|
||||
simulatorFragmentation: [k.OBCISimulatorFragmentationNone, k.OBCISimulatorFragmentationRandom, k.OBCISimulatorFragmentationFullBuffers, k.OBCISimulatorFragmentationOneByOne],
|
||||
simulatorLatencyTime: 16,
|
||||
@@ -41,80 +43,88 @@ function OpenBCIFactory () {
|
||||
};
|
||||
|
||||
/**
|
||||
* @description The initialization method to call first, before any other method.
|
||||
* @param options (optional) - Board optional configurations.
|
||||
* - `baudRate` {Number} - Baud Rate, defaults to 115200. Manipulating this is allowed if
|
||||
* firmware on board has been previously configured.
|
||||
*
|
||||
* - `boardType` {String} - Specifies type of OpenBCI board.
|
||||
* 3 Possible Boards:
|
||||
* `default` - 8 Channel OpenBCI board (Default)
|
||||
* `daisy` - 8 Channel OpenBCI board with Daisy Module. Total of 16 channels.
|
||||
* `ganglion` - 4 Channel board
|
||||
* (NOTE: THIS IS IN-OP TIL RELEASE OF GANGLION BOARD 07/2016)
|
||||
*
|
||||
* - `simulate` {Boolean} - Full functionality, just mock data. Must attach Daisy module by setting
|
||||
* `simulatorDaisyModuleAttached` to `true` in order to get 16 channels. (Default `false`)
|
||||
*
|
||||
* - `simulatorBoardFailure` {Boolean} - Simulates board communications failure. This occurs when the RFduino on
|
||||
* the board is not polling the RFduino on the dongle. (Default `false`)
|
||||
*
|
||||
* - `simulatorDaisyModuleAttached` {Boolean} - Simulates a daisy module being attached to the OpenBCI board.
|
||||
* This is useful if you want to test how your application reacts to a user requesting 16 channels
|
||||
* but there is no daisy module actually attached, or vice versa, where there is a daisy module
|
||||
* attached and the user only wants to use 8 channels. (Default `false`)
|
||||
*
|
||||
* - `simulatorFirmwareVersion` {String} - Allows simulator to be started with firmware version 2 features
|
||||
* 2 Possible Options:
|
||||
* `v1` - Firmware Version 1 (Default)
|
||||
* `v2` - Firmware Version 2
|
||||
*
|
||||
* - `simulatorFragmentation` {String} - Specifies how to break packets to simulate fragmentation, which
|
||||
* occurs commonly in real devices. It is recommended to test code with this enabled.
|
||||
* 4 Possible Options:
|
||||
* `none` - do not fragment packets; output complete chunks immediately when produced (Default)
|
||||
* `random` - output random small chunks of data interspersed with full buffers
|
||||
* `fullBuffers` - allow buffers to fill up until the latency timer has expired
|
||||
* `oneByOne` - output each byte separately
|
||||
*
|
||||
* - `simulatorLatencyTime` {Number} - The time in milliseconds to wait before sending partially full buffers,
|
||||
if `simulatorFragmentation` is specified. (Default `16`)
|
||||
*
|
||||
* - `simulatorBufferSize` {Number} - The size of a full buffer of data, if `simulatorFragmentation` is
|
||||
* specified. (Default `4096`)
|
||||
*
|
||||
* - `simulatorHasAccelerometer` - {Boolean} - Sets simulator to send packets with accelerometer data. (Default `true`)
|
||||
*
|
||||
* - `simulatorInjectAlpha` - {Boolean} - Inject a 10Hz alpha wave in Channels 1 and 2 (Default `true`)
|
||||
*
|
||||
* - `simulatorInjectLineNoise` {String} - Injects line noise on channels.
|
||||
* 3 Possible Options:
|
||||
* `60Hz` - 60Hz line noise (Default) [America]
|
||||
* `50Hz` - 50Hz line noise [Europe]
|
||||
* `none` - Do not inject line noise.
|
||||
*
|
||||
* - `simulatorSampleRate` {Number} - The sample rate to use for the simulator. Simulator will set to 125 if
|
||||
* `simulatorDaisyModuleAttached` is set `true`. However, setting this option overrides that
|
||||
* setting and this sample rate will be used. (Default is `250`)
|
||||
*
|
||||
* - `simulatorSerialPortFailure` {Boolean} - Simulates not being able to open a serial connection. Most likely
|
||||
* due to a OpenBCI dongle not being plugged in.
|
||||
*
|
||||
* - `sntpTimeSync` - {Boolean} Syncs the module up with an SNTP time server and uses that as single source
|
||||
* of truth instead of local computer time. If you are running experiements on your local
|
||||
* computer, keep this `false`. (Default `false`)
|
||||
*
|
||||
* - `sntpTimeSyncHost` - {String} The ntp server to use, can be either sntp or ntp. (Defaults `pool.ntp.org`).
|
||||
*
|
||||
* - `sntpTimeSyncPort` - {Number} The port to access the ntp server. (Defaults `123`)
|
||||
*
|
||||
* - `verbose` {Boolean} - Print out useful debugging events. (Default `false`)
|
||||
*
|
||||
* - `debug` {Boolean} - Print out a raw dump of bytes sent and received. (Default `false`)
|
||||
*
|
||||
* @constructor
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
* @description The initialization method to call first, before any other method.
|
||||
* @param options (optional) - Board optional configurations.
|
||||
* - `baudRate` {Number} - Baud Rate, defaults to 115200. Manipulating this is allowed if
|
||||
* firmware on board has been previously configured.
|
||||
*
|
||||
* - `boardType` {String} - Specifies type of OpenBCI board.
|
||||
* 3 Possible Boards:
|
||||
* `default` - 8 Channel OpenBCI board (Default)
|
||||
* `daisy` - 8 Channel OpenBCI board with Daisy Module. Total of 16 channels.
|
||||
* `ganglion` - 4 Channel board
|
||||
* (NOTE: THIS IS IN-OP TIL RELEASE OF GANGLION BOARD 07/2016)
|
||||
*
|
||||
* - `hardSet` {Boolean} - Recommended if using `daisy` board! For some reason, the `daisy` is sometimes
|
||||
* not picked up by the module so you can set `hardSet` to true which will ensure the daisy
|
||||
* is picked up. (Default `false`)
|
||||
*
|
||||
* - `simulate` {Boolean} - Full functionality, just mock data. Must attach Daisy module by setting
|
||||
* `simulatorDaisyModuleAttached` to `true` in order to get 16 channels. (Default `false`)
|
||||
*
|
||||
* - `simulatorBoardFailure` {Boolean} - Simulates board communications failure. This occurs when the RFduino on
|
||||
* the board is not polling the RFduino on the dongle. (Default `false`)
|
||||
*
|
||||
* - `simulatorDaisyModuleAttached` {Boolean} - Simulates a daisy module being attached to the OpenBCI board.
|
||||
* This is useful if you want to test how your application reacts to a user requesting 16 channels
|
||||
* but there is no daisy module actually attached, or vice versa, where there is a daisy module
|
||||
* attached and the user only wants to use 8 channels. (Default `false`)
|
||||
*
|
||||
* - `simulatorDaisyModuleCanBeAttached` {Boolean} - Allows the simulation of the a hot swapped daisy board.
|
||||
* For example: You coule simulate if the board has only detected 8 channels and the user requested
|
||||
* 16 channels. (Default `true`)
|
||||
*
|
||||
* - `simulatorFirmwareVersion` {String} - Allows simulator to be started with firmware version 2 features
|
||||
* 2 Possible Options:
|
||||
* `v1` - Firmware Version 1 (Default)
|
||||
* `v2` - Firmware Version 2
|
||||
*
|
||||
* - `simulatorFragmentation` {String} - Specifies how to break packets to simulate fragmentation, which
|
||||
* occurs commonly in real devices. It is recommended to test code with this enabled.
|
||||
* 4 Possible Options:
|
||||
* `none` - do not fragment packets; output complete chunks immediately when produced (Default)
|
||||
* `random` - output random small chunks of data interspersed with full buffers
|
||||
* `fullBuffers` - allow buffers to fill up until the latency timer has expired
|
||||
* `oneByOne` - output each byte separately
|
||||
*
|
||||
* - `simulatorLatencyTime` {Number} - The time in milliseconds to wait before sending partially full buffers,
|
||||
* if `simulatorFragmentation` is specified. (Default `16`)
|
||||
*
|
||||
* - `simulatorBufferSize` {Number} - The size of a full buffer of data, if `simulatorFragmentation` is
|
||||
* specified. (Default `4096`)
|
||||
*
|
||||
* - `simulatorHasAccelerometer` - {Boolean} - Sets simulator to send packets with accelerometer data. (Default `true`)
|
||||
*
|
||||
* - `simulatorInjectAlpha` - {Boolean} - Inject a 10Hz alpha wave in Channels 1 and 2 (Default `true`)
|
||||
*
|
||||
* - `simulatorInjectLineNoise` {String} - Injects line noise on channels.
|
||||
* 3 Possible Options:
|
||||
* `60Hz` - 60Hz line noise (Default) [America]
|
||||
* `50Hz` - 50Hz line noise [Europe]
|
||||
* `none` - Do not inject line noise.
|
||||
*
|
||||
* - `simulatorSampleRate` {Number} - The sample rate to use for the simulator. Simulator will set to 125 if
|
||||
* `simulatorDaisyModuleAttached` is set `true`. However, setting this option overrides that
|
||||
* setting and this sample rate will be used. (Default is `250`)
|
||||
*
|
||||
* - `simulatorSerialPortFailure` {Boolean} - Simulates not being able to open a serial connection. Most likely
|
||||
* due to a OpenBCI dongle not being plugged in.
|
||||
*
|
||||
* - `sntpTimeSync` - {Boolean} Syncs the module up with an SNTP time server and uses that as single source
|
||||
* of truth instead of local computer time. If you are running experiements on your local
|
||||
* computer, keep this `false`. (Default `false`)
|
||||
*
|
||||
* - `sntpTimeSyncHost` - {String} The ntp server to use, can be either sntp or ntp. (Defaults `pool.ntp.org`).
|
||||
*
|
||||
* - `sntpTimeSyncPort` - {Number} The port to access the ntp server. (Defaults `123`)
|
||||
*
|
||||
* - `verbose` {Boolean} - Print out useful debugging events. (Default `false`)
|
||||
*
|
||||
* - `debug` {Boolean} - Print out a raw dump of bytes sent and received. (Default `false`)
|
||||
*
|
||||
* @constructor
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
function OpenBCIBoard (options) {
|
||||
options = (typeof options !== 'function') && options || {};
|
||||
var opts = {};
|
||||
@@ -157,7 +167,7 @@ function OpenBCIFactory () {
|
||||
// Arrays
|
||||
this.accelArray = [0, 0, 0]; // X, Y, Z
|
||||
this.channelSettingsArray = k.channelSettingsArrayInit(k.numberOfChannelsForBoardType(this.options.boardType));
|
||||
this.writeOutArray = new Array(100);
|
||||
this.writeOutArray = [];
|
||||
// Booleans
|
||||
this._streaming = false;
|
||||
// Buffers
|
||||
@@ -200,13 +210,13 @@ function OpenBCIFactory () {
|
||||
// Numbers
|
||||
this.badPackets = 0;
|
||||
this.curParsingMode = k.OBCIParsingReset;
|
||||
this.commandsToWrite = 0;
|
||||
this.impedanceArray = openBCISample.impedanceArray(k.numberOfChannelsForBoardType(this.options.boardType));
|
||||
this.previousSampleNumber = -1;
|
||||
this.sampleCount = 0;
|
||||
this.timeOfPacketArrival = 0;
|
||||
this.writeOutDelay = k.OBCIWriteIntervalDelayMSShort;
|
||||
// Strings
|
||||
this.portName = null;
|
||||
|
||||
// NTP
|
||||
if (this.options.sntpTimeSync) {
|
||||
@@ -255,6 +265,7 @@ function OpenBCIFactory () {
|
||||
alpha: this.options.simulatorInjectAlpha,
|
||||
boardFailure: this.options.simulatorBoardFailure,
|
||||
daisy: this.options.simulatorDaisyModuleAttached,
|
||||
daisyCanBeAttached: this.options.simulatorDaisyModuleCanBeAttached,
|
||||
drift: this.options.simulatorInternalClockDrift,
|
||||
firmwareVersion: this.options.simulatorFirmwareVersion,
|
||||
fragmentation: this.options.simulatorFragmentation,
|
||||
@@ -281,29 +292,42 @@ function OpenBCIFactory () {
|
||||
this._processBytes(data);
|
||||
});
|
||||
this.serial.once('open', () => {
|
||||
var timeoutLength = this.options.simulate ? 50 : 300;
|
||||
if (this.options.verbose) console.log('Serial port open');
|
||||
setTimeout(() => {
|
||||
new Promise(resolve => {
|
||||
// TODO: document why this 300 ms delay is needed
|
||||
setTimeout(resolve, this.options.simulate ? 50 : 300);
|
||||
}).then(() => {
|
||||
if (this.options.verbose) console.log('Sending stop command, in case the device was left streaming...');
|
||||
this.write(k.OBCIStreamStop);
|
||||
if (this.serial) this.serial.flush();
|
||||
}, timeoutLength);
|
||||
setTimeout(() => {
|
||||
return this.write(k.OBCIStreamStop);
|
||||
}).then(() => {
|
||||
return new Promise(resolve => this.serial.flush(resolve));
|
||||
}).then(() => {
|
||||
// TODO: document why this 250 ms delay is needed
|
||||
return new Promise(resolve => setTimeout(resolve, 250));
|
||||
}).then(() => {
|
||||
if (this.options.verbose) console.log('Sending soft reset');
|
||||
this.softReset();
|
||||
// TODO: this promise chain resolves early because
|
||||
// A. some legacy code (in tests) sets the ready handler after this resolves
|
||||
// and
|
||||
// B. other legacy code (in tests) needs the simulator to reply with segmented packets, never fragmented
|
||||
// which is C. not implemented yet except in a manner such that replies occur in the write handler,
|
||||
// resulting in the EOT arriving before this resolves
|
||||
// Fix one or more of the above 3 situations, then move resolve() to the next block.
|
||||
resolve();
|
||||
return this.softReset();
|
||||
}).then(() => {
|
||||
if (this.options.verbose) console.log("Waiting for '$$$'");
|
||||
}, timeoutLength + 250);
|
||||
});
|
||||
});
|
||||
this.serial.once('close', () => {
|
||||
if (this.options.verbose) console.log('Serial Port Closed');
|
||||
// 'close' is emitted in _disconnected()
|
||||
this._disconnected();
|
||||
this._disconnected('port closed');
|
||||
});
|
||||
this.serial.once('error', (err) => {
|
||||
if (this.options.verbose) console.log('Serial Port Error');
|
||||
this.emit('error', err);
|
||||
this._disconnected();
|
||||
this._disconnected(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -312,10 +336,9 @@ function OpenBCIFactory () {
|
||||
* @description Called once when for any reason the serial port is no longer open.
|
||||
* @private
|
||||
*/
|
||||
OpenBCIBoard.prototype._disconnected = function () {
|
||||
OpenBCIBoard.prototype._disconnected = function (err) {
|
||||
this._streaming = false;
|
||||
|
||||
this.commandsToWrite = 0;
|
||||
clearTimeout(this.writer);
|
||||
this.writer = null;
|
||||
|
||||
@@ -323,6 +346,11 @@ function OpenBCIFactory () {
|
||||
this.serial = null;
|
||||
|
||||
this.emit('close');
|
||||
|
||||
while (this.writeOutArray.length > 0) {
|
||||
var command = this.writeOutArray.pop();
|
||||
if (command.reject) command.reject(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -332,9 +360,6 @@ function OpenBCIFactory () {
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
OpenBCIBoard.prototype.disconnect = function () {
|
||||
if (!this.isConnected()) return Promise.reject('no board connected');
|
||||
|
||||
// no need for timeout here; streamStop already performs a delay
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
if (this.isStreaming()) {
|
||||
@@ -343,12 +368,16 @@ function OpenBCIFactory () {
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// serial emitting 'close' will call _disconnected
|
||||
this.serial.close(() => {
|
||||
resolve();
|
||||
if (!this.isConnected()) {
|
||||
return Promise.reject('no board connected');
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
// serial emitting 'close' will call _disconnected
|
||||
this.serial.close(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -361,14 +390,24 @@ function OpenBCIFactory () {
|
||||
return this.serial.isOpen();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @description Checks if the board is currently sending samples.
|
||||
* @returns {boolean} - True if streaming.
|
||||
*/
|
||||
OpenBCIBoard.prototype.isSimulating = function () {
|
||||
return this.options.simulate;
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Checks if the board is currently sending samples.
|
||||
* @returns {boolean} - True if streaming.
|
||||
*/
|
||||
OpenBCIBoard.prototype.isStreaming = function () {
|
||||
return this._streaming;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @description Sends a start streaming command to the board.
|
||||
* @returns {Promise} indicating if the signal was able to be sent.
|
||||
@@ -382,13 +421,7 @@ function OpenBCIFactory () {
|
||||
if (this.isStreaming()) return reject('Error [.streamStart()]: Already streaming');
|
||||
this._streaming = true;
|
||||
this._reset_ABANDONED(); // framework is incomplete but looks useful
|
||||
this.write(k.OBCIStreamStart)
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 10); // allow time for command to get sent
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
this.write(k.OBCIStreamStart).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -404,13 +437,7 @@ function OpenBCIFactory () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isStreaming()) return reject('Error [.streamStop()]: No stream to stop');
|
||||
this._streaming = false;
|
||||
this.write(k.OBCIStreamStop)
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 10); // allow time for command to get sent
|
||||
})
|
||||
.catch(err => reject(err));
|
||||
this.write(k.OBCIStreamStop).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -462,50 +489,55 @@ function OpenBCIFactory () {
|
||||
|
||||
/**
|
||||
* @description To be able to easily write to the board but ensure that we never send commands
|
||||
* with less than a 10ms spacing between sends. This uses an array and pops off
|
||||
* the entries until there are none left.
|
||||
* with less than a 10ms spacing between sends in early version boards. This uses
|
||||
* an array and shifts off the entries until there are none left.
|
||||
* @param dataToWrite - Either a single character or an Array of characters
|
||||
* @returns {Promise}
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
OpenBCIBoard.prototype.write = function (dataToWrite) {
|
||||
var writerFunction = () => {
|
||||
/* istanbul ignore else */
|
||||
if (this.commandsToWrite > 0) {
|
||||
var command = this.writeOutArray.shift();
|
||||
this.commandsToWrite--;
|
||||
if (this.commandsToWrite === 0) {
|
||||
this.writer = null;
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isConnected()) {
|
||||
reject('not connected');
|
||||
} else {
|
||||
if (Array.isArray(dataToWrite)) { // Got an input array
|
||||
var len = dataToWrite.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
this.writeOutArray.push({ cmd: dataToWrite[i], reject: reject });
|
||||
}
|
||||
this.writeOutArray[this.writeOutArray.length - 1].resolve = resolve;
|
||||
} else {
|
||||
this.writeOutArray.push({ cmd: dataToWrite, reject: reject, resolve: resolve });
|
||||
}
|
||||
|
||||
if (!this.writer) { // there is no writer started
|
||||
var writerFunction = () => {
|
||||
if (this.writeOutArray.length === 0) {
|
||||
this.writer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var command = this.writeOutArray.shift();
|
||||
var promise = this._writeAndDrain(command.cmd);
|
||||
|
||||
promise.then(() => {
|
||||
this.writer = setTimeout(writerFunction, this.writeOutDelay);
|
||||
}, () => {
|
||||
// write failed but more commands may be pending that need a result
|
||||
writerFunction();
|
||||
});
|
||||
|
||||
if (command.reject) {
|
||||
promise.catch(err => {
|
||||
if (this.options.verbose) console.log('write failure: ' + err);
|
||||
command.reject(err);
|
||||
});
|
||||
}
|
||||
if (command.resolve) promise.then(command.resolve);
|
||||
};
|
||||
this.writer = setTimeout(writerFunction, this.writeOutDelay);
|
||||
}
|
||||
this._writeAndDrain(command)
|
||||
.catch(err => {
|
||||
/* istanbul ignore if */
|
||||
if (this.options.verbose) console.log('write failure: ' + err);
|
||||
});
|
||||
} else {
|
||||
if (this.options.verbose) console.log('Big problem! Writer started with no commands to write');
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// console.log('write method called')
|
||||
if (!this.isConnected()) return reject('not connected');
|
||||
if (Array.isArray(dataToWrite)) { // Got an input array
|
||||
var len = dataToWrite.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
this.writeOutArray[this.commandsToWrite] = dataToWrite[i];
|
||||
this.commandsToWrite++;
|
||||
}
|
||||
} else {
|
||||
this.writeOutArray[this.commandsToWrite] = dataToWrite;
|
||||
this.commandsToWrite++;
|
||||
}
|
||||
if (this.writer === null || this.writer === undefined) { // there is no writer started
|
||||
this.writer = setTimeout(writerFunction, this.writeOutDelay);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -651,7 +683,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSet, channelNumber]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSet, channelNumber])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -701,7 +733,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSetOverride, channelNumber]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelSetOverride, channelNumber])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -751,7 +783,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelGet]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdChannelGet])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -797,7 +829,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeGet]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeGet])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -848,7 +880,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeSet, pollTime]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdPollTimeSet, pollTime])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -920,9 +952,9 @@ function OpenBCIFactory () {
|
||||
|
||||
// Send the radio channel query command
|
||||
if (speed === k.OBCIRadioBaudRateFastStr) {
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetFast]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetFast])).catch(reject);
|
||||
} else {
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetDefault]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdBaudRateSetDefault])).catch(reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -970,7 +1002,7 @@ function OpenBCIFactory () {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
|
||||
// Send the radio channel query command
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdSystemStatus]));
|
||||
this._writeAndDrain(new Buffer([k.OBCIRadioKey, k.OBCIRadioCmdSystemStatus])).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1002,6 +1034,105 @@ function OpenBCIFactory () {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the board type.
|
||||
* @return boardType: string
|
||||
*/
|
||||
OpenBCIBoard.prototype.getBoardType = function() {
|
||||
return this.info.boardType;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the core info object.
|
||||
* @return {{boardType: string, sampleRate: number, firmware: string, numberOfChannels: number, missedPackets: number}}
|
||||
*/
|
||||
OpenBCIBoard.prototype.getInfo = function() {
|
||||
return this.info;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the info property for board type.
|
||||
* @param boardType {String}
|
||||
* `default` or `daisy`. Defaults to `default`.
|
||||
*/
|
||||
OpenBCIBoard.prototype.overrideInfoForBoardType = function(boardType) {
|
||||
switch (boardType) {
|
||||
case k.OBCIBoardDaisy:
|
||||
this.info.boardType = k.OBCIBoardDaisy;
|
||||
this.info.numberOfChannels = k.OBCINumberOfChannelsDaisy;
|
||||
this.info.sampleRate = k.OBCISampleRate125;
|
||||
this.channelSettingsArray = k.channelSettingsArrayInit(k.OBCINumberOfChannelsDaisy);
|
||||
this.goertzelObject = openBCISample.goertzelNewObject(k.OBCINumberOfChannelsDaisy);
|
||||
this.impedanceArray = openBCISample.impedanceArray(k.OBCINumberOfChannelsDaisy);
|
||||
break;
|
||||
case k.OBCIBoardDefault:
|
||||
default:
|
||||
this.info.boardType = k.OBCIBoardDefault;
|
||||
this.info.numberOfChannels = k.OBCINumberOfChannelsDefault;
|
||||
this.info.sampleRate = k.OBCISampleRate250;
|
||||
this.channelSettingsArray = k.channelSettingsArrayInit(k.OBCINumberOfChannelsDefault);
|
||||
this.goertzelObject = openBCISample.goertzelNewObject(k.OBCINumberOfChannelsDefault);
|
||||
this.impedanceArray = openBCISample.impedanceArray(k.OBCINumberOfChannelsDefault);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to sync the module and board to `boardType`
|
||||
* @param boardType {String}
|
||||
* Either `default` or `daisy`
|
||||
* @return {Promise}
|
||||
*/
|
||||
OpenBCIBoard.prototype.hardSetBoardType = function (boardType) {
|
||||
if (this.isStreaming()) return Promise.reject('Must not be streaming!');
|
||||
return new Promise((resolve, reject) => {
|
||||
const eotFunc = (data) => {
|
||||
switch (data.slice(0, data.length - k.OBCIParseEOT.length).toString()) {
|
||||
case k.OBCIChannelMaxNumber8SuccessDaisyRemoved:
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDefault);
|
||||
resolve('daisy removed');
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber16DaisyAlreadyAttached:
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDaisy);
|
||||
resolve('daisy already attached');
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber16DaisyAttached:
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDaisy);
|
||||
resolve('daisy attached');
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber16NoDaisyAttached:
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDefault);
|
||||
reject('unable to attach daisy');
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber8NoDaisyToRemove:
|
||||
default:
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDefault);
|
||||
resolve('no daisy to remove');
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (boardType === k.OBCIBoardDefault) {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
this.once(k.OBCIEmitterEot, eotFunc);
|
||||
this.write(k.OBCIChannelMaxNumber8)
|
||||
.catch((err) => {
|
||||
this.removeListener(k.OBCIEmitterEot, eotFunc);
|
||||
reject(err);
|
||||
});
|
||||
} else if (boardType === k.OBCIBoardDaisy) {
|
||||
this.curParsingMode = k.OBCIParsingEOT;
|
||||
this.once(k.OBCIEmitterEot, eotFunc);
|
||||
this.write(k.OBCIChannelMaxNumber16)
|
||||
.catch((err) => {
|
||||
this.removeListener(k.OBCIEmitterEot, eotFunc);
|
||||
reject(err);
|
||||
});
|
||||
} else {
|
||||
reject('invalid board type');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Sends a soft reset command to the board
|
||||
* @returns {Promise}
|
||||
@@ -1092,13 +1223,11 @@ function OpenBCIFactory () {
|
||||
var arrayOfCommands = [];
|
||||
return new Promise((resolve, reject) => {
|
||||
k.getChannelSetter(channelNumber, powerDown, gain, inputType, bias, srb2, srb1)
|
||||
.then((arr, newChannelSettingObject) => {
|
||||
arrayOfCommands = arr;
|
||||
this.channelSettingsArray[channelNumber - 1] = newChannelSettingObject;
|
||||
resolve(this.write(arrayOfCommands));
|
||||
}, function (err) {
|
||||
reject(err);
|
||||
});
|
||||
.then((val) => {
|
||||
arrayOfCommands = val.commandArray;
|
||||
this.channelSettingsArray[channelNumber - 1] = val.newChannelSettingsObject;
|
||||
return this.write(arrayOfCommands);
|
||||
}).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1146,12 +1275,13 @@ function OpenBCIFactory () {
|
||||
this.impedanceTest.active = true;
|
||||
this.impedanceTest.continuousMode = true;
|
||||
|
||||
var chain = Promise.resolve();
|
||||
for (var i = 0; i < this.numberOfChannels(); i++) {
|
||||
k.getImpedanceSetter(i + 1, false, true).then((commandsArray) => {
|
||||
this.write(commandsArray);
|
||||
});
|
||||
chain = chain
|
||||
.then(() => k.getImpedanceSetter(i + 1, false, true))
|
||||
.then((commandsArray) => this.write(commandsArray));
|
||||
}
|
||||
resolve();
|
||||
chain.then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1168,12 +1298,13 @@ function OpenBCIFactory () {
|
||||
this.impedanceTest.active = false;
|
||||
this.impedanceTest.continuousMode = false;
|
||||
|
||||
var chain = Promise.resolve();
|
||||
for (var i = 0; i < this.numberOfChannels(); i++) {
|
||||
k.getImpedanceSetter(i + 1, false, false).then((commandsArray) => {
|
||||
this.write(commandsArray);
|
||||
});
|
||||
chain = chain
|
||||
.then(() => k.getImpedanceSetter(i + 1, false, false))
|
||||
.then((commandsArray) => this.write(commandsArray));
|
||||
}
|
||||
resolve();
|
||||
chain.then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1358,8 +1489,6 @@ function OpenBCIFactory () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isConnected()) return reject('Must be connected');
|
||||
|
||||
var delayInMS = 0;
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (this.options.verbose) {
|
||||
if (pInput && !nInput) {
|
||||
@@ -1382,18 +1511,15 @@ function OpenBCIFactory () {
|
||||
if (this.options.verbose) console.log('pInput: ' + pInput + ' nInput: ' + nInput);
|
||||
// Get impedance settings to send the board
|
||||
k.getImpedanceSetter(channelNumber, pInput, nInput).then((commandsArray) => {
|
||||
this.write(commandsArray);
|
||||
// delayInMS += commandsArray.length * k.OBCIWriteIntervalDelayMSLong
|
||||
delayInMS += this.commandsToWrite * k.OBCIWriteIntervalDelayMSShort; // Account for commands waiting to be sent in the write buffer
|
||||
setTimeout(() => {
|
||||
/**
|
||||
* If either pInput or nInput are true then we should start calculating impedance. Setting
|
||||
* this.impedanceTest.active to true here allows us to route every sample for an impedance
|
||||
* calculation instead of the normal sample output.
|
||||
*/
|
||||
if (pInput || nInput) this.impedanceTest.active = true;
|
||||
resolve(channelNumber);
|
||||
}, delayInMS); // Prevents emitting .impedanceArray before all setting commands have been applied
|
||||
return this.write(commandsArray);
|
||||
}).then(() => {
|
||||
/**
|
||||
* If either pInput or nInput are true then we should start calculating impedance. Setting
|
||||
* this.impedanceTest.active to true here allows us to route every sample for an impedance
|
||||
* calculation instead of the normal sample output.
|
||||
*/
|
||||
if (pInput || nInput) this.impedanceTest.active = true;
|
||||
resolve(channelNumber);
|
||||
}, (err) => {
|
||||
reject(err);
|
||||
});
|
||||
@@ -1494,7 +1620,7 @@ function OpenBCIFactory () {
|
||||
* response from the board.
|
||||
* @param recordingDuration {String} - The duration you want to log SD information for. Limited to:
|
||||
* '14sec', '5min', '15min', '30min', '1hour', '2hour', '4hour', '12hour', '24hour'
|
||||
* @returns {Promise} - Resolves if the command was added to write queue.
|
||||
* @returns {Promise} - Resolves when the command has been written.
|
||||
* @private
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
@@ -1517,7 +1643,7 @@ function OpenBCIFactory () {
|
||||
/**
|
||||
* @description Sends the stop SD logging command to the board. If not streaming then `eot` event will be emitted
|
||||
* with request response from the board.
|
||||
* @returns {Promise} - Resovles if added to the write queue
|
||||
* @returns {Promise} - Resolves when written
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
OpenBCIBoard.prototype.sdStop = function () {
|
||||
@@ -1593,8 +1719,7 @@ function OpenBCIFactory () {
|
||||
this.sync.curSyncObj = openBCISample.newSyncObject();
|
||||
this.sync.curSyncObj.timeSyncSent = this.time();
|
||||
this.curParsingMode = k.OBCIParsingTimeSyncSent;
|
||||
this._writeAndDrain(k.OBCISyncTimeSet);
|
||||
resolve();
|
||||
this._writeAndDrain(k.OBCISyncTimeSet).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1691,8 +1816,8 @@ function OpenBCIFactory () {
|
||||
case k.OBCIParsingEOT:
|
||||
if (openBCISample.doesBufferHaveEOT(data)) {
|
||||
this.curParsingMode = k.OBCIParsingNormal;
|
||||
this.emit('eot', data);
|
||||
this.buffer = null;
|
||||
this.emit(k.OBCIEmitterEot, data);
|
||||
this.buffer = openBCISample.stripToEOTBuffer(data);
|
||||
} else {
|
||||
this.buffer = data;
|
||||
}
|
||||
@@ -1701,9 +1826,31 @@ function OpenBCIFactory () {
|
||||
// Does the buffer have an EOT in it?
|
||||
if (openBCISample.doesBufferHaveEOT(data)) {
|
||||
this._processParseBufferForReset(data);
|
||||
this.curParsingMode = k.OBCIParsingNormal;
|
||||
this.buffer = null;
|
||||
this.emit('ready');
|
||||
if (this.options.hardSet) {
|
||||
if (this.getBoardType() !== this.options.boardType) {
|
||||
this.emit(k.OBCIEmitterHardSet);
|
||||
this.hardSetBoardType(this.options.boardType)
|
||||
.then(() => {
|
||||
this.emit(k.OBCIEmitterReady)
|
||||
})
|
||||
.catch((err) => {
|
||||
this.emit(k.OBCIEmitterError, err);
|
||||
});
|
||||
|
||||
} else {
|
||||
this.curParsingMode = k.OBCIParsingNormal;
|
||||
this.emit(k.OBCIEmitterReady);
|
||||
this.buffer = openBCISample.stripToEOTBuffer(data);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (this.getBoardType() !== this.options.boardType && this.options.verbose) {
|
||||
console.log(`Module detected ${this.getBoardType()} board type but you specified ${this.options.boardType}, use 'hardSet' to force the module to correct itself`);
|
||||
}
|
||||
this.curParsingMode = k.OBCIParsingNormal;
|
||||
this.emit(k.OBCIEmitterReady);
|
||||
this.buffer = openBCISample.stripToEOTBuffer(data);
|
||||
}
|
||||
} else {
|
||||
this.buffer = data;
|
||||
}
|
||||
@@ -1795,20 +1942,17 @@ function OpenBCIFactory () {
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Alters the global info object by parseing an incoming soft reset key
|
||||
* @param dataBuffer {Buffer} - The soft reset data buffer
|
||||
* @private
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
* @description Alters the global info object by parseing an incoming soft reset key
|
||||
* @param dataBuffer {Buffer} - The soft reset data buffer
|
||||
* @returns {Buffer} - If there is data left in the buffer, just it will be returned.
|
||||
* @private
|
||||
* @author AJ Keller (@pushtheworldllc)
|
||||
*/
|
||||
OpenBCIBoard.prototype._processParseBufferForReset = function (dataBuffer) {
|
||||
if (openBCISample.countADSPresent(dataBuffer) === 2) {
|
||||
this.info.boardType = k.OBCIBoardDaisy;
|
||||
this.info.numberOfChannels = k.OBCINumberOfChannelsDaisy;
|
||||
this.info.sampleRate = k.OBCISampleRate125;
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDaisy);
|
||||
} else {
|
||||
this.info.boardType = k.OBCIBoardDefault;
|
||||
this.info.numberOfChannels = k.OBCINumberOfChannelsDefault;
|
||||
this.info.sampleRate = k.OBCISampleRate250;
|
||||
this.overrideInfoForBoardType(k.OBCIBoardDefault);
|
||||
}
|
||||
|
||||
if (openBCISample.findV2Firmware(dataBuffer)) {
|
||||
|
||||
+19
-3
@@ -156,6 +156,11 @@ const obciMiscSoftReset = 'v';
|
||||
/** 16 Channel Commands */
|
||||
const obciChannelMaxNumber8 = 'c';
|
||||
const obciChannelMaxNumber16 = 'C';
|
||||
const obciChannelMaxNumber8NoDaisyToRemove = '';
|
||||
const obciChannelMaxNumber8SuccessDaisyRemoved = 'daisy removed';
|
||||
const obciChannelMaxNumber16DaisyAlreadyAttached = '16';
|
||||
const obciChannelMaxNumber16DaisyAttached = 'daisy attached16';
|
||||
const obciChannelMaxNumber16NoDaisyAttached = 'no daisy to attach!8';
|
||||
|
||||
/** 60Hz line filter */
|
||||
const obciFilterDisable = 'g';
|
||||
@@ -335,7 +340,9 @@ const obciRadioBaudRateFastStr = 'fast';
|
||||
/** Emitters */
|
||||
const obciEmitterClose = 'close';
|
||||
const obciEmitterDroppedPacket = 'droppedPacket';
|
||||
const obciEmitterEot = 'eot';
|
||||
const obciEmitterError = 'error';
|
||||
const obciEmitterHardSet = 'hardSet';
|
||||
const obciEmitterImpedanceArray = 'impedanceArray';
|
||||
const obciEmitterQuery = 'query';
|
||||
const obciEmitterRawDataPacket = 'rawDataPacket';
|
||||
@@ -724,6 +731,11 @@ module.exports = {
|
||||
/** 16 Channel Commands */
|
||||
OBCIChannelMaxNumber8: obciChannelMaxNumber8,
|
||||
OBCIChannelMaxNumber16: obciChannelMaxNumber16,
|
||||
OBCIChannelMaxNumber8NoDaisyToRemove: obciChannelMaxNumber8NoDaisyToRemove,
|
||||
OBCIChannelMaxNumber8SuccessDaisyRemoved: obciChannelMaxNumber8SuccessDaisyRemoved,
|
||||
OBCIChannelMaxNumber16DaisyAlreadyAttached: obciChannelMaxNumber16DaisyAlreadyAttached,
|
||||
OBCIChannelMaxNumber16DaisyAttached: obciChannelMaxNumber16DaisyAttached,
|
||||
OBCIChannelMaxNumber16NoDaisyAttached: obciChannelMaxNumber16NoDaisyAttached,
|
||||
/** Filters */
|
||||
OBCIFilterDisable: obciFilterDisable,
|
||||
OBCIFilterEnable: obciFilterEnable,
|
||||
@@ -894,7 +906,9 @@ module.exports = {
|
||||
/** Emitters */
|
||||
OBCIEmitterClose: obciEmitterClose,
|
||||
OBCIEmitterDroppedPacket: obciEmitterDroppedPacket,
|
||||
OBCIEmitterEot: obciEmitterEot,
|
||||
OBCIEmitterError: obciEmitterError,
|
||||
OBCIEmitterHardSet: obciEmitterHardSet,
|
||||
OBCIEmitterImpedanceArray: obciEmitterImpedanceArray,
|
||||
OBCIEmitterQuery: obciEmitterQuery,
|
||||
OBCIEmitterRawDataPacket: obciEmitterRawDataPacket,
|
||||
@@ -926,7 +940,10 @@ module.exports = {
|
||||
* false -> Disconnect all N inputs from SRB1 (default))
|
||||
* Select to connect (true) all channels' N inputs to SRB1. This effects all pins,
|
||||
* and disconnects all N inputs from the ADC.
|
||||
* @returns {Promise} resolves array of commands to be sent, rejects on bad input or no board
|
||||
* @returns {Promise} resolves {commandArray: array of commands to be sent,
|
||||
newChannelSettingsObject: an updated channel settings object
|
||||
to be stored in openBCIBoard.channelSettingsArray},
|
||||
rejects on bad input or no board
|
||||
*/
|
||||
function channelSetter (channelNumber, powerDown, gain, inputType, bias, srb2, srb1) {
|
||||
// Used to store and assemble the commands
|
||||
@@ -991,8 +1008,7 @@ function channelSetter (channelNumber, powerDown, gain, inputType, bias, srb2, s
|
||||
cmdSrb1,
|
||||
obciChannelCmdLatch
|
||||
];
|
||||
// console.log(outputArray)
|
||||
resolve(outputArray, newChannelSettingsObject);
|
||||
resolve({commandArray: outputArray, newChannelSettingsObject: newChannelSettingsObject});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -522,6 +522,7 @@ var sampleModule = {
|
||||
makeTailByteFromPacketType,
|
||||
isStopByte,
|
||||
newSyncObject,
|
||||
stripToEOTBuffer,
|
||||
/**
|
||||
* @description Checks to make sure the previous sample number is one less
|
||||
* then the new sample number. Takes into account sample numbers wrapping
|
||||
@@ -1111,6 +1112,31 @@ function isSuccessInBuffer (dataBuffer) {
|
||||
return s.matches >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Used to slice a buffer for the EOT '$$$'.
|
||||
* @param dataBuffer {Buffer} - The buffer of some length to parse
|
||||
* @returns {Buffer} - The remaining buffer.
|
||||
*/
|
||||
function stripToEOTBuffer (dataBuffer) {
|
||||
let indexOfEOT = dataBuffer.indexOf(k.OBCIParseEOT);
|
||||
if (indexOfEOT >= 0) {
|
||||
indexOfEOT += k.OBCIParseEOT.length;
|
||||
} else {
|
||||
return dataBuffer;
|
||||
}
|
||||
|
||||
if (indexOfEOT < dataBuffer.byteLength) {
|
||||
if (k.getVersionNumber(process.version) >= 6) {
|
||||
// From introduced in node version 6.x.x
|
||||
return Buffer.from(dataBuffer.slice(indexOfEOT));
|
||||
} else {
|
||||
return new Buffer(dataBuffer.slice(indexOfEOT));
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Used to parse a buffer for the `,` character that is acked back after a time sync request is sent
|
||||
* @param dataBuffer {Buffer} - The buffer of some length to parse
|
||||
|
||||
+28
-1
@@ -15,6 +15,7 @@ function OpenBCISimulatorFactory () {
|
||||
alpha: true,
|
||||
boardFailure: false,
|
||||
daisy: false,
|
||||
daisyCanBeAttached: true,
|
||||
drift: 0,
|
||||
firmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2],
|
||||
fragmentation: [k.OBCISimulatorFragmentationNone, k.OBCISimulatorFragmentationRandom, k.OBCISimulatorFragmentationFullBuffers, k.OBCISimulatorFragmentationOneByOne],
|
||||
@@ -101,11 +102,13 @@ function OpenBCISimulatorFactory () {
|
||||
// TODO: upgrade from old-style streams to stream.Duplex or stream.Transform
|
||||
util.inherits(OpenBCISimulator, stream.Stream);
|
||||
|
||||
OpenBCISimulator.prototype.flush = function () {
|
||||
OpenBCISimulator.prototype.flush = function (callback) {
|
||||
this.outputBuffered = 0;
|
||||
|
||||
clearTimeout(this.outputLoopHandle);
|
||||
this.outputLoopHandle = null;
|
||||
|
||||
if (callback) callback();
|
||||
};
|
||||
|
||||
OpenBCISimulator.prototype.isOpen = function () {
|
||||
@@ -250,6 +253,30 @@ function OpenBCISimulatorFactory () {
|
||||
}, 10);
|
||||
}
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber8:
|
||||
if (this.options.daisy) {
|
||||
this.options.daisy = false;
|
||||
this._output(new Buffer(k.OBCIChannelMaxNumber8SuccessDaisyRemoved));
|
||||
this._printEOT();
|
||||
} else {
|
||||
this._printEOT();
|
||||
}
|
||||
break;
|
||||
case k.OBCIChannelMaxNumber16:
|
||||
if (this.options.daisy) {
|
||||
this._output(new Buffer(k.OBCIChannelMaxNumber16DaisyAlreadyAttached));
|
||||
this._printEOT();
|
||||
} else {
|
||||
if (this.options.daisyCanBeAttached) {
|
||||
this.options.daisy = true;
|
||||
this._output(new Buffer(k.OBCIChannelMaxNumber16DaisyAttached));
|
||||
this._printEOT();
|
||||
} else {
|
||||
this._output(new Buffer(k.OBCIChannelMaxNumber16NoDaisyAttached));
|
||||
this._printEOT();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openbci",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"description": "The official Node.js SDK for the OpenBCI Biosensor Board.",
|
||||
"main": "openBCIBoard",
|
||||
"scripts": {
|
||||
@@ -36,6 +36,7 @@
|
||||
"sandboxed-module": "^2.0.3",
|
||||
"semistandard": "^9.0.0",
|
||||
"sinon": "^1.17.2",
|
||||
"sinon-as-promised": "^4.0.2",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"snazzy": "^5.0.0"
|
||||
},
|
||||
|
||||
+256
-54
@@ -443,6 +443,13 @@ describe('OpenBCIConstants', function () {
|
||||
it('sets max of 16', function () {
|
||||
assert.equal('C', k.OBCIChannelMaxNumber16);
|
||||
});
|
||||
it('has correct return messages', function () {
|
||||
assert.equal('', k.OBCIChannelMaxNumber8NoDaisyToRemove);
|
||||
assert.equal('daisy removed', k.OBCIChannelMaxNumber8SuccessDaisyRemoved);
|
||||
assert.equal('16', k.OBCIChannelMaxNumber16DaisyAlreadyAttached);
|
||||
assert.equal('daisy attached16', k.OBCIChannelMaxNumber16DaisyAttached);
|
||||
assert.equal('no daisy to attach!8', k.OBCIChannelMaxNumber16NoDaisyAttached);
|
||||
});
|
||||
});
|
||||
describe('On board filters', function () {
|
||||
it('disable', function () {
|
||||
@@ -792,32 +799,60 @@ describe('OpenBCIConstants', function () {
|
||||
describe('channel input selection works', function () {
|
||||
// this.timeout(5000)
|
||||
it('channel 2', function (done) {
|
||||
k.getChannelSetter(2, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[1].should.equal('2');
|
||||
k.getChannelSetter(2, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[1].should.equal('2');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(2);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('channel 5', function (done) {
|
||||
k.getChannelSetter(5, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[1].should.equal('5');
|
||||
k.getChannelSetter(5, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[1].should.equal('5');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(5);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('channel 9', function (done) {
|
||||
k.getChannelSetter(9, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[1].should.equal('Q');
|
||||
k.getChannelSetter(9, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[1].should.equal('Q');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(9);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('channel 15', function (done) {
|
||||
k.getChannelSetter(15, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[1].should.equal('U');
|
||||
k.getChannelSetter(15, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[1].should.equal('U');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(15);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -832,16 +867,30 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('power selection works', function () {
|
||||
it('on', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[2].should.equal('0');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[2].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('off', function (done) {
|
||||
k.getChannelSetter(1, true, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[2].should.equal('1');
|
||||
k.getChannelSetter(1, true, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[2].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(true);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -853,56 +902,105 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('gain selection works', function () {
|
||||
it('1x', function (done) {
|
||||
k.getChannelSetter(1, false, 1, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('0');
|
||||
k.getChannelSetter(1, false, 1, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(1);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('2x', function (done) {
|
||||
k.getChannelSetter(1, false, 2, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('1');
|
||||
k.getChannelSetter(1, false, 2, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(2);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('4x', function (done) {
|
||||
k.getChannelSetter(1, false, 4, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('2');
|
||||
k.getChannelSetter(1, false, 4, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('2');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(4);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('6x', function (done) {
|
||||
k.getChannelSetter(1, false, 6, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('3');
|
||||
k.getChannelSetter(1, false, 6, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('3');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(6);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('8x', function (done) {
|
||||
k.getChannelSetter(1, false, 8, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('4');
|
||||
k.getChannelSetter(1, false, 8, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('4');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(8);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('12x', function (done) {
|
||||
k.getChannelSetter(1, false, 12, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('5');
|
||||
k.getChannelSetter(1, false, 12, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('5');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(12);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('24x', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[3].should.equal('6');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[3].should.equal('6');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -917,64 +1015,120 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('input type', function () {
|
||||
it('normal', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('0');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('shorted', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'shorted', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('1');
|
||||
k.getChannelSetter(1, false, 24, 'shorted', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('shorted');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('biasMethod', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'biasMethod', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('2');
|
||||
k.getChannelSetter(1, false, 24, 'biasMethod', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('2');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('biasMethod');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('mvdd', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'mvdd', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('3');
|
||||
k.getChannelSetter(1, false, 24, 'mvdd', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('3');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('mvdd');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('temp', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'temp', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('4');
|
||||
k.getChannelSetter(1, false, 24, 'temp', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('4');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('temp');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('testsig', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'testSig', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('5');
|
||||
k.getChannelSetter(1, false, 24, 'testSig', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('5');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('testSig');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('biasDrp', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'biasDrp', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('6');
|
||||
k.getChannelSetter(1, false, 24, 'biasDrp', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('6');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('biasDrp');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('biasDrn', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'biasDrn', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[4].should.equal('7');
|
||||
k.getChannelSetter(1, false, 24, 'biasDrn', true, true, false).then(function (val) {
|
||||
val.commandArray[4].should.equal('7');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('biasDrn');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -989,16 +1143,30 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('bias selection works', function () {
|
||||
it('Include', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[5].should.equal('1');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[5].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('Remove', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', false, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[5].should.equal('0');
|
||||
k.getChannelSetter(1, false, 24, 'normal', false, true, false).then(function (val) {
|
||||
val.commandArray[5].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(false);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -1010,16 +1178,30 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('SRB2 selection works', function () {
|
||||
it('Connect', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[6].should.equal('1');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[6].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('Disconnect', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, false, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[6].should.equal('0');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, false, false).then(function (val) {
|
||||
val.commandArray[6].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(false);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -1031,16 +1213,30 @@ describe('OpenBCIConstants', function () {
|
||||
});
|
||||
describe('SRB1 selection works', function () {
|
||||
it('Connect', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, true).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[7].should.equal('1');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, true).then(function (val) {
|
||||
val.commandArray[7].should.equal('1');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(true);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
it('Disconnect', function (done) {
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (arrayOfCommands) {
|
||||
arrayOfCommands[7].should.equal('0');
|
||||
k.getChannelSetter(1, false, 24, 'normal', true, true, false).then(function (val) {
|
||||
val.commandArray[7].should.equal('0');
|
||||
val.newChannelSettingsObject.channelNumber.should.equal(1);
|
||||
val.newChannelSettingsObject.powerDown.should.equal(false);
|
||||
val.newChannelSettingsObject.gain.should.equal(24);
|
||||
val.newChannelSettingsObject.inputType.should.equal('normal');
|
||||
val.newChannelSettingsObject.bias.should.equal(true);
|
||||
val.newChannelSettingsObject.srb2.should.equal(true);
|
||||
val.newChannelSettingsObject.srb1.should.equal(false);
|
||||
done();
|
||||
}).catch(function (err) {
|
||||
done(err);
|
||||
@@ -1251,9 +1447,15 @@ describe('OpenBCIConstants', function () {
|
||||
it('Event Emitter Dropped Packet', function () {
|
||||
assert.equal('droppedPacket', k.OBCIEmitterDroppedPacket);
|
||||
});
|
||||
it('Event Emitter EOT', function () {
|
||||
assert.equal('eot', k.OBCIEmitterEot);
|
||||
});
|
||||
it('Event Emitter Error', function () {
|
||||
assert.equal('error', k.OBCIEmitterError);
|
||||
});
|
||||
it('Event Emitter Hard Set', function () {
|
||||
assert.equal('hardSet', k.OBCIEmitterHardSet);
|
||||
});
|
||||
it('Event Emitter Impedance Array', function () {
|
||||
assert.equal('impedanceArray', k.OBCIEmitterImpedanceArray);
|
||||
});
|
||||
|
||||
@@ -1210,6 +1210,66 @@ $$$`);
|
||||
expect(openBCISample.droppedPacketCheck(previous, current)).to.be.null;
|
||||
});
|
||||
});
|
||||
describe('#stripToEOTBuffer', function () {
|
||||
it('should return the buffer if no EOT', function () {
|
||||
let buf = null;
|
||||
if (k.getVersionNumber(process.version) >= 6) {
|
||||
// From introduced in node version 6.x.x
|
||||
buf = Buffer.from('tacos are delicious');
|
||||
} else {
|
||||
buf = new Buffer('tacos are delicious');
|
||||
}
|
||||
expect(openBCISample.stripToEOTBuffer(buf).toString()).to.equal(buf.toString());
|
||||
});
|
||||
it('should slice the buffer after just eot $$$', function () {
|
||||
let eotBuf = null;
|
||||
let bufPost = null;
|
||||
if (k.getVersionNumber(process.version) >= 6) {
|
||||
// From introduced in node version 6.x.x
|
||||
eotBuf = Buffer.from(k.OBCIParseEOT);
|
||||
bufPost = Buffer.from('tacos');
|
||||
} else {
|
||||
eotBuf = new Buffer(k.OBCIParseEOT);
|
||||
bufPost = new Buffer('tacos');
|
||||
}
|
||||
|
||||
let totalBuf = Buffer.concat([eotBuf, bufPost]);
|
||||
expect(openBCISample.stripToEOTBuffer(totalBuf).toString()).to.equal(bufPost.toString());
|
||||
});
|
||||
it('should slice the buffer after eot $$$', function () {
|
||||
let bufPre = null;
|
||||
let eotBuf = null;
|
||||
let bufPost = null;
|
||||
if (k.getVersionNumber(process.version) >= 6) {
|
||||
// From introduced in node version 6.x.x
|
||||
bufPre = Buffer.from('tacos are delicious');
|
||||
eotBuf = Buffer.from(k.OBCIParseEOT);
|
||||
bufPost = Buffer.from('tacos');
|
||||
} else {
|
||||
bufPre = new Buffer('tacos are delicious');
|
||||
eotBuf = new Buffer(k.OBCIParseEOT);
|
||||
bufPost = new Buffer('tacos');
|
||||
}
|
||||
|
||||
let totalBuf = Buffer.concat([bufPre, eotBuf, bufPost]);
|
||||
expect(openBCISample.stripToEOTBuffer(totalBuf).toString()).to.equal(bufPost.toString());
|
||||
});
|
||||
it('should return null if nothing left', function () {
|
||||
let bufPre = null;
|
||||
let eotBuf = null;
|
||||
if (k.getVersionNumber(process.version) >= 6) {
|
||||
// From introduced in node version 6.x.x
|
||||
bufPre = Buffer.from('tacos are delicious');
|
||||
eotBuf = Buffer.from(k.OBCIParseEOT);
|
||||
} else {
|
||||
bufPre = new Buffer('tacos are delicious');
|
||||
eotBuf = new Buffer(k.OBCIParseEOT);
|
||||
}
|
||||
|
||||
let totalBuf = Buffer.concat([bufPre, eotBuf]);
|
||||
expect(openBCISample.stripToEOTBuffer(totalBuf)).to.equal(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#goertzelProcessSample', function () {
|
||||
|
||||
@@ -0,0 +1,954 @@
|
||||
'use strict';
|
||||
var bluebirdChecks = require('./bluebirdChecks');
|
||||
var sinon = require('sinon');
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
var should = chai.should(); // eslint-disable-line no-unused-vars
|
||||
var openBCIBoard = require('../openBCIBoard');
|
||||
var openBCISample = openBCIBoard.OpenBCISample;
|
||||
var k = openBCISample.k;
|
||||
var chaiAsPromised = require('chai-as-promised');
|
||||
var sinonChai = require('sinon-chai');
|
||||
var sinonAsPromised = require('sinon-as-promised')(bluebirdChecks.BluebirdPromise);
|
||||
var fs = require('fs');
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
chai.use(sinonChai);
|
||||
|
||||
describe('openbci-radios', function () {
|
||||
this.timeout(2000);
|
||||
var ourBoard, masterPortName, realBoard;
|
||||
|
||||
before(function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard();
|
||||
ourBoard.autoFindOpenBCIBoard()
|
||||
.then(portName => {
|
||||
ourBoard = null;
|
||||
realBoard = true;
|
||||
masterPortName = portName;
|
||||
done();
|
||||
})
|
||||
.catch(() => {
|
||||
ourBoard = null;
|
||||
realBoard = false;
|
||||
masterPortName = k.OBCISimulatorPortName;
|
||||
done();
|
||||
});
|
||||
});
|
||||
after(done => {
|
||||
if (ourBoard) {
|
||||
if (ourBoard['connected']) {
|
||||
ourBoard.disconnect()
|
||||
.then(() => {
|
||||
done();
|
||||
})
|
||||
.catch(err => {
|
||||
done(err);
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
describe('#radioChannelSet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
|
||||
it('should not change the channel number if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.radioChannelGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
|
||||
it('should reject if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioChannelSet(1).then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet(1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if a number is not sent as input', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet('1').should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if no channel number is presented as arg', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if the requested new channel number is lower than 0', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet(-1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if the requested new channel number is higher than 25', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet(26).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should not change the channel if the board is not communicating with the host', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorBoardFailure: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet(1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should change the channel if connected, not steaming, and using firmware version 2+', function (done) {
|
||||
var newChannelNumber = 2;
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSet(newChannelNumber).then(channelNumber => {
|
||||
expect(channelNumber).to.be.equal(newChannelNumber);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioChannelSetHostOverride', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
it('should not change the channel number if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.radioChannelSetHostOverride().should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should reject if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioChannelSetHostOverride(1).then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if a number is not sent as input', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSetHostOverride('1').should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if no channel number is presented as arg', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSetHostOverride().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if the requested new channel number is lower than 0', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSetHostOverride(-1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should reject if the requested new channel number is higher than 25', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSetHostOverride(26).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should change the channel if connected, not steaming, and using firmware version 2+', function (done) {
|
||||
var newChannelNumber = 2;
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelSetHostOverride(newChannelNumber).then(channelNumber => {
|
||||
expect(channelNumber).to.be.equal(newChannelNumber);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioChannelGet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
|
||||
it('should not query if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioChannelGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should not query if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioChannelGet().then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should not query if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should query if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelGet().then(res => {
|
||||
expect(res.channelNumber).to.be.within(k.OBCIRadioChannelMin, k.OBCIRadioChannelMax);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should get message even if the board is not communicating with dongle', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorBoardFailure: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioChannelGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioPollTimeSet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
it('should not change the channel number if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.radioPollTimeSet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
|
||||
it('should reject if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioPollTimeSet(1).then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet(1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if a number is not sent as input', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet('1').should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if no poll time is presented as arg', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if the requested new poll time is lower than 0', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet(-1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should reject if the requested new poll time is higher than 255', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet(256).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should not change the poll time if the board is not communicating with the host', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorBoardFailure: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet(1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should change the poll time if connected, not steaming, and using firmware version 2+', function (done) {
|
||||
var newPollTime = 69;
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeSet(newPollTime).then(() => {
|
||||
done();
|
||||
}).catch(err => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioPollTimeGet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
|
||||
it('should not query if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioPollTimeGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should not query if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioPollTimeGet().then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should not query if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should query if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeGet().then(pollTime => {
|
||||
expect(pollTime).to.be.greaterThan(0);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should get failure message if the board is not communicating with dongle', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorBoardFailure: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioPollTimeGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioBaudRateSet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
|
||||
it('should not try to set baud rate if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioBaudRateSet('default').should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should reject if no input', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioBaudRateSet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should be rejected if input type incorrect', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioBaudRateSet(1).should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should not try to change the baud rate if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioBaudRateSet('default').then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should not try to change the baud rate if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioBaudRateSet('default').should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should set the baud rate to default if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioBaudRateSet('default').then(baudrate => {
|
||||
expect(baudrate).to.be.equal(115200);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should set the baud rate to fast if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioBaudRateSet('fast').then(baudrate => {
|
||||
expect(baudrate).to.be.equal(230400);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioSystemStatusGet', function () {
|
||||
afterEach(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
}).catch(() => done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
afterEach(() => bluebirdChecks.noPendingPromises());
|
||||
|
||||
it('should not get system status if not connected', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.radioSystemStatusGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
it('should not get system status if streaming', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.streamStart()
|
||||
.then(() => {
|
||||
ourBoard.radioSystemStatusGet().then(() => {
|
||||
done('should have rejected');
|
||||
}).catch(() => {
|
||||
done(); // Test pass
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should not get system status if not firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioSystemStatusGet().should.be.rejected.and.notify(done);
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should get up system status if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2'
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioSystemStatusGet().then(isUp => {
|
||||
expect(isUp).to.be.true;
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should get down system status if firmware version 2', function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulate: true,
|
||||
simulatorFirmwareVersion: 'v2',
|
||||
simulatorBoardFailure: true
|
||||
});
|
||||
ourBoard.connect(k.OBCISimulatorPortName)
|
||||
.then(() => {
|
||||
ourBoard.once('ready', () => {
|
||||
ourBoard.radioSystemStatusGet().then(isUp => {
|
||||
expect(isUp).to.be.false;
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#radioTests', function () {
|
||||
this.timeout(0);
|
||||
before(function (done) {
|
||||
ourBoard = new openBCIBoard.OpenBCIBoard({
|
||||
verbose: true,
|
||||
simulatorFirmwareVersion: 'v2',
|
||||
simulatorFragmentation: k.OBCISimulatorFragmentationRandom
|
||||
});
|
||||
ourBoard.connect(masterPortName).catch(err => done(err));
|
||||
|
||||
ourBoard.once('ready', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
after(function (done) {
|
||||
if (ourBoard.isConnected()) {
|
||||
ourBoard.disconnect().then(() => {
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
after(() => bluebirdChecks.noPendingPromises());
|
||||
it('should be able to get the channel number', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
// The channel number should be between 0 and 25. Those are hard limits.
|
||||
ourBoard.radioChannelGet().then(res => {
|
||||
expect(res.channelNumber).to.be.within(0, 25);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to set the channel to 1', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioChannelSet(1).then(channelNumber => {
|
||||
expect(channelNumber).to.equal(1);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to set the channel to 2', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioChannelSet(2).then(channelNumber => {
|
||||
expect(channelNumber).to.equal(2);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to set the channel to 25', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioChannelSet(25).then(channelNumber => {
|
||||
expect(channelNumber).to.equal(25);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to set the channel to 5', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioChannelSet(5).then(channelNumber => {
|
||||
expect(channelNumber).to.equal(5);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to override host channel number, verify system is down, set the host back and verify system is up', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
var systemChanNumber = 0;
|
||||
var newChanNum = 0;
|
||||
// var timey = Date.now()
|
||||
// Get the current system channel
|
||||
ourBoard.radioChannelGet()
|
||||
.then(res => {
|
||||
// Store it
|
||||
systemChanNumber = res.channelNumber;
|
||||
// console.log(`system channel number: ${res.channelNumber}`)
|
||||
if (systemChanNumber === 25) {
|
||||
newChanNum = 24;
|
||||
} else {
|
||||
newChanNum = systemChanNumber + 1;
|
||||
}
|
||||
// Call to change just the host
|
||||
return ourBoard.radioChannelSetHostOverride(newChanNum);
|
||||
})
|
||||
.then(newChanNumActual => {
|
||||
expect(newChanNumActual).to.equal(newChanNum);
|
||||
// timey = Date.now()
|
||||
// console.log(`new chan ${newChanNumActual} got`, timey, '0ms')
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(function () {
|
||||
// console.log(`get status`, Date.now(), `${Date.now() - timey}ms`)
|
||||
ourBoard.radioSystemStatusGet().then(isUp => {
|
||||
// console.log('resolving', Date.now(), `${Date.now() - timey}ms`)
|
||||
resolve(isUp);
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
}, 270); // Should be accurate after 270 seconds
|
||||
});
|
||||
})
|
||||
.then(isUp => {
|
||||
// console.log(`isUp test`, Date.now(), `${Date.now() - timey}ms`)
|
||||
expect(isUp).to.be.false;
|
||||
return ourBoard.radioChannelSetHostOverride(systemChanNumber); // Set back to good
|
||||
})
|
||||
.then(newChanNumActual => {
|
||||
// Verify we set it back to normal
|
||||
expect(newChanNumActual).to.equal(systemChanNumber);
|
||||
return ourBoard.radioSystemStatusGet();
|
||||
})
|
||||
.then(isUp => {
|
||||
expect(isUp).to.be.true;
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it('should be able to get the poll time', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioPollTimeGet().should.eventually.be.greaterThan(0).and.notify(done);
|
||||
});
|
||||
it('should be able to set the poll time', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioPollTimeSet(80).should.become(80).and.notify(done);
|
||||
});
|
||||
it('should be able to change to default baud rate', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioBaudRateSet('default').should.become(115200).and.notify(done);
|
||||
});
|
||||
it('should be able to change to fast baud rate', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioBaudRateSet('fast').then(newBaudRate => {
|
||||
expect(newBaudRate).to.equal(230400);
|
||||
return ourBoard.radioBaudRateSet('default');
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
it('should be able to set the system status', function (done) {
|
||||
// Don't test if not using v2
|
||||
if (!ourBoard.usingVersionTwoFirmware()) return done();
|
||||
ourBoard.radioSystemStatusGet().then(isUp => {
|
||||
expect(isUp).to.be.true;
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
+419
-943
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -32,6 +32,7 @@ describe('openBCISimulator', function () {
|
||||
expect(simulator.options.alpha).to.be.true;
|
||||
expect(simulator.options.boardFailure).to.be.false;
|
||||
expect(simulator.options.daisy).to.be.false;
|
||||
expect(simulator.options.daisyCanBeAttached).to.be.true;
|
||||
expect(simulator.options.drift).to.equal(0);
|
||||
expect(simulator.options.firmwareVersion).to.equal(k.OBCIFirmwareV1);
|
||||
expect(simulator.options.lineNoise).to.equal(k.OBCISimulatorLineNoiseHz60);
|
||||
@@ -272,12 +273,69 @@ describe('openBCISimulator', function () {
|
||||
simulator.once('open', done);
|
||||
});
|
||||
afterEach(() => {
|
||||
simulator.removeAllListeners('data');
|
||||
simulator = null;
|
||||
});
|
||||
describe('set max channels', function () {
|
||||
this.timeout(100);
|
||||
it('should send nothing if no daisy attached', function (done) {
|
||||
simulator.options.daisy = false;
|
||||
simulator.on('data', function (data) {
|
||||
expect(data.toString().match(k.OBCIParseEOT)).to.not.equal(null);
|
||||
if (data.toString().match(k.OBCIParseEOT)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
simulator.write(k.OBCIChannelMaxNumber8);
|
||||
});
|
||||
it('should send daisy removed if daisy attached', function (done) {
|
||||
simulator.options.daisy = true;
|
||||
simulator.on('data', function (data) {
|
||||
expect(data.toString().match(`daisy removed${k.OBCIParseEOT}`)).to.not.equal(null);
|
||||
if (data.toString().match(k.OBCIParseEOT)) {
|
||||
expect(simulator.options.daisy).to.equal(false);
|
||||
done();
|
||||
}
|
||||
});
|
||||
simulator.write(k.OBCIChannelMaxNumber8);
|
||||
});
|
||||
it('should send just 16 if daisy already attached', function (done) {
|
||||
simulator.options.daisy = true;
|
||||
simulator.on('data', function (data) {
|
||||
expect(data.toString().match(`16${k.OBCIParseEOT}`)).to.not.equal(null);
|
||||
if (data.toString().match(k.OBCIParseEOT)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
simulator.write(k.OBCIChannelMaxNumber16);
|
||||
});
|
||||
it('should send daisy attached if able to attach', function (done) {
|
||||
simulator.options.daisy = false;
|
||||
simulator.options.daisyCanBeAttached = true;
|
||||
simulator.on('data', function (data) {
|
||||
expect(data.toString().match(`daisy attached16`)).to.not.equal(null);
|
||||
if (data.toString().match(k.OBCIParseEOT)) {
|
||||
expect(simulator.options.daisy).to.equal(true);
|
||||
done();
|
||||
}
|
||||
});
|
||||
simulator.write(k.OBCIChannelMaxNumber16);
|
||||
});
|
||||
it('should send daisy attached if not able to attach', function (done) {
|
||||
simulator.options.daisy = false;
|
||||
simulator.options.daisyCanBeAttached = false;
|
||||
simulator.on('data', function (data) {
|
||||
expect(data.toString().match(`no daisy to attach!`)).to.not.equal(null);
|
||||
if (data.toString().match(k.OBCIParseEOT)) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
simulator.write(k.OBCIChannelMaxNumber16);
|
||||
});
|
||||
});
|
||||
describe('reset', function () {
|
||||
it('should be v2', function (done) {
|
||||
simulator.on('data', function (data) {
|
||||
console.log(data.toString());
|
||||
expect(data.toString().match('v2')).to.not.equal(null);
|
||||
done();
|
||||
});
|
||||
@@ -667,7 +725,7 @@ describe('openBCISimulator', function () {
|
||||
bufferSize: bufferSize,
|
||||
latencyTime: 1000
|
||||
});
|
||||
simulator.on('data', function (buffer) {
|
||||
simulator.once('data', function (buffer) {
|
||||
expect(buffer.length).to.equal(bufferSize);
|
||||
done();
|
||||
});
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário