diff --git a/README.md b/README.md index 2fe9742..e78b0f7 100644 --- a/README.md +++ b/README.md @@ -514,6 +514,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. +### .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}} + ### .getSettingsForChannel(channelNumber) Gets the specified channelSettings register data from printRegisterSettings call. @@ -841,6 +847,34 @@ Stop logging to the SD card and close any open file. If you are not streaming wh **_Returns_** resolves if the command was added to the write queue. +### .setInfoForBoardType(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`. + +**_Returns_** a promise, fulfilled if the command was sent to the write queue. Rejects if input is not `8` or `16`. + +### .setMaxChannels(numberOfChannels) + +Sends a command to the board to set the max channels. If you have a daisy attached, calling this function will re-sniff for the daisy ADS and attempt to use it. + +**_numberOfChannels_** + +A Number indicating the number of channels. + +* `8` - Default number of channels. +* `16` - Daisy number of channels. + +**_Returns_** a promise, fulfilled if the command was sent to the write queue. Rejects if input is not `8` or `16`. + ### .simulatorEnable() To enter simulate mode. Must call [`.connect()`](#method-connect) after. diff --git a/changelog.md b/changelog.md index 7695e26..6e1695f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,13 @@ +# 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 `.setInfoForBoardType()` see readme.md +* Get info for the core obhect 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 diff --git a/openBCIBoard.js b/openBCIBoard.js index cb01d5d..db8f2f5 100644 --- a/openBCIBoard.js +++ b/openBCIBoard.js @@ -1012,6 +1012,53 @@ function OpenBCIFactory () { }); }; + /** + * 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.setInfoForBoardType = function(boardType) { + switch (boardType) { + case k.OBCIBoardDaisy: + this.info.boardType = k.OBCIBoardDaisy; + this.info.numberOfChannels = k.OBCINumberOfChannelsDaisy; + this.info.sampleRate = k.OBCISampleRate125; + break; + case k.OBCIBoardDefault: + default: + this.info.boardType = k.OBCIBoardDefault; + this.info.numberOfChannels = k.OBCINumberOfChannelsDefault; + this.info.sampleRate = k.OBCISampleRate250; + break; + } + }; + + /** + * Used to set the max number of channels on the Cyton board. + * @param numberOfChannels {number} + * Either 8 or 16 + * @return {Promise} + */ + OpenBCIBoard.prototype.setMaxChannels = function (numberOfChannels) { + if (numberOfChannels === k.OBCINumberOfChannelsDefault) { + this.curParsingMode = k.OBCIParsingEOT; + return this.write(k.OBCIChannelMaxNumber8); + } else if (numberOfChannels === k.OBCINumberOfChannelsDaisy) { + this.curParsingMode = k.OBCIParsingEOT; + return this.write(k.OBCIChannelMaxNumber16); + } else { + return Promise.reject('invalid number of channels'); + } + }; + /** * @description Sends a soft reset command to the board * @returns {Promise} @@ -1807,13 +1854,9 @@ function OpenBCIFactory () { */ 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.setInfoForBoardType(k.OBCIBoardDaisy); } else { - this.info.boardType = k.OBCIBoardDefault; - this.info.numberOfChannels = k.OBCINumberOfChannelsDefault; - this.info.sampleRate = k.OBCISampleRate250; + this.setInfoForBoardType(k.OBCIBoardDefault); } if (openBCISample.findV2Firmware(dataBuffer)) { diff --git a/package.json b/package.json index c6109b6..d456f6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openbci", - "version": "1.4.2", + "version": "1.4.4", "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" }, diff --git a/test/openBCIBoard-test.js b/test/openBCIBoard-test.js index d4f820e..013f540 100644 --- a/test/openBCIBoard-test.js +++ b/test/openBCIBoard-test.js @@ -9,6 +9,7 @@ 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 bufferEqual = require('buffer-equal'); var fs = require('fs'); var math = require('mathjs'); @@ -451,6 +452,34 @@ describe('openbci-sdk', function () { }); }).catch(err => done(err)); }); + it('should be able to set info for default board', function () { + ourBoard.info.boardType = 'burrito'; + ourBoard.info.sampleRate = 60; + ourBoard.info.numberOfChannels = 200; + ourBoard.setInfoForBoardType('default'); + expect(ourBoard.getInfo().boardType).to.be.equal(k.OBCIBoardDefault); + expect(ourBoard.getInfo().numberOfChannels).to.be.equal(k.OBCINumberOfChannelsDefault); + expect(ourBoard.getInfo().sampleRate).to.be.equal(k.OBCISampleRate250); + }); + it('should be able to set info for daisy board', function () { + ourBoard.info.boardType = 'burrito'; + ourBoard.info.sampleRate = 60; + ourBoard.info.numberOfChannels = 200; + ourBoard.setInfoForBoardType('daisy'); + expect(ourBoard.getInfo().boardType).to.be.equal(k.OBCIBoardDaisy); + expect(ourBoard.getInfo().numberOfChannels).to.be.equal(k.OBCINumberOfChannelsDaisy); + expect(ourBoard.getInfo().sampleRate).to.be.equal(k.OBCISampleRate125); + }); + it('should set info to default on bad input string', function () { + ourBoard.info.boardType = 'burrito'; + ourBoard.info.sampleRate = 60; + ourBoard.info.numberOfChannels = 200; + ourBoard.setInfoForBoardType('taco'); + expect(ourBoard.getInfo().boardType).to.be.equal(k.OBCIBoardDefault); + expect(ourBoard.getInfo().numberOfChannels).to.be.equal(k.OBCINumberOfChannelsDefault); + expect(ourBoard.getInfo().sampleRate).to.be.equal(k.OBCISampleRate250); + }); + }); describe('#debug', function () { before(function (done) { @@ -664,7 +693,7 @@ describe('openbci-sdk', function () { ourBoard.write(k.OBCISDLogStop).should.have.been.rejected, ourBoard.write(k.OBCISDLogStop).should.have.been.rejected, ourBoard.disconnect() - ]).then(() => {+ + ]).then(() => { writeSpy.should.have.not.been.called; writeSpy.restore(); }); @@ -785,6 +814,38 @@ describe('openbci-sdk', function () { }); }); }); + describe('#setMaxChannels', function () { + before(function (done) { + if (!ourBoard.isConnected()) { + ourBoard.connect(masterPortName) + .then(done) + .catch(err => done(err)); + } else { + done(); + } + }); + it('should write the command to set channels to 8', function (done) { + ourBoard.setMaxChannels(8) + .then(() => { + setTimeout(() => { + spy.should.have.been.calledWith(k.OBCIChannelMaxNumber8); + done(); + }, 5 * k.OBCIWriteIntervalDelayMSShort); + }).catch(done); + }); + it('should write the command to set channels to 16', function (done) { + ourBoard.setMaxChannels(16) + .then(() => { + setTimeout(() => { + spy.should.have.been.calledWith(k.OBCIChannelMaxNumber16); + done(); + }, 5 * k.OBCIWriteIntervalDelayMSShort); + }).catch(done); + }); + it('should not write a command if invalid channel number', function (done) { + ourBoard.setMaxChannels(0).should.be.rejected.and.notify(done); + }); + }); // bad describe('#channelOff', function () { before(function (done) {