Skip to content

Commit af9f086

Browse files
author
AJ Keller
committed
Fix #131 and add example for daisy with hardset
1 parent a2b4d73 commit af9f086

File tree

5 files changed

+213
-5
lines changed

5 files changed

+213
-5
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### New Features
44
* New simulator option `simulatorDaisyModuleCanBeAttached` - Boolean, deafults to true, allows the simulation of the a hot swapped daisy board or simulates a misinformed module.
55
* 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.
6+
* Add example for streaming with `daisy` and `hardSet`.
67

78
### Breaking changes
89
* `.setInfoForBoardType()` changed to `.overrideInfoForBoardType()` to elevate it's dangerous nature.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* This is an example from the readme.md
3+
* On windows you should run with PowerShell not git bash.
4+
* Install
5+
* [nodejs](https://nodejs.org/en/)
6+
*
7+
* To run:
8+
* change directory to this file `cd examples/debug`
9+
* do `npm install`
10+
* then `npm start`
11+
*/
12+
var debug = false; // Pretty print any bytes in and out... it's amazing...
13+
var verbose = true; // Adds verbosity to functions
14+
15+
var OpenBCIBoard = require('openbci').OpenBCIBoard;
16+
var ourBoard = new OpenBCIBoard({
17+
boardType: 'daisy',
18+
debug: debug,
19+
hardSet: true,
20+
verbose: verbose
21+
});
22+
23+
ourBoard.on('error', (err) => {
24+
console.log(err);
25+
});
26+
27+
ourBoard.autoFindOpenBCIBoard().then(portName => {
28+
if (portName) {
29+
/**
30+
* Connect to the board with portName
31+
* Only works if one board is plugged in
32+
* i.e. ourBoard.connect(portName).....
33+
*/
34+
ourBoard.connect(portName) // Port name is a serial port name, see `.listPorts()`
35+
.then(() => {
36+
ourBoard.once('ready',() => {
37+
ourBoard.streamStart();
38+
ourBoard.on('sample',(sample) => {
39+
/** Work with sample */
40+
for (var i = 0; i < ourBoard.numberOfChannels(); i++) {
41+
console.log("Channel " + (i + 1) + ": " + sample.channelData[i].toFixed(8) + " Volts.");
42+
// prints to the console
43+
// "Channel 1: 0.00001987 Volts."
44+
// "Channel 2: 0.00002255 Volts."
45+
// ...
46+
// "Channel 16: -0.00001875 Volts."
47+
}
48+
});
49+
});
50+
});
51+
} else {
52+
/** Unable to auto find OpenBCI board */
53+
console.log('Unable to auto find OpenBCI board');
54+
}
55+
});
56+
57+
function exitHandler (options, err) {
58+
if (options.cleanup) {
59+
if (verbose) console.log('clean');
60+
/** Do additional clean up here */
61+
}
62+
if (err) console.log(err.stack);
63+
if (options.exit) {
64+
if (verbose) console.log('exit');
65+
ourBoard.disconnect().catch(console.log);
66+
}
67+
}
68+
69+
if (process.platform === "win32") {
70+
const rl = require("readline").createInterface({
71+
input: process.stdin,
72+
output: process.stdout
73+
});
74+
75+
rl.on("SIGINT", function () {
76+
process.emit("SIGINT");
77+
});
78+
}
79+
80+
// do something when app is closing
81+
process.on('exit', exitHandler.bind(null, {
82+
cleanup: true
83+
}));
84+
85+
// catches ctrl+c event
86+
process.on('SIGINT', exitHandler.bind(null, {
87+
exit: true
88+
}));
89+
90+
// catches uncaught exceptions
91+
process.on('uncaughtException', exitHandler.bind(null, {
92+
exit: true
93+
}));
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "get-streaming-daisy",
3+
"version": "1.0.0",
4+
"description": "Get streaming with hard set daisy example",
5+
"main": "getStreaming.js",
6+
"scripts": {
7+
"start": "node getStreamingDaisy.js",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"keywords": [
11+
"get"
12+
],
13+
"author": "AJ Keller",
14+
"license": "MIT",
15+
"dependencies": {
16+
"openbci": "^1.5.0"
17+
}
18+
}

openBCIBoard.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,10 +1088,6 @@ function OpenBCIFactory () {
10881088
return new Promise((resolve, reject) => {
10891089
const eotFunc = (data) => {
10901090
switch (data.slice(0, data.length - k.OBCIParseEOT.length).toString()) {
1091-
case k.OBCIChannelMaxNumber8NoDaisyToRemove:
1092-
this.overrideInfoForBoardType(k.OBCIBoardDefault);
1093-
resolve('no daisy to remove');
1094-
break;
10951091
case k.OBCIChannelMaxNumber8SuccessDaisyRemoved:
10961092
this.overrideInfoForBoardType(k.OBCIBoardDefault);
10971093
resolve('daisy removed');
@@ -1108,8 +1104,10 @@ function OpenBCIFactory () {
11081104
this.overrideInfoForBoardType(k.OBCIBoardDefault);
11091105
reject('unable to attach daisy');
11101106
break;
1107+
case k.OBCIChannelMaxNumber8NoDaisyToRemove:
11111108
default:
1112-
reject(Error('invalid return, board may not be configured correctly.'));
1109+
this.overrideInfoForBoardType(k.OBCIBoardDefault);
1110+
resolve('no daisy to remove');
11131111
break;
11141112
}
11151113
};

test/openBCIBoard-test.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,104 @@ describe('openbci-sdk', function () {
756756
done();
757757
}
758758
});
759+
it('daisy attached in soft reset, daisy requested by user in options, module is successful', function (done) {
760+
if (ourBoard.isSimulating()) {
761+
// Turn hardSet on
762+
ourBoard.options.hardSet = true;
763+
// Set the options to daisy boardType
764+
ourBoard.options.boardType = k.OBCIBoardDaisy;
765+
// The simulator does have a daisy
766+
ourBoard.options.simulatorDaisyModuleAttached = true;
767+
// The simulator is able to attach daisy
768+
ourBoard.options.simulatorDaisyModuleCanBeAttached = true;
769+
const failTestWithErr = (err) => {
770+
ourBoard.options.hardSet = false;
771+
ourBoard.disconnect().then(() => { // call disconnect
772+
done(err);
773+
}).catch(() => {
774+
done(err);
775+
});
776+
};
777+
var hardSetFuncFailure = () => {
778+
ourBoard.removeListener('ready', readyFuncSuccess);
779+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
780+
failTestWithErr('should not hardSet');
781+
};
782+
var errorFuncTestFailure = () => {
783+
ourBoard.removeListener('ready', readyFuncSuccess);
784+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
785+
failTestWithErr('should not error');
786+
};
787+
var readyFuncSuccess = () => {
788+
ourBoard.removeListener('error', errorFuncTestFailure);
789+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
790+
// Verify the module is still default
791+
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardDaisy);
792+
ourBoard.options.hardSet = false;
793+
ourBoard.disconnect().then(() => { // call disconnect
794+
done();
795+
}).catch(() => {
796+
done();
797+
});
798+
};
799+
800+
ourBoard.once('error', errorFuncTestFailure);
801+
ourBoard.once('ready', readyFuncSuccess);
802+
ourBoard.once('hardSet', hardSetFuncFailure);
803+
ourBoard.connect(masterPortName).catch(err => done(err));
804+
} else {
805+
done();
806+
}
807+
});
808+
it('no daisy attached in soft reset, default requested by user in options, module is successful', function (done) {
809+
if (ourBoard.isSimulating()) {
810+
// Turn hardSet on
811+
ourBoard.options.hardSet = true;
812+
// Set the options to default boardType
813+
ourBoard.options.boardType = k.OBCIBoardDefault;
814+
// The simulator does not have a daisy
815+
ourBoard.options.simulatorDaisyModuleAttached = false;
816+
// The simulator is able to attach daisy
817+
ourBoard.options.simulatorDaisyModuleCanBeAttached = false;
818+
const failTestWithErr = (err) => {
819+
ourBoard.options.hardSet = false;
820+
ourBoard.disconnect().then(() => { // call disconnect
821+
done(err);
822+
}).catch(() => {
823+
done(err);
824+
});
825+
};
826+
var hardSetFuncFailure = () => {
827+
ourBoard.removeListener('ready', readyFuncSuccess);
828+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
829+
failTestWithErr('should not hard set');
830+
};
831+
var errorFuncTestFailure = () => {
832+
ourBoard.removeListener('ready', readyFuncSuccess);
833+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
834+
failTestWithErr('should not emit error');
835+
};
836+
var readyFuncSuccess = () => {
837+
ourBoard.removeListener('error', errorFuncTestFailure);
838+
ourBoard.removeListener('hardSet', hardSetFuncFailure);
839+
// Verify the module is still default
840+
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardDefault);
841+
ourBoard.options.hardSet = false;
842+
ourBoard.disconnect().then(() => { // call disconnect
843+
done();
844+
}).catch(() => {
845+
done();
846+
});
847+
};
848+
849+
ourBoard.once('error', errorFuncTestFailure);
850+
ourBoard.once('ready', readyFuncSuccess);
851+
ourBoard.once('hardSet', hardSetFuncFailure);
852+
ourBoard.connect(masterPortName).catch(err => done(err));
853+
} else {
854+
done();
855+
}
856+
});
759857
});
760858
describe('#connected', function () {
761859
beforeEach(function (done) {

0 commit comments

Comments
 (0)