class Emotiv(object): def __init__(self, displayOutput=False, headsetId=0, research_headset=True): self._goOn = True self.packets = Queue() self.packetsReceived = 0 self.packetsProcessed = 0 self.battery = 0 self.displayOutput = displayOutput self.headsetId = headsetId self.research_headset = research_headset self.sensors = { 'F3': {'value': 0, 'quality': 0}, 'FC6': {'value': 0, 'quality': 0}, 'P7': {'value': 0, 'quality': 0}, 'T8': {'value': 0, 'quality': 0}, 'F7': {'value': 0, 'quality': 0}, 'F8': {'value': 0, 'quality': 0}, 'T7': {'value': 0, 'quality': 0}, 'P8': {'value': 0, 'quality': 0}, 'AF4': {'value': 0, 'quality': 0}, 'F4': {'value': 0, 'quality': 0}, 'AF3': {'value': 0, 'quality': 0}, 'O2': {'value': 0, 'quality': 0}, 'O1': {'value': 0, 'quality': 0}, 'FC5': {'value': 0, 'quality': 0}, 'X': {'value': 0, 'quality': 0}, 'Y': {'value': 0, 'quality': 0}, 'Unknown': {'value': 0, 'quality': 0} } def setup(self, headsetId=0): if windows: self.setupWin() else: self.setupPosix() def updateStdout(self): while self._goOn: if self.displayOutput: if windows: os.system('cls') else: os.system('clear') print "Packets Received: %s Packets Processed: %s" % (self.packetsReceived, self.packetsProcessed) print('\n'.join("%s Reading: %s Strength: %s" % (k[1], self.sensors[k[1]]['value'],self.sensors[k[1]]['quality']) for k in enumerate(self.sensors))) print "Battery: %i" % g_battery gevent.sleep(1) def getLinuxSetup(self): rawinputs = [] for filename in os.listdir("/sys/class/hidraw"): realInputPath = check_output(["realpath", "/sys/class/hidraw/" + filename]) sPaths = realInputPath.split('/') s = len(sPaths) s = s - 4 i = 0 path = "" while s > i: path = path + sPaths[i] + "/" i += 1 rawinputs.append([path, filename]) hiddevices = [] # TODO: Add support for multiple USB sticks? make a bit more elegant for input in rawinputs: try: with open(input[0] + "/manufacturer", 'r') as f: manufacturer = f.readline() f.close() if ("Emotiv Systems Inc." in manufacturer) or ("Emotiv Systems Pty Ltd" in manufacturer) : with open(input[0] + "/serial", 'r') as f: serial = f.readline().strip() f.close() print "Serial: " + serial + " Device: " + input[1] # Great we found it. But we need to use the second one... hidraw = input[1] id_hidraw = int(hidraw[-1]) # The dev headset might use the first device, or maybe if more than one are connected they might. id_hidraw += 1 hidraw = "hidraw" + id_hidraw.__str__() print "Serial: " + serial + " Device: " + hidraw + " (Active)" return [serial, hidraw, ] except IOError as e: print "Couldn't open file: %s" % e def setupWin(self): devices = [] try: for device in hid.find_all_hid_devices(): if device.vendor_id != 0x21A1 and device.vendor_id != 0x1234: continue if device.product_name == 'Brain Waves': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == 'EPOC BCI': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == '00000000000': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == 'Emotiv RAW DATA': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) gevent.spawn(self.setupCrypto, self.serialNum) gevent.spawn(self.updateStdout) while self._goOn: try: gevent.sleep(0) except KeyboardInterrupt: self._goOn = False for device in devices: device.close() finally: for device in devices: device.close() def handler(self, data): assert data[0] == 0 tasks.put_nowait(''.join(map(chr, data[1:]))) self.packetsReceived += 1 return True def setupPosix(self): _os_decryption = False if os.path.exists('/dev/eeg/raw'): # The decrpytion is handled by the Linux epoc daemon. We don't need to handle it there. _os_decryption = True self.hidraw = open("/dev/eeg/raw") else: setup = self.getLinuxSetup() self.serialNum = setup[0] if os.path.exists("/dev/" + setup[1]): self.hidraw = open("/dev/" + setup[1]) else: self.hidraw = open("/dev/hidraw4") gevent.spawn(self.setupCrypto, self.serialNum) gevent.spawn(self.updateStdout) while self._goOn: try: data = self.hidraw.read(32) if data != "": if _os_decryption: self.packets.put_nowait(EmotivPacket(data)) else: # Queue it! self.packetsReceived += 1 tasks.put_nowait(data) gevent.sleep(0) except KeyboardInterrupt: self._goOn = False return True def setupCrypto(self, sn): type = 0 # feature[5] type &= 0xF type = 0 # I believe type == True is for the Dev headset, I'm not using that. That's the point of this library in the first place I thought. k = ['\0'] * 16 k[0] = sn[-1] k[1] = '\0' k[2] = sn[-2] if type: k[3] = 'H' k[4] = sn[-1] k[5] = '\0' k[6] = sn[-2] k[7] = 'T' k[8] = sn[-3] k[9] = '\x10' k[10] = sn[-4] k[11] = 'B' else: k[3] = 'T' k[4] = sn[-3] k[5] = '\x10' k[6] = sn[-4] k[7] = 'B' k[8] = sn[-1] k[9] = '\0' k[10] = sn[-2] k[11] = 'H' k[12] = sn[-3] k[13] = '\0' k[14] = sn[-4] k[15] = 'P' # It doesn't make sense to have more than one greenlet handling this as data needs to be in order anyhow. I guess you could assign an ID or something # to each packet but that seems like a waste also or is it? The ID might be useful if your using multiple headsets or usb sticks. key = ''.join(k) iv = Random.new().read(AES.block_size) cipher = AES.new(key, AES.MODE_ECB, iv) for i in k: print "0x%.02x " % (ord(i)) while self._goOn: while not tasks.empty(): task = tasks.get() data = cipher.decrypt(task[:16]) + cipher.decrypt(task[16:]) self.lastPacket = EmotivPacket(data, self.sensors) self.packets.put_nowait(self.lastPacket) self.packetsProcessed += 1 gevent.sleep(0) gevent.sleep(0) def dequeue(self): try: p = self.packets.get() self.packets.clear() return p except Exception, e: print e
class Emotiv(object): def __init__(self, displayOutput=False, headsetId=0, research_headset=True): self._goOn = True self.packets = Queue() self.packetsReceived = 0 self.packetsProcessed = 0 self.battery = 0 self.displayOutput = displayOutput self.headsetId = headsetId self.research_headset = research_headset self.sensors = { 'F3': { 'value': 0, 'quality': 0 }, 'FC6': { 'value': 0, 'quality': 0 }, 'P7': { 'value': 0, 'quality': 0 }, 'T8': { 'value': 0, 'quality': 0 }, 'F7': { 'value': 0, 'quality': 0 }, 'F8': { 'value': 0, 'quality': 0 }, 'T7': { 'value': 0, 'quality': 0 }, 'P8': { 'value': 0, 'quality': 0 }, 'AF4': { 'value': 0, 'quality': 0 }, 'F4': { 'value': 0, 'quality': 0 }, 'AF3': { 'value': 0, 'quality': 0 }, 'O2': { 'value': 0, 'quality': 0 }, 'O1': { 'value': 0, 'quality': 0 }, 'FC5': { 'value': 0, 'quality': 0 }, 'X': { 'value': 0, 'quality': 0 }, 'Y': { 'value': 0, 'quality': 0 }, 'Unknown': { 'value': 0, 'quality': 0 } } def setup(self, headsetId=0): if windows: self.setupWin() else: self.setupPosix() def updateStdout(self): while self._goOn: if self.displayOutput: if windows: os.system('cls') else: os.system('clear') print "Packets Received: %s Packets Processed: %s" % ( self.packetsReceived, self.packetsProcessed) print('\n'.join("%s Reading: %s Strength: %s" % (k[1], self.sensors[k[1]]['value'], self.sensors[k[1]]['quality']) for k in enumerate(self.sensors))) print "Battery: %i" % g_battery gevent.sleep(1) def getLinuxSetup(self): rawinputs = [] for filename in os.listdir("/sys/class/hidraw"): realInputPath = check_output( ["realpath", "/sys/class/hidraw/" + filename]) sPaths = realInputPath.split('/') s = len(sPaths) s = s - 4 i = 0 path = "" while s > i: path = path + sPaths[i] + "/" i += 1 rawinputs.append([path, filename]) hiddevices = [] # TODO: Add support for multiple USB sticks? make a bit more elegant for input in rawinputs: try: with open(input[0] + "/manufacturer", 'r') as f: manufacturer = f.readline() f.close() if ("Emotiv Systems Inc." in manufacturer) or ("Emotiv Systems Pty Ltd" in manufacturer): with open(input[0] + "/serial", 'r') as f: serial = f.readline().strip() f.close() print "Serial: " + serial + " Device: " + input[1] # Great we found it. But we need to use the second one... hidraw = input[1] id_hidraw = int(hidraw[-1]) # The dev headset might use the first device, or maybe if more than one are connected they might. id_hidraw += 1 hidraw = "hidraw" + id_hidraw.__str__() print "Serial: " + serial + " Device: " + hidraw + " (Active)" return [ serial, hidraw, ] except IOError as e: print "Couldn't open file: %s" % e def setupWin(self): devices = [] try: for device in hid.find_all_hid_devices(): if device.vendor_id != 0x21A1 and device.vendor_id != 0x1234: continue if device.product_name == 'Brain Waves': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == 'EPOC BCI': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == '00000000000': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) elif device.product_name == 'Emotiv RAW DATA': devices.append(device) device.open() self.serialNum = device.serial_number device.set_raw_data_handler(self.handler) gevent.spawn(self.setupCrypto, self.serialNum) gevent.spawn(self.updateStdout) while self._goOn: try: gevent.sleep(0) except KeyboardInterrupt: self._goOn = False for device in devices: device.close() finally: for device in devices: device.close() def handler(self, data): assert data[0] == 0 tasks.put_nowait(''.join(map(chr, data[1:]))) self.packetsReceived += 1 return True def setupPosix(self): _os_decryption = False if os.path.exists('/dev/eeg/raw'): # The decrpytion is handled by the Linux epoc daemon. We don't need to handle it there. _os_decryption = True self.hidraw = open("/dev/eeg/raw") else: setup = self.getLinuxSetup() self.serialNum = setup[0] if os.path.exists("/dev/" + setup[1]): self.hidraw = open("/dev/" + setup[1]) else: self.hidraw = open("/dev/hidraw4") gevent.spawn(self.setupCrypto, self.serialNum) gevent.spawn(self.updateStdout) while self._goOn: try: data = self.hidraw.read(32) if data != "": if _os_decryption: self.packets.put_nowait(EmotivPacket(data)) else: # Queue it! self.packetsReceived += 1 tasks.put_nowait(data) gevent.sleep(0) except KeyboardInterrupt: self._goOn = False return True def setupCrypto(self, sn): type = 0 # feature[5] type &= 0xF type = 0 # I believe type == True is for the Dev headset, I'm not using that. That's the point of this library in the first place I thought. k = ['\0'] * 16 k[0] = sn[-1] k[1] = '\0' k[2] = sn[-2] if type: k[3] = 'H' k[4] = sn[-1] k[5] = '\0' k[6] = sn[-2] k[7] = 'T' k[8] = sn[-3] k[9] = '\x10' k[10] = sn[-4] k[11] = 'B' else: k[3] = 'T' k[4] = sn[-3] k[5] = '\x10' k[6] = sn[-4] k[7] = 'B' k[8] = sn[-1] k[9] = '\0' k[10] = sn[-2] k[11] = 'H' k[12] = sn[-3] k[13] = '\0' k[14] = sn[-4] k[15] = 'P' # It doesn't make sense to have more than one greenlet handling this as data needs to be in order anyhow. I guess you could assign an ID or something # to each packet but that seems like a waste also or is it? The ID might be useful if your using multiple headsets or usb sticks. key = ''.join(k) iv = Random.new().read(AES.block_size) cipher = AES.new(key, AES.MODE_ECB, iv) for i in k: print "0x%.02x " % (ord(i)) while self._goOn: while not tasks.empty(): task = tasks.get() data = cipher.decrypt(task[:16]) + cipher.decrypt(task[16:]) self.lastPacket = EmotivPacket(data, self.sensors) self.packets.put_nowait(self.lastPacket) self.packetsProcessed += 1 gevent.sleep(0) gevent.sleep(0) def dequeue(self): try: p = self.packets.get() self.packets.clear() return p except Exception, e: print e