Skip to content

Commit ee5557d

Browse files
author
AJ Keller
committed
ADD: functions to handle impedance packet for ganglion over wifi
1 parent 143d4b5 commit ee5557d

6 files changed

+131
-21
lines changed

changelog.md

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
# 0.2.2
1+
# v0.2.3
2+
3+
### New Features
4+
5+
* Add function for parsing an impedance object `.parsePacketImpedance()`
6+
7+
# v0.2.2
28

39
### Bug Fixes
410

511
* Fix wrap around bug in extractRawBLEDataPackets
612

7-
# 0.2.1
13+
# v0.2.1
814

915
### Bug Fixes
1016

@@ -14,47 +20,47 @@
1420

1521
* Add features for `openbci-ganglion`
1622

17-
# 0.2.0
23+
# v0.2.0
1824

1925
### New Feature
2026

2127
* With scale option false, `.parsePacketStandardAccel()` `.parsePacketTimeSyncedAccel()` will now return array called will now return `accelDataCounts` property with un-scaled data.
2228

23-
# 0.1.5
29+
# v0.1.5
2430

2531
### Bug Fixes
2632

2733
* Was missing errors in constants used by ganglion and other ble projects.
2834
* Fixed getChannelData functions to support 2 channel cytons
2935

30-
# 0.1.4
36+
# v0.1.4
3137

3238
### Bug Fixes
3339

3440
* E-patch on new function added 0.1.3
3541

3642

37-
# 0.1.3
43+
# v0.1.3
3844

3945
### New Features
4046

4147
* A bunch of functions to support synchronization of channel settings with cyton. Will be used by both the Wifi and the Cyton node modules.
4248

43-
# 0.1.2
49+
# v0.1.2
4450

4551
### Bug Fixes
4652

4753
* Send counts did not work for daisy.
4854
* Sample output was inconsistent
4955
* Fixed `timeStamp` to `timestamp` this was pr #147 (thanks @alexdevmotion)
5056

51-
# 0.1.1
57+
# v0.1.1
5258

5359
### Bug Fixes
5460

5561
* Send counts did not work for daisy.
5662

57-
# 0.1.0
63+
# v0.1.0
5864

5965
### New Functions
6066

@@ -64,26 +70,26 @@
6470

6571
* Removed function called `findV2Firmware()` because it's useless with v3.0.0 firmware
6672

67-
# 0.0.10
73+
# v0.0.10
6874

6975
### New Function
7076

7177
* Add `boardTypeForNumberOfChannels()` to Constants
7278

73-
# 0.0.9
79+
# v0.0.9
7480

7581
### New Features
7682

7783
* Add impedance calculation functions from cyton
7884
* The simulator from OpenBCI_NodeJS has been ripped out and place into this library! Woo.
7985

80-
# 0.0.8
86+
# v0.0.8
8187

8288
### New Features
8389

8490
* Sample object now has property `valid` of type `boolean`, `false` when error parseing packet, `true` otherwise. On `false` there will be another property called `error` of type `string` which contains an error message.
8591

86-
# 0.0.7
92+
# v0.0.7
8793

8894
### Continuous Integration
8995

@@ -98,7 +104,7 @@
98104
* In openBCIUtilities.js add function `transformRawDataPacketToSample` to parse a single raw data packet
99105
* In openBCIConstants.js add function `rawDataToSampleObjectDefault(numChannels)` which should be used by drivers to create the object that is passed through each call to `transformRawDataPacketsToSample`
100106

101-
# 0.0.6
107+
# v0.0.6
102108

103109
### Bug Fixes
104110

@@ -114,19 +120,19 @@
114120

115121
* `getChannelDataArray` now takes object as only arg.
116122

117-
# 0.0.5
123+
# v0.0.5
118124

119125
### Bug Fixes
120126

121127
* When not scaling outputs `channelDataCounts` instead of `channelData`
122128

123-
# 0.0.4
129+
# v0.0.4
124130

125131
### Bug Fixes
126132

127133
* Fix bug where samples were not properly being extracted
128134

129-
# 0.0.2
135+
# v0.0.2
130136

131137
### Breaking Changes
132138

@@ -138,6 +144,6 @@
138144

139145
* Added a function in the sample module that parses a raw buffer of OpenBCI data, extracts raw data packets and returns the buffer with just the raw data packets removed. Allowing the user to process other data that is not a raw data.
140146

