Skip to content

Commit 3c46100

Browse files
author
AJ Keller
authored
Merge pull request #84 from aj-ptw/dropped-packet-alert
Add dropped packet detection
2 parents 094e328 + 2c0b2e3 commit 3c46100

9 files changed

+135
-7
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,13 +1040,17 @@ ourBoard.write('o');
10401040
10411041
Emitted when the serial connection to the board is closed.
10421042
1043+
### <a name="event-close"></a> .on('droppedPacket', callback)
1044+
1045+
Emitted when a packet (or packets) are dropped. Returns an array.
1046+
10431047
### <a name="event-error"></a> .on('error', callback)
10441048
10451049
Emitted when there is an on the serial port.
10461050
10471051
### <a name="event-impedance-array"></a> .on('impedanceArray', callback)
10481052
1049-
Emitted when there is a new impedanceArray available.
1053+
Emitted when there is a new impedanceArray available. Returns an array.
10501054
10511055
### <a name="event-query"></a> .on('query', callback)
10521056

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# 1.3.0
2+
3+
### New Features
4+
5+
* Add dropped packet detection, new event `droppedPacket` can be added to get an array of dropped packet numbers in the case of the dropped packet event.
6+
17
# 1.2.3
28

39
### Enhancements

openBCIBoard.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,10 @@ function OpenBCIFactory() {
185185
this.curParsingMode = k.OBCIParsingReset;
186186
this.commandsToWrite = 0;
187187
this.impedanceArray = openBCISample.impedanceArray(k.numberOfChannelsForBoardType(this.options.boardType));
188-
this.writeOutDelay = k.OBCIWriteIntervalDelayMSShort;
188+
this.previousSampleNumber = -1;
189189
this.sampleCount = 0;
190190
this.timeOfPacketArrival = 0;
191+
this.writeOutDelay = k.OBCIWriteIntervalDelayMSShort;
191192
// Strings
192193

193194
// NTP
@@ -1735,6 +1736,11 @@ function OpenBCIFactory() {
17351736
OpenBCIBoard.prototype._processQualifiedPacket = function(rawDataPacketBuffer) {
17361737
if (!rawDataPacketBuffer) return;
17371738
if (rawDataPacketBuffer.byteLength !== k.OBCIPacketSize) return;
1739+
var missedPacketArray = openBCISample.droppedPacketCheck(this.previousSampleNumber, rawDataPacketBuffer[k.OBCIPacketPositionSampleNumber]);
1740+
if (missedPacketArray) {
1741+
this.emit('droppedPacket', missedPacketArray);
1742+
}
1743+
this.previousSampleNumber = rawDataPacketBuffer[k.OBCIPacketPositionSampleNumber];
17381744
var packetType = openBCISample.getRawPacketType(rawDataPacketBuffer[k.OBCIPacketPositionStopByte]);
17391745
switch (packetType) {
17401746
case k.OBCIStreamPacketStandardAccel:

openBCIConstants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ const OBCISimulatorLineNoiseNone = 'None';
199199
const OBCISampleRate125 = 125;
200200
const OBCISampleRate250 = 250;
201201

202+
/** Max sample number */
203+
const OBCISampleNumberMax = 255;
204+
202205
/** Packet Size */
203206
const OBCIPacketSize = 33;
204207

@@ -729,6 +732,8 @@ module.exports = {
729732
/** Possible Sample Rates */
730733
OBCISampleRate125,
731734
OBCISampleRate250,
735+
/** Max sample number */
736+
OBCISampleNumberMax,
732737
/** Packet Size */
733738
OBCIPacketSize,
734739
/** Notable Bytes */

openBCISample.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,42 @@ var sampleModule = {
522522
isTimeSyncSetConfirmationInBuffer,
523523
makeTailByteFromPacketType,
524524
isStopByte,
525-
newSyncObject
525+
newSyncObject,
526+
/**
527+
* @description Checks to make sure the previous sample number is one less
528+
* then the new sample number. Takes into account sample numbers wrapping
529+
* around at 255.
530+
* @param `previousSampleNumber` {Number} - An integer number of the previous
531+
* sample number.
532+
* @param `newSampleNumber` {Number} - An integer number of the new sample
533+
* number.
534+
* @returns {Array} - Returns null if there is no dropped packets, otherwise,
535+
* or on a missed packet, an array of their packet numbers is returned.
536+
*/
537+
droppedPacketCheck: (previousSampleNumber, newSampleNumber) => {
538+
if (previousSampleNumber === k.OBCISampleNumberMax && newSampleNumber === 0) {
539+
return null;
540+
}
541+
542+
if (newSampleNumber - previousSampleNumber === 1) {
543+
return null;
544+
}
545+
546+
var missedPacketArray = [];
547+
548+
if (previousSampleNumber > newSampleNumber) {
549+
var numMised = k.OBCISampleNumberMax - previousSampleNumber;
550+
for (var i = 0; i < numMised; i++) {
551+
missedPacketArray.push(previousSampleNumber + i + 1);
552+
}
553+
previousSampleNumber = -1;
554+
}
555+
556+
for (var i = 1; i < (newSampleNumber - previousSampleNumber); i++) {
557+
missedPacketArray.push(previousSampleNumber + i);
558+
}
559+
return missedPacketArray;
560+
}
526561
};
527562

528563
module.exports = sampleModule;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openbci",
3-
"version": "1.2.3",
3+
"version": "1.3.0",
44
"description": "The official Node.js SDK for the OpenBCI Biosensor Board.",
55
"main": "openBCIBoard",
66
"scripts": {

test/OpenBCIConstants-test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,11 @@ describe('OpenBCIConstants', function() {
765765
assert.equal(250, k.OBCISampleRate250);
766766
});
767767
});
768+
describe('Max sample number',function() {
769+
it('should be 255',function () {
770+
assert.equal(255, k.OBCISampleNumberMax);
771+
});
772+
});
768773
describe("Radio Channel Limits", function() {
769774
it("should get the right channel number max",function () {
770775
expect(k.OBCIRadioChannelMax).to.be.equal(25);

test/OpenBCISample-test.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ var assert = require('assert');
55
var openBCISample = require('../openBCISample');
66
var sinon = require('sinon');
77
var chai = require('chai'),
8-
expect = chai.expect,
98
should = chai.should(),
10-
expect = chai.expect;
9+
expect = chai.expect,
10+
assert = chai.assert;
1111

1212
var chaiAsPromised = require("chai-as-promised");
1313
var sinonChai = require("sinon-chai");
@@ -1373,7 +1373,41 @@ describe('openBCISample',function() {
13731373
it("should have property boardTime",function() {
13741374
expect(syncObj).to.have.property("boardTime",0);
13751375
});
1376-
})
1376+
});
1377+
describe('#droppedPacketCheck',function() {
1378+
it("should return an array of missed packet numbers",function() {
1379+
previous = 0;
1380+
current = previous + 2;
1381+
assert.sameMembers(openBCISample.droppedPacketCheck(previous, current), [1], "dropped one packet");
1382+
1383+
previous = 0;
1384+
current = previous + 4;
1385+
assert.sameMembers(openBCISample.droppedPacketCheck(previous, current), [1,2,3], "dropped three packets");
1386+
1387+
previous = 255;
1388+
current = 2;
1389+
assert.sameMembers(openBCISample.droppedPacketCheck(previous, current), [0,1], "dropped two packets on wrap edge!");
1390+
1391+
previous = 254;
1392+
current = 2;
1393+
assert.sameMembers(openBCISample.droppedPacketCheck(previous, current), [255,0,1], "dropped three packets on wrap!");
1394+
1395+
previous = 250;
1396+
current = 1;
1397+
assert.sameMembers(openBCISample.droppedPacketCheck(previous, current), [251,252,253,254,255,0], "dropped a bunch of packets on wrap!");
1398+
1399+
});
1400+
it("should roll over when 255 was previous and current is 0", function() {
1401+
previous = 255;
1402+
current = 0;
1403+
expect(openBCISample.droppedPacketCheck(previous, current)).to.be.null;
1404+
});
1405+
it("should return null when previous is one less then new sample number", function() {
1406+
previous = 0;
1407+
current = previous + 1;
1408+
expect(openBCISample.droppedPacketCheck(previous, current)).to.be.null;
1409+
});
1410+
});
13771411
});
13781412

13791413

test/openBCIBoard-test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,39 @@ describe('openbci-sdk',function() {
10101010
funcSpyTimeSyncedAccel.should.not.have.been.called;
10111011
funcSpyTimeSyncedRawAux.should.not.have.been.called;
10121012
});
1013+
it("should emit a dropped packet on dropped packet",function(done) {
1014+
// Set to default state
1015+
ourBoard.previousSampleNumber = -1;
1016+
var sampleNumber0 = openBCISample.samplePacket(0);
1017+
ourBoard.once('droppedPacket',() => {
1018+
done();
1019+
});
1020+
var sampleNumber2 = openBCISample.samplePacket(2);
1021+
// Call the function under test
1022+
ourBoard._processDataBuffer(sampleNumber0);
1023+
ourBoard._processDataBuffer(sampleNumber2);
1024+
});
1025+
it("should emit a dropped packet on dropped packet with edge",function(done) {
1026+
// Set to default state
1027+
var count = 0;
1028+
ourBoard.previousSampleNumber = 253;
1029+
var buf1 = openBCISample.samplePacket(254);
1030+
var countFunc = arr => {
1031+
count++;
1032+
};
1033+
ourBoard.on('droppedPacket', countFunc);
1034+
var buf2 = openBCISample.samplePacket(0);
1035+
var buf3 = openBCISample.samplePacket(1);
1036+
// Call the function under test
1037+
ourBoard._processDataBuffer(buf1);
1038+
ourBoard._processDataBuffer(buf2);
1039+
ourBoard._processDataBuffer(buf3);
1040+
setTimeout(() => {
1041+
ourBoard.removeListener('droppedPacket', countFunc);
1042+
expect(count).to.equal(1);
1043+
done();
1044+
}, 10)
1045+
});
10131046
});
10141047

10151048
describe("#_processPacketTimeSyncSet", function() {

0 commit comments

Comments
 (0)