Skip to content

Commit a6f5d75

Browse files
author
AJ Keller
committed
ADD: daisy high speed over wifo
1 parent 407553c commit a6f5d75

File tree

5 files changed

+77
-155
lines changed

5 files changed

+77
-155
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
* Refactored library for pip
1212
* Moved plugins folder into openbci dir so plugins can be imported when installed with pip
1313

14+
15+
## Beta 0
16+
17+
* Adds high speed for Daisy over WiFi - now all boards are supported!
18+
19+
## Alpha 1
20+
21+
* Adds high speed for Ganglion over WiFi
22+
23+
## Alpha 0
24+
25+
* Adds high speed for Cyton over WiFi
26+
1427
# v0.1
1528

1629
## dev

openbci/utils/parse.py

Lines changed: 42 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -180,74 +180,55 @@ def transform_raw_data_packet_to_sample(self, raw_data):
180180
return sample
181181

182182
def make_daisy_sample_object_wifi(self, lower_sample_object, upper_sample_object):
183-
pass
184-
185-
"""
186-
/**
187-
* @description Used to make one sample object from two sample objects. The sample number of the new daisy sample will
188-
* be the upperSampleObject's sample number divded by 2. This allows us to preserve consecutive sample numbers that
189-
* flip over at 127 instead of 255 for an 8 channel. The daisySampleObject will also have one `channelData` array
190-
* with 16 elements inside it, with the lowerSampleObject in the lower indices and the upperSampleObject in the
191-
* upper set of indices. The auxData from both channels shall be captured in an object called `auxData` which
192-
* contains two arrays referenced by keys `lower` and `upper` for the `lowerSampleObject` and `upperSampleObject`,
193-
* respectively. The timestamps shall be averaged and moved into an object called `timestamp`. Further, the
194-
* un-averaged timestamps from the `lowerSampleObject` and `upperSampleObject` shall be placed into an object called
195-
* `_timestamps` which shall contain two keys `lower` and `upper` which contain the original timestamps for their
196-
* respective sampleObjects.
197-
* @param lowerSampleObject {Object} - Lower 8 channels with odd sample number
198-
* @param upperSampleObject {Object} - Upper 8 channels with even sample number
199-
* @returns {Object} - The new merged daisy sample object
200-
*/
201-
function makeDaisySampleObjectWifi (lowerSampleObject, upperSampleObject) {
202-
let daisySampleObject = {};
203-
204-
if (lowerSampleObject.hasOwnProperty('channelData')) {
205-
daisySampleObject['channelData'] = lowerSampleObject.channelData.concat(upperSampleObject.channelData);
206-
}
207-
208-
if (lowerSampleObject.hasOwnProperty('channelDataCounts')) {
209-
daisySampleObject['channelDataCounts'] = lowerSampleObject.channelDataCounts.concat(upperSampleObject.channelDataCounts);
210-
}
183+
"""
184+
/**
185+
* @description Used to make one sample object from two sample objects. The sample number of the new daisy sample will
186+
* be the upperSampleObject's sample number divded by 2. This allows us to preserve consecutive sample numbers that
187+
* flip over at 127 instead of 255 for an 8 channel. The daisySampleObject will also have one `channelData` array
188+
* with 16 elements inside it, with the lowerSampleObject in the lower indices and the upperSampleObject in the
189+
* upper set of indices. The auxData from both channels shall be captured in an object called `auxData` which
190+
* contains two arrays referenced by keys `lower` and `upper` for the `lowerSampleObject` and `upperSampleObject`,
191+
* respectively. The timestamps shall be averaged and moved into an object called `timestamp`. Further, the
192+
* un-averaged timestamps from the `lowerSampleObject` and `upperSampleObject` shall be placed into an object called
193+
* `_timestamps` which shall contain two keys `lower` and `upper` which contain the original timestamps for their
194+
* respective sampleObjects.
195+
* @param lowerSampleObject {Object} - Lower 8 channels with odd sample number
196+
* @param upperSampleObject {Object} - Upper 8 channels with even sample number
197+
* @returns {Object} - The new merged daisy sample object
198+
*/
199+
"""
200+
daisy_sample_object = OpenBCISample()
211201

212-
daisySampleObject['sampleNumber'] = upperSampleObject.sampleNumber;
202+
if lower_sample_object.channel_data is not None:
203+
daisy_sample_object.channel_data = lower_sample_object.channel_data + upper_sample_object.channel_data
213204

214-
daisySampleObject['auxData'] = {
215-
'lower': lowerSampleObject.auxData,
216-
'upper': upperSampleObject.auxData
217-
};
205+
daisy_sample_object.sample_number = upper_sample_object.sample_number
206+
daisy_sample_object.id = daisy_sample_object.sample_number
218207

219-
if (lowerSampleObject.hasOwnProperty('timestamp')) {
220-
daisySampleObject['timestamp'] = lowerSampleObject.timestamp;
221-
}
208+
daisy_sample_object.aux_data = {
209+
'lower': lower_sample_object.aux_data,
210+
'upper': upper_sample_object.aux_data
211+
}
222212

223-
daisySampleObject.stopByte = lowerSampleObject.stopByte;
213+
if lower_sample_object.timestamp:
214+
daisy_sample_object.timestamp = lower_sample_object.timestamp
224215

225-
daisySampleObject['_timestamps'] = {
226-
'lower': lowerSampleObject.timestamp,
227-
'upper': upperSampleObject.timestamp
228-
};
216+
daisy_sample_object.stop_byte = lower_sample_object.stop_byte
229217

230-
if (lowerSampleObject.hasOwnProperty('accelData')) {
231-
if (lowerSampleObject.accelData[0] > 0 || lowerSampleObject.accelData[1] > 0 || lowerSampleObject.accelData[2] > 0) {
232-
daisySampleObject.accelData = lowerSampleObject.accelData;
233-
} else {
234-
daisySampleObject.accelData = upperSampleObject.accelData;
235-
}
236-
}
218+
daisy_sample_object._timestamps = {
219+
'lower': lower_sample_object.timestamp,
220+
'upper': upper_sample_object.timestamp
221+
}
237222

238-
if (lowerSampleObject.hasOwnProperty('accelDataCounts')) {
239-
if (lowerSampleObject.accelDataCounts[0] > 0 || lowerSampleObject.accelDataCounts[1] > 0 || lowerSampleObject.accelDataCounts[2] > 0) {
240-
daisySampleObject.accelDataCounts = lowerSampleObject.accelDataCounts;
241-
} else {
242-
daisySampleObject.accelDataCounts = upperSampleObject.accelDataCounts;
243-
}
244-
}
223+
if lower_sample_object.accel_data is not None:
224+
if lower_sample_object.accel_data[0] > 0 or lower_sample_object.accel_data[1] > 0 or lower_sample_object.accel_data[2] > 0:
225+
daisy_sample_object.accel_data = lower_sample_object.accel_data
226+
else:
227+
daisy_sample_object.accel_data = upper_sample_object.accel_data
245228

246-
daisySampleObject['valid'] = true;
229+
daisy_sample_object.valid = True
247230

248-
return daisySampleObject;
249-
}
250-
"""
231+
return daisy_sample_object
251232

