source: trunk/Puzzlebox/Synapse/Device.py @ 413

Last change on this file since 413 was 412, checked in by sc, 5 years ago
  • added support for Telekinesis EEG
File size: 12.1 KB
RevLine 
[372]1# -*- coding: utf-8 -*-
2
3# Copyright Puzzlebox Productions, LLC (2010-2012)
4#
5# This code is released under the GNU Pulic License (GPL) version 2
6# For more information please refer to http://www.gnu.org/copyleft/gpl.html
7
8__changelog__ = """\
[389]9Last Update: 2012.04.23
[372]10"""
11
12__todo__ = """
13"""
14
15### IMPORTS ###
[373]16import os, sys
[372]17
18import Puzzlebox.Synapse.Configuration as configuration
19
20if configuration.ENABLE_PYSIDE:
21        try:
22                import PySide as PyQt4
[373]23                from PySide import QtCore, QtGui
[372]24        except Exception, e:
[373]25                print "ERROR: [Synapse:Device] Exception importing PySide:",
[372]26                print e
27                configuration.ENABLE_PYSIDE = False
28        else:
29                print "INFO: [Synapse:Device] Using PySide module"
30
31if not configuration.ENABLE_PYSIDE:
32        print "INFO: [Synapse:Device] Using PyQt4 module"
[373]33        from PyQt4 import QtCore, QtGui
[372]34
[378]35if (sys.platform == 'win32'):
36        import _winreg as winreg
37        import itertools
38        import re
39        import serial
40        DEFAULT_IMAGE_PATH = 'images'
41elif (sys.platform == 'darwin'):
42        DEFAULT_IMAGE_PATH = 'images'
43else:
44        import bluetooth
45        DEFAULT_IMAGE_PATH = '/usr/share/puzzlebox_synapse/images'
[372]46
[378]47
[372]48#####################################################################
49# Globals
50#####################################################################
51
52DEBUG = configuration.DEBUG
53
54PATH_TO_HCITOOL = '/usr/bin/hcitool'
55
56
57#####################################################################
58# Classes
59#####################################################################
60
61class puzzlebox_synapse_device(QtGui.QWidget):
62       
63        def __init__(self, log, \
64                     DEBUG=DEBUG, \
65                     parent=None, \
66                     ):
67               
68                self.log = log
69                self.DEBUG = DEBUG
70                self.parent=parent
71               
72                if self.parent == None:
73                        QtGui.QWidget.__init__(self, parent)
74                        #self.setupUi(self)
75               
76                        self.configureSettings()
77                        self.connectWidgets()
78               
[373]79                self.name = "Synapse:Device"
[372]80       
81       
82        ##################################################################
83       
84        def configureSettings(self):
85               
86                pass
87       
88       
89        ##################################################################
90       
91        def connectWidgets(self):
92               
93                pass
94       
95       
96        ##################################################################
97       
98        def enumerateSerialPorts(self):
99               
100                """ Uses the Win32 registry to return an
101                iterator of serial (COM) ports
102                existing on this computer.
103               
104                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
105                """
106         
107                path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
108                try:
109                        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
110                except WindowsError:
111                        #raise IterationError
112                        return
113               
114                for i in itertools.count():
115                        try:
116                                val = winreg.EnumValue(key, i)
117                                yield str(val[1])
118                        except EnvironmentError:
119                                break
120       
121       
122        ##################################################################
123       
124        def fullPortName(self, portname):
125               
126                """ Given a port-name (of the form COM7,
127                COM12, CNCA0, etc.) returns a full
128                name suitable for opening with the
129                Serial class.
130                """
131               
132                m = re.match('^COM(\d+)$', portname)
133                if m and int(m.group(1)) < 10:
134                        return portname
135               
136                return '\\\\.\\' + portname
137       
138       
139        ##################################################################
140       
141        def searchForSerialDevices(self, devices=[]):
142               
143                if (sys.platform == 'win32'):
144                       
145                        for portname in self.enumerateSerialPorts():
146                               
147                                if portname not in devices:
148                                        #portname = self.fullPortName(portname)
149                                        devices.append(portname)
150               
[389]151               
152                elif (sys.platform == 'darwin'):
153                 
[412]154                  # Handle Telekinesis first so it shows up at top of listings
[389]155                  for device in os.listdir('/dev'):
[412]156                         if (device.startswith('tty.Telekinesis')):
157                                       
158                                        devices.append( os.path.join('/dev', device))
159                 
160                  for device in os.listdir('/dev'):
[389]161                         if (device.startswith('tty.MindWaveMobile') or \
162                             device.startswith('tty.MindWave')):
163                                         
164                                         devices.append( os.path.join('/dev', device))
165                       
166                       
167                  # Handle MindSet separately so it shows up second in listings
168                  for device in os.listdir('/dev'):
169                         if (device.startswith('tty.MindSet')):
170                                         
171                                         devices.append( os.path.join('/dev', device))
172               
[372]173                else:
174                       
[389]175                        #if os.path.exists('/dev/tty.MindWaveMobile-SPPDev'):
176                                #devices.append('/dev/tty.MindWaveMobile-SPPDev')
177                        #if os.path.exists('/dev/tty.MindWaveMobile-DevA'):
178                                #devices.append('/dev/tty.MindWaveMobile-DevA')
179                        #if os.path.exists('/dev/tty.MindWaveMobile-DevB'):
180                                #devices.append('/dev/tty.MindWaveMobile-DevB')
[372]181                       
[389]182                        #if os.path.exists('/dev/tty.MindWave'):
183                                #devices.append('/dev/tty.MindWave')
184                        #if os.path.exists('/dev/tty.MindWave1'):
185                                #devices.append('/dev/tty.MindWave1')
186                        #if os.path.exists('/dev/tty.MindWave2'):
187                                #devices.append('/dev/tty.MindWave2')
188                        #if os.path.exists('/dev/tty.MindWave3'):
189                                #devices.append('/dev/tty.MindWave3')
190                        #if os.path.exists('/dev/tty.MindWave4'):
191                                #devices.append('/dev/tty.MindWave4')
192                        #if os.path.exists('/dev/tty.MindWave5'):
193                                #devices.append('/dev/tty.MindWave5')
[372]194                       
[389]195                        #if os.path.exists('/dev/tty.MindSet-DevB'):
196                                #devices.append('/dev/tty.MindSet-DevB')
[372]197                       
198                       
[389]199                  for device in os.listdir('/dev'):
200                         if (device.startswith('ttyUSB') or \
201                             device.startswith('ttyACM') or \
[402]202                             device.startswith('tty.usbserial') or \
[389]203                             device.startswith('rfcomm')):
204                                         
205                                         devices.append( os.path.join('/dev', device))
[372]206                       
[389]207                        #if os.path.exists('/dev/ttyUSB0'):
208                                #devices.append('/dev/ttyUSB0')
209                        #if os.path.exists('/dev/ttyUSB1'):
210                                #devices.append('/dev/ttyUSB1')
211                        #if os.path.exists('/dev/ttyUSB2'):
212                                #devices.append('/dev/ttyUSB2')
213                        #if os.path.exists('/dev/ttyUSB3'):
214                                #devices.append('/dev/ttyUSB3')
215                        #if os.path.exists('/dev/ttyUSB4'):
216                                #devices.append('/dev/ttyUSB4')
217                        #if os.path.exists('/dev/ttyUSB5'):
218                                #devices.append('/dev/ttyUSB5')
219                        #if os.path.exists('/dev/ttyUSB6'):
220                                #devices.append('/dev/ttyUSB6')
221                        #if os.path.exists('/dev/ttyUSB7'):
222                                #devices.append('/dev/ttyUSB7')
223                        #if os.path.exists('/dev/ttyUSB8'):
224                                #devices.append('/dev/ttyUSB8')
225                        #if os.path.exists('/dev/ttyUSB9'):
226                                #devices.append('/dev/ttyUSB9')
[372]227                       
[389]228                        #if os.path.exists('/dev/rfcomm0'):
229                                #devices.append('/dev/rfcomm0')
230                        #if os.path.exists('/dev/rfcomm1'):
231                                #devices.append('/dev/rfcomm1')
232                        #if os.path.exists('/dev/rfcomm2'):
233                                #devices.append('/dev/rfcomm2')
234                        #if os.path.exists('/dev/rfcomm3'):
235                                #devices.append('/dev/rfcomm3')
236                        #if os.path.exists('/dev/rfcomm4'):
237                                #devices.append('/dev/rfcomm4')
238                       
239                        #if os.path.exists('/dev/ttyACM0'):
240                                #devices.append('/dev/ttyACM0')
241                        #if os.path.exists('/dev/ttyACM1'):
242                                #devices.append('/dev/ttyACM1')
243                        #if os.path.exists('/dev/ttyACM2'):
244                                #devices.append('/dev/ttyACM2')
245                        #if os.path.exists('/dev/ttyACM3'):
246                                #devices.append('/dev/ttyACM3')
247                        #if os.path.exists('/dev/ttyACM4'):
248                                #devices.append('/dev/ttyACM4')
[372]249               
250               
251                return(devices)
252       
253       
254        ##################################################################
255       
256        def hcitoolScanForRemoteDevices(self, devices=[]):
257               
258                bluetooth_devices = []
259               
260                #command = '%s scan 2> /dev/null' % PATH_TO_HCITOOL
261                command = '%s scan' % PATH_TO_HCITOOL
262               
263                if self.DEBUG > 1:
264                        print 'INFO: Calling "%s"' % command
265               
266                output = os.popen(command, 'r')
267               
268                try:
269                        result = output.readlines()
270                except Exception, e:
271                        if self.DEBUG:
272                                print "ERROR [Synapse-Interface]: Failed reading result from call to hcitool:",
273                                print e
274                        result = ''
275               
276                if result == '':
277                        return([]) # Under OS X hcitool doesn't exist so we don't see any devices
278               
279                for line in result:
280                        line = line.strip()
281                        if line == '' or line == 'Scanning ...':
282                                continue
283                        elif self.DEBUG > 1:
284                                print line
285                        try:
286                                address = line.split('\t')[0]
287                        except:
288                                pass
289                        else:
290                                bluetooth_devices.append(address)
291               
292               
293                for address in bluetooth_devices:
294                       
295                        command = '%s name %s' % (PATH_TO_HCITOOL, address)
296                       
297                        if self.DEBUG:
298                                print 'INFO: Calling "%s"' % command
299                       
300                        output = os.popen(command, 'r')
301                       
302                        for line in output.readlines():
303                                line = line.strip()
304                                if line == '':
305                                        continue
306                                elif self.DEBUG:
307                                        print '\t',
308                                        print line
309                               
310                                device_name = line.strip()
311                       
312                                if ((device_name == 'MindSet' or device_name == 'MindWave Mobile') and \
313                                        (address not in devices)):
314                                        devices.append(address)
315                               
316                                else:
317                                        if self.DEBUG:
318                                                print 'INFO: Found but not recognized: [%s] %s' % \
319                                                        (address, device_name)
320               
321               
322                return (devices)
323       
324       
325        ##################################################################
326       
327        def hcitoolGetActiveConnections(self, devices=[]):
328               
329                bluetooth_devices = []
330               
331                #command = '%s con 2> /dev/null' % PATH_TO_HCITOOL
332                command = '%s con' % PATH_TO_HCITOOL
333               
334                if self.DEBUG > 1:
335                        print 'INFO: Calling "%s"' % command
336               
337                output = os.popen(command, 'r')
338               
339                try:
340                        result = output.readlines()
341                except Exception, e:
342                        if self.DEBUG:
343                                print "ERROR [Synapse:Interface]: Failed reading result from call to hcitool:",
344                                print e
345                        result = ''
346
347                if result == '':
348                        return([]) # Under OS X hcitool doesn't exist so we don't see any devices
349
350                for line in result:
351                        line = line.strip()
352                        if line == '' or line == 'Connections:':
353                                continue
354                        elif self.DEBUG > 1:
355                                print line
356                        try:
357                                address = line.split(' ')[2]
358                        except:
359                                pass
360                        else:
361                                bluetooth_devices.append(address)
362               
363               
364                for address in bluetooth_devices:
365                       
366                        command = '%s name %s' % (PATH_TO_HCITOOL, address)
367                       
368                        if self.DEBUG:
369                                print 'INFO: Calling "%s":' % command
370                       
371                        output = os.popen(command, 'r')
372                       
373                        for line in output.readlines():
374                                line = line.strip()
375                                if line == '':
376                                        continue
377                                elif self.DEBUG:
378                                        print '\t',
379                                        print line
380                               
381                                device_name = line.strip()
382                       
383                                if ((device_name == 'MindSet' or device_name == 'MindWave Mobile') and \
384                                        (address not in devices)):
385                                        devices.append(address)
386               
387               
388                return (devices)
389       
390       
391        ##################################################################
392       
393        def searchForDevices(self):
394               
395                enable_hcitool = configuration.ENABLE_HCITOOL
396               
397                devices = []
398               
399                #self.pushButtonBluetoothSearch.setText('Searching')
400               
401                if ((sys.platform != 'win32' and sys.platform != 'darwin') and \
402                     configuration.THINKGEAR_BLUETOOTH_SEARCH):
403                       
404                        # Bluetooth module doesn't compile properly under Windows
405                        # and doesn't exist under OS X
406                       
407                        # PyBluez API Documentation
408                        # http://pybluez.googlecode.com/svn/www/docs-0.7/index.html
409                       
410                        bluetooth_devices = []
411                       
412                        if not enable_hcitool:
413                               
414                                try:
415                                       
416                                        if self.DEBUG:
417                                                print "INFO: Searching for Bluetooth devices using PyBluez module"
418                                       
419                                        bluetooth_devices = bluetooth.discover_devices( \
420                                              duration=configuration.THINKGEAR_BLUETOOTH_DISCOVER_DEVICES_TIMEOUT, \
421                                                               flush_cache=True, \
422                                                               lookup_names=False)
423                                       
424                                        for address in bluetooth_devices:
425                                               
426                                                if self.DEBUG:
427                                                        print "INFO: Device discovered",
428                                                        print address
429                                               
430                                                device_name = bluetooth.lookup_name(address, \
431                                                                 configuration.THINKGEAR_BLUETOOTH_LOOKUP_NAME_TIMEOUT)
432                                                if ((device_name == 'MindSet' or device_name == 'MindWave Mobile') and \
433                                                        (address not in devices)):
434                                                        devices.append(address)
435                                       
436                                       
437                                        # There is an issue under recent released of Linux
438                                        # in which already-connected Bluetooth ThinkGear devices
439                                        # are not appearing in a bluetooth device scan. However,
440                                        # using "hcitool" connected devices can be listed correctly.
441                                        # There does not appear to be an equivalent PyBluez feature.
442                                        # (http://pybluez.googlecode.com/svn/www/docs-0.7/index.html)
443                                       
444                                        if devices == []:
445                                                if self.DEBUG:
446                                                        print "INFO: No devices found through PyBluez module. Falling back to hcitool."
447                                                devices = self.hcitoolGetActiveConnections(devices)
448                               
449                               
450                                except Exception, e:
451                                        if self.DEBUG:
452                                                print "ERROR: Exception calling Python Bluetooth module. (Is PyBluez installed?):"
453                                                print e
454                                       
455                                       
456                                        #if (sys.platform != 'darwin'):
457                                        enable_hcitool = True
458                       
459                       
460                        if enable_hcitool:
461                               
462                                devices = self.hcitoolScanForRemoteDevices(devices)
463                                devices = self.hcitoolGetActiveConnections(devices)
464                       
465                       
466                        if self.DEBUG > 2:
467                                print "Bluetooth Devices found:",
468                                print devices
469               
470               
471                devices = self.searchForSerialDevices(devices)
472               
473               
474                if self.DEBUG:
475                        print "Devices found:",
476                        print devices
477               
478               
479                return(devices)
480
Note: See TracBrowser for help on using the repository browser.