Skip to content

Commit

Permalink
Merge pull request #96 from OpenBCI/1.4.0
Browse files Browse the repository at this point in the history
1.4.0
  • Loading branch information
AJ Keller authored Oct 31, 2016
2 parents 37db876 + c4e29bb commit d4f62ef
Show file tree
Hide file tree
Showing 19 changed files with 12,231 additions and 11,622 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"extends": ["standard"], "parser": "babel-eslint"}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ hardwareVoltageOutputAll.txt

# For git
*.orig

# Text editor temporary files
.*.sw* # vi/vim
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ node_modules
.DS_Store
public
myOutput.txt
*.tgz
*.tgz
openBCISerialFormat
48 changes: 31 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![codecov](https://codecov.io/gh/OpenBCI/OpenBCI_NodeJS/branch/master/graph/badge.svg)](https://codecov.io/gh/OpenBCI/OpenBCI_NodeJS)
[![Dependency Status](https://david-dm.org/OpenBCI/OpenBCI_NodeJS.svg)](https://david-dm.org/OpenBCI/OpenBCI_NodeJS)
[![npm](https://img.shields.io/npm/dm/openbci.svg?maxAge=2592000)](http://npmjs.com/package/openbci)
[![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)

# OpenBCI Node.js SDK

Expand All @@ -24,8 +25,7 @@ The purpose of this module is to **get connected** and **start streaming** as fa
1. [Constructor](#constructor)
2. [Methods](#method)
3. [Events](#event)
4. [Properties](#property)
5. [Constants](#constants)
4. [Constants](#constants)
6. [Interfacing With Other Tools](#interfacing-with-other-tools)
7. [Developing](#developing)
8. [Testing](#testing)
Expand Down Expand Up @@ -388,18 +388,26 @@ Board optional configurations.
* `simulatorFirmwareVersion` {String} - Allows the simulator to use 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 latency timer has expired
* `oneByOne` - output each byte separately
* `simulatorLatencyTime` {Number} - The time in milliseconds to wait before sending partially full buffers of data, 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.
* `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 experiments on your local computer, keep this `false`. (Default `false`)
* `sntpTimeSyncHost` - {String} The sntp server to use, can be either sntp or ntp (Defaults `pool.ntp.org`).
* `sntpTimeSyncPort` - {Number} The port to access the sntp 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`)
**Note, we have added support for either all lowercase OR camel case for the options, use whichever style you prefer.**
Expand Down Expand Up @@ -670,6 +678,16 @@ Sends command to turn off impedances for all channels and stop continuously calc
**_Returns_** a promise, that fulfills when all the commands are sent to the internal write buffer
### <a name="method-is-connected"></a> .isConnected()
Checks if the driver is connected to a board.
**_Returns_** a boolean, true if connected
### <a name="method-is-streaming"></a> .isStreaming()
Checks if the board is currently sending samples.
**_Returns_** a boolean, true if streaming
### <a name="method-list-ports"></a> .listPorts()
List available ports so the user can choose a device when not automatically found.
Expand Down Expand Up @@ -1017,13 +1035,13 @@ Either a single character or an Array of characters
Sends a single character command to the board.
```js
// ourBoard has fulfilled the promise on .connected() and 'ready' has been observed previously
// ourBoard has fulfilled the promise on .connect() and 'ready' has been observed previously
ourBoard.write('a');
```
Sends an array of bytes
```js
// ourBoard has fulfilled the promise on .connected() and 'ready' has been observed previously
// ourBoard has fulfilled the promise on .connect() and 'ready' has been observed previously
ourBoard.write(['x','0','1','0','0','0','0','0','0','X']);
```
Expand Down Expand Up @@ -1069,15 +1087,9 @@ Emitted when the board is in a ready to start streaming state.
Emitted when there is a new sample available.
## <a name="property"></a> Properties:
### <a name="event-sample"></a> .on('synced', callback)
### <a name="property-connected"></a> connected
A bool, true if connected to an OpenBCI board, false if not.
### <a name="property-streaming"></a> streaming
A bool, true if streaming data from an OpenBCI board, false if not.
Emitted when there is a new sample available.
## <a name="constants"></a> Constants:
Expand Down Expand Up @@ -1155,10 +1167,12 @@ npm test
1. Fork it!
2. Create your feature branch: `git checkout -b my-new-feature`
3. Make changes and ensure tests all pass. (`npm test`)
4. Commit your changes: `git commit -m 'Add some feature'`
5. Push to the branch: `git push origin my-new-feature`
6. Submit a pull request :D
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
## <a name="license"></a> License:
Expand Down
35 changes: 35 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
# 1.4.0

### New Features

* Three new initialization options: `simulatorFragmentation`, `simulatorBufferSize`, and `simulatorLatencyTimer`. Together, these enable a more _realistic_ serial port simulation, mimicking different potential user computer systems.
* New option `debug` gives a live dump of serial traffic on the console if enabled
* New API function `.isConnected()` to check if communications are active.
* New API function `.isStreaming()` to check if samples are coming from the board.

### Enhancements

* Implement and adapt semi-standard code style. Closes #83
* autoFindOpenBCIBoard now notices and uses the stock dongle on Linux
* 'synced' object now has `error` property, null on good syncs, error description on bad syncs.

### Breaking Changes

* The setting for simulatorInjectLineNoise has changed from `None` to `none`
* connect() will now fail if already connected
* The constructor will throw an error now if an invalid option is passed
* The `.connected` property has been removed, replaced by `.isConnected()`. Removed from docs.
* 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

### Bug Fixes

* Fixed bug where early packet fragments were dropped after board reset
* Fixed bug where time sync replies that began a buffered chunk were ignored
* Fixed bug where simulator would output wrong version in its reset message
* Fixed bug where resources were not cleaned up if connect was called twice
* Fixed bug where serial data was written after disconnection
* Fixed bug where unexpected disconnection was not detected
* Fixed bug where promises could lead to out of order packet processing.

# 1.3.3

### New Features
Expand Down
115 changes: 55 additions & 60 deletions examples/timeSync/timeSync.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,83 +11,78 @@ var OpenBCIBoard = require('openbci').OpenBCIBoard;

var ourBoard = new OpenBCIBoard({});

const resyncPeriodMin = 5; // re sync every five minutes
const secondsInMinute = 60;
var sampleRate = 250; // Default to 250, ALWAYS verify with a call to `.sampleRate()` after 'ready' event!
var timeSyncPossible = false;

ourBoard.autoFindOpenBCIBoard().then(portName => {
if(portName) {
/**
* Connect to the board with portName
* 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*/
}
if (portName) {
/**
* Connect to the board with portName
* 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 */
}
});

var readyFunc = () => {
// 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 {
killFunc();
}
// 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 {
killFunc();
}
};

var killFunc = () => {
ourBoard.disconnect()
ourBoard.disconnect()
.then(() => {
process.kill();
process.kill();
});
}
};

var sampleFunc = sample => {
// Resynchronize every every second
if (sample._count % (sampleRate * 1) === 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}`);
// Resynchronize every every second
if (sample._count % (sampleRate * 1) === 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!`);
}
}
});
}

// Stop after one minute
if (sample._count > sampleRate * 60) {
killFunc();
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}`);
}
}

}
// Stop after one minute
if (sample._count > sampleRate * 60) {
killFunc();
}
};

// Subscribe to your functions
ourBoard.on('ready',readyFunc);
ourBoard.on('sample',sampleFunc);
ourBoard.on('ready', readyFunc);
ourBoard.on('sample', sampleFunc);
Loading

0 comments on commit d4f62ef

Please sign in to comment.