252233
"""
253234
/**
@@ -349,4 +330,6 @@ def __init__(self,
349330
self.sample_number = sample_number
350331
self.start_byte = start_byte
351332
self.stop_byte = stop_byte
333+
self.timestamp = 0
334+
self._timestamps = {}
352335
self.valid = valid

openbci/utils/utilities.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -62,33 +62,3 @@ def sample_packet_impedance(channel_number):
6262

6363
def sample_packet_user_defined():
6464
return bytearray([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, make_tail_byte_from_packet_type(k.OBCIStreamPacketUserDefinedType)]);
65-
66-
67-
def new_sample(sample_number):
68-
sample_number = sample_number_normalize(sample_number)
69-
return {
70-
'start_byte': k.RAW_BYTE_START,
71-
'sample_number': sample_number,
72-
'channel_data': [],
73-
'accel_data': [],
74-
'aux_data': None,
75-
'stop_byte': k.RAW_BYTE_STOP,
76-
'board_time': 0,
77-
'timestamp': 0,
78-
'valid': True
79-
}
80-
81-
82-
def new_sample_no_scale(sample_number):
83-
sample_number = sample_number_normalize(sample_number)
84-
return {
85-
'start_byte': k.RAW_BYTE_START,
86-
'sample_number': sample_number,
87-
'channel_data_counts': [],
88-
'accel_data_counts': [],
89-
'aux_data': None,
90-
'stop_byte': k.RAW_BYTE_STOP,
91-
'board_time': 0,
92-
'timestamp': 0,
93-
'valid': True
94-
}

openbci/wifi.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def handle_sample(sample):
2828
import requests
2929
import xmltodict
3030

31-
from openbci.utils import k, ParseRaw, ssdp
31+
from openbci.utils import k, ParseRaw, OpenBCISample, ssdp
3232

3333
SAMPLE_RATE = 0 # Hz
3434

@@ -486,8 +486,9 @@ def __init__(self, sock, callback=None, high_speed=True,
486486
asyncore.dispatcher_with_send.__init__(self, sock)
487487

488488
self.callback = callback
489+
self.daisy = daisy
489490
self.high_speed = high_speed
490-
self.last_odd_sample = None
491+
self.last_odd_sample = OpenBCISample()
491492
self.parser = parser if parser is not None else ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24])
492493

493494
def handle_read(self):
@@ -508,21 +509,15 @@ def handle_read(self):
508509
if ~sample.sample_number % 2:
509510
self.last_odd_sample = sample
510511
# even sample: concatenate and send if last sample was the fist part, otherwise drop the packet
511-
elif sample.sample_number - 1 == self.last_odd_sample.id:
512+
elif sample.sample_number - 1 == self.last_odd_sample.sample_number:
512513
# the aux data will be the average between the two samples, as the channel
513514
# samples themselves have been averaged by the board
514-
avg_aux_data = list(
515-
(np.array(sample.aux_data) + np.array(self.last_odd_sample.aux_data)) / 2)
516-
whole_sample = OpenBCISample(sample.id,
517-
sample.channel_data + self.last_odd_sample.channel_data,
518-
avg_aux_data)
519-
for call in callback:
520-
call(whole_sample)
515+
daisy_sample = self.parser.make_daisy_sample_object_wifi(self.last_odd_sample, sample)
516+
if self.callback is not None:
517+
self.callback(daisy_sample)
521518
else:
522-
for call in callback:
523-
call(sample)
524-
if self.callback is not None:
525-
self.callback(sample)
519+
if self.callback is not None:
520+
self.callback(sample)
526521

527522
else:
528523
try:

tests/test_parse.py

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import mock
33

44
from openbci.utils import (k,
5-
new_sample,
6-
new_sample_no_scale,
5+
OpenBCISample,
76
ParseRaw,
87
sample_packet,
98
sample_packet_standard_raw_aux,
@@ -250,104 +249,66 @@ def test_transform_raw_data_packets_to_sample(self):
250249
def test_make_daisy_sample_object_wifi(self):
251250
parser = ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24])
252251
# Make the lower sample(channels 1 - 8)
253-
lower_sample_object = new_sample(1)
252+
lower_sample_object = OpenBCISample(sample_number=1)
254253
lower_sample_object.channel_data = [1, 2, 3, 4, 5, 6, 7, 8]
255254
lower_sample_object.aux_data = [0, 1, 2]
256255
lower_sample_object.timestamp = 4
257256
lower_sample_object.accel_data = [0, 0, 0]
258257
# Make the upper sample(channels 9 - 16)
259-
upper_sample_object = new_sample(2)
260-
upper_sample_object.channelData = [9, 10, 11, 12, 13, 14, 15, 16]
261-
upper_sample_object.accelData = [0, 1, 2]
262-
lower_sample_object.auxData = [3, 4, 5]
258+
upper_sample_object = OpenBCISample(sample_number=2)
259+
upper_sample_object.channel_data = [9, 10, 11, 12, 13, 14, 15, 16]
260+
upper_sample_object.accel_data = [0, 1, 2]
261+
upper_sample_object.aux_data = [3, 4, 5]
263262
upper_sample_object.timestamp = 8
264263

265264
daisy_sample_object = parser.make_daisy_sample_object_wifi(lower_sample_object, upper_sample_object);
266265

267-
lower_sample_object_no_scale = new_sample(1)
268-
lower_sample_object_no_scale.channelDataCounts = [1, 2, 3, 4, 5, 6, 7, 8]
269-
lower_sample_object_no_scale.auxData = [0, 1, 2]
270-
lower_sample_object_no_scale.accelDataCounts = [0, 0, 0]
271-
lower_sample_object_no_scale.timestamp = 4
272-
273-
# Make the upper sample(channels 9 - 16)
274-
upper_sample_object_no_scale = new_sample(2)
275-
upper_sample_object_no_scale.channelDataCounts = [9, 10, 11, 12, 13, 14, 15, 16]
276-
lower_sample_object_no_scale.accelDataCounts = [0, 1, 2]
277-
upper_sample_object_no_scale.auxData = [3, 4, 5]
278-
upper_sample_object_no_scale.timestamp = 8
279-
280-
# Call the function under test
281-
daisy_sample_object_no_scale = parser.make_daisy_sample_object_wifi(lower_sample_object_no_scale,
282-
upper_sample_object_no_scale)
283-
284266
# should have valid object true
285267
self.assertTrue(daisy_sample_object.valid)
286-
self.assertTrue(daisy_sample_object_no_scale.valid)
287268

288269
# should make a channelData array 16 elements long
289270
self.assertEqual(len(daisy_sample_object.channel_data), k.NUMBER_OF_CHANNELS_DAISY)
290-
self.assertEqual(len(daisy_sample_object_no_scale.channel_data_counts), k.NUMBER_OF_CHANNELS_DAISY)
291271

292272
# should make a channelData array with lower array in front of upper array
293273
for i in range(16):
294274
self.assertEqual(daisy_sample_object.channel_data[i], i + 1)
295-
self.assertEqual(daisy_sample_object_no_scale.channel_data_counts[i], i + 1)
296275

276+
self.assertEqual(daisy_sample_object.id, daisy_sample_object.sample_number)
297277
self.assertEqual(daisy_sample_object.sample_number, daisy_sample_object.sample_number)
298-
self.assertEqual(daisy_sample_object_no_scale.sample_number, daisy_sample_object_no_scale.sample_number)
299278

300279
# should put the aux packets in an object
301-
self.assertIsNotNone(daisy_sample_object.aux_data.lower)
302-
self.assertIsNotNone(daisy_sample_object.aux_data.upper)
303-
self.assertIsNotNone(daisy_sample_object_no_scale.aux_data.lower)
304-
self.assertIsNotNone(daisy_sample_object_no_scale.aux_data.upper)
280+
self.assertIsNotNone(daisy_sample_object.aux_data['lower'])
281+
self.assertIsNotNone(daisy_sample_object.aux_data['upper'])
305282

306283
# should put the aux packets in an object in the right order
307284
for i in range(3):
308285
self.assertEqual(daisy_sample_object.aux_data['lower'][i], i)
309286
self.assertEqual(daisy_sample_object.aux_data['upper'][i], i + 3)
310-
self.assertEqual(daisy_sample_object_no_scale.aux_data['lower'][i], i)
311-
self.assertEqual(daisy_sample_object_no_scale.aux_data['upper'][i], i + 3)
312287

313288
# should take the lower timestamp
314289
self.assertEqual(daisy_sample_object.timestamp, lower_sample_object.timestamp)
315-
self.assertEqual(daisy_sample_object_no_scale.timestamp, lower_sample_object.timestamp)
316290

317291
# should take the lower stopByte
318292
self.assertEqual(daisy_sample_object.stop_byte, lower_sample_object.stop_byte)
319-
self.assertEqual(daisy_sample_object_no_scale.stop_byte, lower_sample_object.stop_byte)
320293

321294
# should place the old timestamps in an object
322-
self.assertEqual(daisy_sample_object._timestamps.lower, lower_sample_object.timestamp)
323-
self.assertEqual(daisy_sample_object._timestamps.upper, upper_sample_object.timestamp)
324-
self.assertEqual(daisy_sample_object_no_scale._timestamps.lower, lower_sample_object_no_scale.timestamp)
325-
self.assertEqual(daisy_sample_object_no_scale._timestamps.upper, upper_sample_object_no_scale.timestamp)
295+
self.assertEqual(daisy_sample_object._timestamps['lower'], lower_sample_object.timestamp)
296+
self.assertEqual(daisy_sample_object._timestamps['upper'], upper_sample_object.timestamp)
326297

327298
# should store an accelerometer value if present
328299
self.assertIsNotNone(daisy_sample_object.accel_data)
329300
self.assertListEqual(daisy_sample_object.accel_data, [0, 1, 2])
330-
self.assertIsNotNone(daisy_sample_object_no_scale.accel_data_counts)
331-
self.assertListEqual(daisy_sample_object_no_scale.accel_data_counts, [0, 1, 2])
332301

333-
lower_sample = new_sample(1)
302+
lower_sample = OpenBCISample(sample_number=1)
334303
lower_sample.accel_data = [0, 1, 2]
335-
upper_sample = new_sample(2)
304+
upper_sample = OpenBCISample(sample_number=2)
336305
upper_sample.accel_data = [0, 0, 0]
337306

338-
lower_sample_no_scale = new_sample_no_scale(1)
339-
lower_sample_no_scale.accel_data_counts = [0, 1, 2]
340-
upper_sample_no_scale = new_sample_no_scale(2)
341-
upper_sample_no_scale.accel_data_counts = [0, 0, 0]
342-
343307
# Call the function under test
344308
daisy_sample = parser.make_daisy_sample_object_wifi(lower_sample, upper_sample)
345-
daisy_sample_no_scale = parser.make_daisy_sample_object_wifi(lower_sample_no_scale, upper_sample_no_scale)
346309

347310
self.assertIsNotNone(daisy_sample.accel_data)
348311
self.assertListEqual(daisy_sample.accel_data, [0, 1, 2])
349-
self.assertIsNotNone(daisy_sample_no_scale.accel_data_counts)
350-
self.assertListEqual(daisy_sample_no_scale.accel_data_counts, [0, 1, 2])
351312

352313

353314
if __name__ == '__main__':

0 commit comments

Comments
 (0)