141-
# 0.0.1
147+
# v0.0.1
142148

143149
Initial release

openBCIConstants.js

+2
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ const obciStreamPacketAccelTimeSyncSet = 3; // 0011
357357
const obciStreamPacketAccelTimeSynced = 4; // 0100
358358
const obciStreamPacketRawAuxTimeSyncSet = 5; // 0101
359359
const obciStreamPacketRawAuxTimeSynced = 6; // 0110
360+
const obciStreamPacketImpedance = 7; // 0111
360361

361362
/** Time from board */
362363
const obciStreamPacketTimeByteSize = 4;
@@ -1068,6 +1069,7 @@ const constantsModule = {
10681069
OBCIStreamPacketAccelTimeSynced: obciStreamPacketAccelTimeSynced,
10691070
OBCIStreamPacketRawAuxTimeSyncSet: obciStreamPacketRawAuxTimeSyncSet,
10701071
OBCIStreamPacketRawAuxTimeSynced: obciStreamPacketRawAuxTimeSynced,
1072+
OBCIStreamPacketImpedance: obciStreamPacketImpedance,
10711073
/** fun funcs */
10721074
isNumber,
10731075
isBoolean,

openBCIUtilities.js

+39-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ let utilitiesModule = {
2828
* @property {Number} sampleNumber The sample number
2929
* @property {Array} channelData The extracted channel data
3030
* @property {Buffer} rawDataPacket The raw data packet
31+
* @property {Boolean} valid If the sample is valid
32+
*/
33+
/**
34+
* @typedef {Object} Impedance
35+
* @property {Number} channelNumber The channel number
36+
* @property {Number} impedanceValue The impedance in ohms
3137
*/
3238
/**
3339
* @typedef {Object} RawDataToSample
@@ -151,6 +157,7 @@ let utilitiesModule = {
151157
parsePacketStandardRawAux,
152158
parsePacketTimeSyncedAccel,
153159
parsePacketTimeSyncedRawAux,
160+
parsePacketImpedance,
154161
/**
155162
* @description Mainly used by the simulator to convert a randomly generated sample into a std OpenBCI V3 Packet
156163
* @param sample - A sample object
@@ -569,6 +576,9 @@ let utilitiesModule = {
569576
samplePacketRawAuxTimeSynced: sampleNumber => {
570577
return new Buffer([0xA0, sampleNumberNormalize(sampleNumber), 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0x00, 0x01, 0, 0, 0, 1, makeTailByteFromPacketType(k.OBCIStreamPacketRawAuxTimeSynced)]);
571578
},
579+
samplePacketImpedance: channelNumber => {
580+
return new Buffer([0xA0, channelNumber, 54, 52, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, makeTailByteFromPacketType(k.OBCIStreamPacketImpedance)]);
581+
},
572582
samplePacketUserDefined: () => {
573583
return new Buffer([0xA0, 0x00, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, makeTailByteFromPacketType(k.OBCIStreamPacketUserDefinedType)]);
574584
},
@@ -990,7 +1000,7 @@ function transformRawDataPacketsToSample (o) {
9901000
samples.push(sample);
9911001
if (sample.hasOwnProperty('sampleNumber')) {
9921002
o['lastSampleNumber'] = sample.sampleNumber;
993-
} else {
1003+
} else if (!sample.hasOwnProperty('impedanceValue')){
9941004
o['lastSampleNumber'] = o.rawDataPacket[k.OBCIPacketPositionSampleNumber];
9951005
}
9961006
}
@@ -1022,6 +1032,9 @@ function transformRawDataPacketToSample (o) {
10221032
case k.OBCIStreamPacketRawAuxTimeSynced:
10231033
sample = utilitiesModule.parsePacketTimeSyncedRawAux(o);
10241034
break;
1035+
case k.OBCIStreamPacketImpedance:
1036+
sample = utilitiesModule.parsePacketImpedance(o);
1037+
break;
10251038
default:
10261039
// Don't do anything if the packet is not defined
10271040
sample = {
@@ -1290,6 +1303,31 @@ function parsePacketTimeSyncedRawAux (o) {
12901303
return sampleObject;
12911304
}
12921305

1306+
/**
1307+
* @description Raw aux
1308+
* @param o {Object} - The input object
1309+
* @param o.rawDataPacket {Buffer} - The 33byte raw time synced accel packet
1310+
* @returns {Impedance} - An impedance object.
1311+
*/
1312+
function parsePacketImpedance (o) {
1313+
// Ths packet has 'A0','00'....,'AA','AA','FF','FF','FF','FF','C4'
1314+
// where the 'AA's form an accel 16bit num and 'FF's form a 32 bit time in ms
1315+
// Check to make sure data is not null.
1316+
if (k.isUndefined(o) || k.isUndefined(o.rawDataPacket) || k.isNull(o.rawDataPacket)) throw new Error(k.OBCIErrorUndefinedOrNullInput);
1317+
// Check to make sure the buffer is the right size.
1318+
if (o.rawDataPacket.byteLength !== k.OBCIPacketSize) throw new Error(k.OBCIErrorInvalidByteLength);
1319+
1320+
let impedanceObject = {};
1321+
1322+
impedanceObject.channelNumber = o.rawDataPacket[1];
1323+
if (impedanceObject.channelNumber === 5) {
1324+
impedanceObject.channelNumber = 0;
1325+
}
1326+
impedanceObject.impedanceValue = Number(o.rawDataPacket.toString().match(/\d+/)[0]);
1327+
1328+
return impedanceObject;
1329+
}
1330+
12931331
/**
12941332
* Use reg ex to parse a `str` register query for a boolean `offset` from index. Throws errors
12951333
* @param str {String} - The string to search

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openbci-utilities",
3-
"version": "0.2.2",
3+
"version": "0.2.3",
44
"description": "The official utility package of Node.js SDK for the OpenBCI Biosensor Boards.",
55
"main": "index.js",
66
"scripts": {

test/openBCIConstants-test.js

+3
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ describe('OpenBCIConstants', function () {
626626
it('Time Synced with Raw Aux', function () {
627627
assert.equal(6, k.OBCIStreamPacketRawAuxTimeSynced);
628628
});
629+
it('Time Synced with Raw Aux', function () {
630+
assert.equal(7, k.OBCIStreamPacketImpedance);
631+
});
629632
});
630633
describe('Time synced with accel packet', function () {
631634
it('X axis', function () {

test/openBCIUtilities-test.js

+62-1
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,51 @@ describe('openBCIUtilities', function () {
10281028
});
10291029
});
10301030
});
1031+
describe('#parsePacketImpedace', function () {
1032+
it('should extract the impedance value for channel 1', function () {
1033+
const expectedChannelNumber = 1;
1034+
const expectedImpedance = 641;
1035+
const rawDataPacket = openBCIUtilities.samplePacketImpedance(expectedChannelNumber);
1036+
let impedanceObject = openBCIUtilities.parsePacketImpedance({
1037+
rawDataPacket
1038+
});
1039+
expect(impedanceObject.channelNumber).to.equal(expectedChannelNumber);
1040+
expect(impedanceObject.impedanceValue).to.equal(expectedImpedance);
1041+
});
1042+
it('should extract the impedance value for channel 4', function () {
1043+
const expectedChannelNumber = 4;
1044+
const expectedImpedance = 64180;
1045+
const rawDataPacket = openBCIUtilities.samplePacketImpedance(expectedChannelNumber);
1046+
rawDataPacket[5] = 56;
1047+
rawDataPacket[6] = 48;
1048+
let impedanceObject = openBCIUtilities.parsePacketImpedance({
1049+
rawDataPacket
1050+
});
1051+
expect(impedanceObject.channelNumber).to.equal(expectedChannelNumber);
1052+
expect(impedanceObject.impedanceValue).to.equal(expectedImpedance);
1053+
});
1054+
it('should extract the impedance value for channel reference', function () {
1055+
const expectedChannelNumber = 5;
1056+
const expectedImpedance = 641;
1057+
const rawDataPacket = openBCIUtilities.samplePacketImpedance(expectedChannelNumber);
1058+
let impedanceObject = openBCIUtilities.parsePacketImpedance({
1059+
rawDataPacket
1060+
});
1061+
expect(impedanceObject.channelNumber).to.equal(0);
1062+
expect(impedanceObject.impedanceValue).to.equal(expectedImpedance);
1063+
});
1064+
describe('#errorConditions', function () {
1065+
it('send non data buffer', function () {
1066+
expect(openBCIUtilities.parsePacketImpedance.bind(openBCIUtilities, {
1067+
})).to.throw(k.OBCIErrorUndefinedOrNullInput);
1068+
});
1069+
it('wrong number of bytes', function () {
1070+
expect(openBCIUtilities.parsePacketImpedance.bind(openBCIUtilities, {
1071+
rawDataPacket: new Buffer(5)
1072+
})).to.throw(k.OBCIErrorInvalidByteLength);
1073+
});
1074+
});
1075+
});
10311076
describe('#getDataArrayAccel', function () {
10321077
it('compute scaled accel values', function () {
10331078
const accelData = openBCIUtilities.getDataArrayAccel(sampleBuf.slice(k.OBCIPacketPositionStartAux, k.OBCIPacketPositionStopAux + 1));
@@ -2837,20 +2882,22 @@ describe('#transformRawDataPacketsToSamples', function () {
28372882
* Test the function that routes raw packets for processing
28382883
*/
28392884
describe('#transformRawDataPacketToSample', function () {
2840-
var funcSpyTimeSyncedAccel, funcSpyTimeSyncedRawAux, funcSpyStandardRawAux, funcSpyStandardAccel;
2885+
var funcSpyTimeSyncedAccel, funcSpyTimeSyncedRawAux, funcSpyStandardRawAux, funcSpyStandardAccel, funcSpyImpedance;
28412886

28422887
before(function () {
28432888
// Put watchers on all functions
28442889
funcSpyStandardAccel = sinon.spy(openBCIUtilities, 'parsePacketStandardAccel');
28452890
funcSpyStandardRawAux = sinon.spy(openBCIUtilities, 'parsePacketStandardRawAux');
28462891
funcSpyTimeSyncedAccel = sinon.spy(openBCIUtilities, 'parsePacketTimeSyncedAccel');
28472892
funcSpyTimeSyncedRawAux = sinon.spy(openBCIUtilities, 'parsePacketTimeSyncedRawAux');
2893+
funcSpyImpedance = sinon.spy(openBCIUtilities, 'parsePacketImpedance');
28482894
});
28492895
beforeEach(function () {
28502896
funcSpyStandardAccel.reset();
28512897
funcSpyStandardRawAux.reset();
28522898
funcSpyTimeSyncedAccel.reset();
28532899
funcSpyTimeSyncedRawAux.reset();
2900+
funcSpyImpedance.reset();
28542901
});
28552902
after(function () {
28562903
// ourBoard = null
@@ -2895,6 +2942,7 @@ describe('#transformRawDataPacketToSample', function () {
28952942
expect(funcSpyStandardRawAux).to.not.have.been.called();
28962943
expect(funcSpyTimeSyncedAccel).to.not.have.been.called();
28972944
expect(funcSpyTimeSyncedRawAux).to.not.have.been.called();
2945+
expect(funcSpyImpedance).to.not.have.been.called();
28982946
});
28992947
it('should throw err when no channel settings', function () {
29002948
var buffer = new Buffer(5).fill(0);
@@ -2965,6 +3013,18 @@ describe('#transformRawDataPacketToSample', function () {
29653013
// Ensure that we extracted only one buffer
29663014
expect(funcSpyTimeSyncedRawAux).to.have.been.calledOnce();
29673015
});
3016+
it('should process an impedance packet', function () {
3017+
var buffer = openBCIUtilities.samplePacketImpedance(1);
3018+
3019+
// Call the function under test
3020+
openBCIUtilities.transformRawDataPacketToSample({
3021+
channelSettings: defaultChannelSettingsArray,
3022+
rawDataPacket: buffer
3023+
});
3024+
3025+
// Ensure that we extracted only one buffer
3026+
expect(funcSpyImpedance).to.have.been.calledOnce();
3027+
});
29683028
it('should not identify any packet', function () {
29693029
var buffer = openBCIUtilities.samplePacket(0);
29703030

@@ -2982,5 +3042,6 @@ describe('#transformRawDataPacketToSample', function () {
29823042
expect(funcSpyStandardRawAux).to.not.have.been.called();
29833043
expect(funcSpyTimeSyncedAccel).to.not.have.been.called();
29843044
expect(funcSpyTimeSyncedRawAux).to.not.have.been.called();
3045+
expect(funcSpyImpedance).to.not.have.been.called();
29853046
});
29863047
});

0 commit comments

Comments
 (0)