Skip to content

Commit 1f0697e

Browse files
committed
ganglion: start to process notifies data
1 parent dddb8fa commit 1f0697e

File tree

1 file changed

+96
-85
lines changed

1 file changed

+96
-85
lines changed

open_bci_ganglion.py

Lines changed: 96 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ def __init__(self, port=None, baud=0, filter_data=False,
8585
print ("disconnect, properties: " + str(self.char_discon.propertiesToString()) + ", supports read: " + str(self.char_discon.supportsRead()))
8686

8787

88+
# set delegate to handle incoming data
89+
self.delegate = GanglionDelegate()
90+
self.gang.setDelegate(self.delegate)
91+
8892
print("Turn on notifications")
8993
# nead up-to-date bluepy, cf https://github.com/IanHarvey/bluepy/issues/53
9094
self.desc_notify = self.char_read.getDescriptors(forUUID=0x2902)[0]
@@ -197,98 +201,23 @@ def start_streaming(self, callback, lapse=-1):
197201
self.check_connection()
198202

199203
while self.streaming:
200-
201-
# read current sample
202-
# FIXME: several samples per packet
203-
sample = self._read_serial_binary()
204-
#for call in callback:
205-
# call(sample)
204+
# at most we will get one sample per packet
205+
self.gang.waitForNotifications(1./self.getSampleRate())
206+
# retrieve current samples on the stack
207+
samples = self.delegate.getSamples()
208+
if not samples:
209+
print("no new sample")
210+
else:
211+
for call in callback:
212+
for sample in samples:
213+
call(sample)
206214

207215
if(lapse > 0 and timeit.default_timer() - start_time > lapse):
208216
self.stop();
209217
if self.log:
210218
self.log_packet_count = self.log_packet_count + 1;
211219

212220

213-
"""
214-
PARSER:
215-
Parses incoming data packet into OpenBCISample -- see docs.
216-
FIXME: use buffer to account for missed / double packets?
217-
"""
218-
def _read_serial_binary(self):
219-
220-
print("reading packet")
221-
packet = self.ser_read()
222-
# TODO: better handling of errors...
223-
if not packet:
224-
self.warn('Device appears to be stalling.')
225-
return
226-
if len(packet) != 20:
227-
self.warn('Wrong packet size, ' + str(len(packet)) + ' instead of 20 bytes')
228-
return
229-
230-
# bluepy returnds INT with python3 and STR with python2
231-
if type(packet) is str:
232-
do_unpack = True
233-
start_byte = struct.unpack('B', packet[0])[0]
234-
else:
235-
do_unpack = False
236-
start_byte = packet[0]
237-
238-
#for b in packet:
239-
# if do_unpack:
240-
# unpac = struct.unpack('B', b)[0]
241-
# else:
242-
# unpac = b
243-
# print (str(unpac))
244-
245-
print(str(start_byte))
246-
# Raw uncompressed
247-
if start_byte == 0:
248-
print ("Raw uncompressed")
249-
# 18-bit compression with Accelerometer
250-
elif start_byte >= 1 and start_byte <= 100:
251-
print("18-bit compression with Accelerometer")
252-
# 19-bit compression without Accelerometer
253-
elif start_byte >=101 and start_byte <= 200:
254-
print("19-bit compression without Accelerometer")
255-
# Impedance Channel
256-
elif start_byte >= 201 and start_byte <= 205:
257-
print("Impedance Channel")
258-
# Part of ASCII
259-
elif start_byte == 206:
260-
print("ASCII message")
261-
print (packet)
262-
# End of ASCII message
263-
elif start_byte == 207:
264-
print ("End of ASCII message")
265-
print (packet)
266-
print ("----")
267-
else:
268-
self.warn("Unknown type of packet: " + str(start_byte))
269-
270-
271-
if False:
272-
#3 byte ints
273-
literal_read = read(3)
274-
275-
unpacked = struct.unpack('3B', literal_read)
276-
277-
#3byte int in 2s compliment
278-
if (unpacked[0] >= 127):
279-
pre_fix = bytes(bytearray.fromhex('FF'))
280-
else:
281-
pre_fix = bytes(bytearray.fromhex('00'))
282-
283-
literal_read = pre_fix + literal_read;
284-
285-
#unpack little endian(>) signed integer(i) (makes unpacking platform independent)
286-
myInt = struct.unpack('>i', literal_read)[0]
287-
288-
if self.scaling_output:
289-
channel_data.append(myInt*scale_fac_uVolts_per_count)
290-
else:
291-
channel_data.append(myInt)
292221

293222

294223
"""
@@ -356,3 +285,85 @@ def __init__(self, packet_id, channel_data, aux_data):
356285
self.channel_data = channel_data;
357286
self.aux_data = aux_data;
358287

288+
289+
class GanglionDelegate(DefaultDelegate):
290+
""" Called by BLE when new data arrive """
291+
def __init__(self):
292+
DefaultDelegate.__init__(self)
293+
294+
def handleNotification(self, cHandle, data):
295+
print ("handle data!")
296+
print cHandle
297+
if len(data) != 20:
298+
self.warn('Wrong packet size, ' + str(len(data)) + ' instead of 20 bytes')
299+
return
300+
self.parse(data)
301+
302+
"""
303+
PARSER:
304+
Parses incoming data packet into OpenBCISample -- see docs.
305+
FIXME: use buffer to account for missed / double packets?
306+
"""
307+
def parse(self, packet):
308+
# bluepy returnds INT with python3 and STR with python2
309+
if type(packet) is str:
310+
# convert a list that must comprises 20 strings to one string
311+
unpac = struct.unpack('20B', "".join(packet))
312+
else:
313+
unpac = packet
314+
315+
start_byte = unpac[0]
316+
317+
for b in unpac:
318+
print (str(b))
319+
320+
print(str(start_byte))
321+
# Raw uncompressed
322+
if start_byte == 0:
323+
print ("Raw uncompressed")
324+
# 18-bit compression with Accelerometer
325+
elif start_byte >= 1 and start_byte <= 100:
326+
print("18-bit compression with Accelerometer")
327+
# 19-bit compression without Accelerometer
328+
elif start_byte >=101 and start_byte <= 200:
329+
print("19-bit compression without Accelerometer")
330+
# Impedance Channel
331+
elif start_byte >= 201 and start_byte <= 205:
332+
print("Impedance Channel")
333+
# Part of ASCII
334+
elif start_byte == 206:
335+
print("ASCII message")
336+
print (packet)
337+
# End of ASCII message
338+
elif start_byte == 207:
339+
print ("End of ASCII message")
340+
print (packet)
341+
print ("----")
342+
else:
343+
self.warn("Unknown type of packet: " + str(start_byte))
344+
345+
346+
if False:
347+
#3 byte ints
348+
literal_read = read(3)
349+
350+
unpacked = struct.unpack('3B', literal_read)
351+
352+
#3byte int in 2s compliment
353+
if (unpacked[0] >= 127):
354+
pre_fix = bytes(bytearray.fromhex('FF'))
355+
else:
356+
pre_fix = bytes(bytearray.fromhex('00'))
357+
358+
literal_read = pre_fix + literal_read;
359+
360+
#unpack little endian(>) signed integer(i) (makes unpacking platform independent)
361+
myInt = struct.unpack('>i', literal_read)[0]
362+
363+
if self.scaling_output:
364+
channel_data.append(myInt*scale_fac_uVolts_per_count)
365+
else:
366+
channel_data.append(myInt)
367+
368+
def getSamples(self):
369+
return None

0 commit comments

Comments
 (0)