source: trunk/brainstorms/Puzzlebox/Brainstorms/Interface.py @ 233

Last change on this file since 233 was 233, checked in by sc, 11 years ago

Brainstorms/Wheelchair_Control.py:

  • general code cleanup

Brainstorms/Interface?.py:

  • initial support for connecting helicopter control to GUI buttons
File size: 48.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Client Interface - Qt
5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
10
11__changelog__ = """\
12Last Update: 2010.11.30
13
14"""
15
16__todo__ = """
17 - server may not correctly handle multiple clients connected
18      to an embedded Brainstorms server
19 - disable autorepeating on shortcut keys
20 - update configuration.ini file with settings entered into interface
21
22"""
23
24import os, sys
25import urllib
26
27if (sys.platform == 'win32'):
28        import _winreg as winreg
29        import itertools
30        import re
31        import serial
32else:
33        import bluetooth
34
35try:
36        import PySide as PyQt4
37        from PySide import QtCore, QtGui, QtNetwork
38except:
39        print "Using PyQt4 module"
40        from PyQt4 import QtCore, QtGui, QtNetwork
41else:
42        print "Using PySide module"
43
44#from PyQt4 import QtCore, QtGui, QtNetwork
45#from PySide import QtCore, QtGui, QtNetwork
46
47from Interface_Design import Ui_Form as Design
48
49import simplejson as json
50
51import Configuration as configuration
52import Client as brainstorms_client
53import Puzzlebox.Brainstorms.ThinkGear.Client as thinkgear_client
54import Helicopter_Control as helicopter_control
55#import puzzlebox_logger
56
57#####################################################################
58# Globals
59#####################################################################
60
61DEBUG = 1
62
63THINKGEAR_POWER_THRESHOLDS = configuration.THINKGEAR_POWER_THRESHOLDS
64
65BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
66
67NXT_BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
68
69DEFAULT_NXT_POWER_LEVEL = configuration.DEFAULT_NXT_POWER_LEVEL
70
71THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
72THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
73
74BRAINSTORMS_FEEDBACK_URL = 'http://brainstorms.puzzlebox.info/contact_cgi.php'
75
76DEVICE_PATH = '/dev'
77PATH_TO_HCITOOL = '/usr/bin/hcitool'
78
79#####################################################################
80# Classes
81#####################################################################
82
83class puzzlebox_brainstorms_client_interface(QtGui.QWidget, Design):
84       
85        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
86               
87                self.log = log
88                self.DEBUG = DEBUG
89               
90                QtGui.QWidget.__init__(self, parent)
91                self.setupUi(self)
92               
93                self.configureSettings()
94                self.connectWidgets()
95               
96                self.name = "Brainstorms Interface"
97               
98                self.brainstormsServer = server
99                self.brainstormsClient = None
100               
101                self.helicopter = None
102                self.wheelchair = None
103               
104                self.drive_state = 'stop_motors'
105                self.current_speed = 0
106       
107       
108        ##################################################################
109       
110        def configureSettings(self):
111               
112                # Brainstorms Interface
113               
114                icon = QtGui.QIcon()
115                icon.addPixmap(QtGui.QPixmap("images/puzzlebox.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
116                self.setWindowIcon(icon)
117               
118                self.pushButtonTurnLeft.setEnabled(False)
119                self.pushButtonForward.setEnabled(False)
120                self.pushButtonTurnRight.setEnabled(False)
121                self.pushButtonTurnLeftReverse.setEnabled(False)
122                self.pushButtonReverse.setEnabled(False)
123                self.pushButtonTurnRightReverse.setEnabled(False)
124               
125                self.pushButtonConcentrationEnable.setDown(True)
126                self.pushButtonRelaxationEnable.setDown(True)
127                self.pushButtonSpeedEnable.setDown(True)
128               
129               
130                # Search for available Serial and Bluetooth devices
131                self.searchForDevices()
132               
133               
134                # LEGO Mindstorms
135                self.textLabelNXTStatus.setText("Status: Disconnected")
136               
137                # Display communication port for LEGO Mindstorms NXT device
138                #self.lineEditNXTPort.setText(NXT_BLUETOOTH_DEVICE)
139                self.comboBoxNXTPortSelect.setEnabled(True)
140               
141               
142                # RC Helicopter
143                self.textLabelHelicopterStatus.setText("Status: Disconnected")
144               
145               
146                # Wheelchair
147                self.textLabelWheelchairStatus.setText("Status: Disconnected")
148               
149               
150                # Control Panel
151               
152                # Display Host for ThinkGear Connect Socket Server
153                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
154                #self.lineEditThinkGearHost.setEnabled(False)
155               
156                # Display Port for ThinkGear Connect Socket Server
157                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
158                #self.lineEditThinkGearPort.setEnabled(False)
159               
160               
161                self.lineEditLeftMotorPort.setText( \
162                   configuration.NXT_MOTOR_PORT_LEFT.upper() )
163                self.lineEditRightMotorPort.setText(   \
164                   configuration.NXT_MOTOR_PORT_RIGHT.upper() )
165                self.checkBoxMotorSpinReversed.setChecked( \
166                   configuration.NXT_MOTORS_MOUNTED_BACKWARDS)
167       
168       
169        ##################################################################
170       
171        def getMinimumThreshold(self, threshold):
172               
173                '''Return the minimum detection level which results
174                in a non-zero power setting'''
175               
176                minimum = 100
177               
178                threshold_keys = threshold.keys()
179                threshold_keys.sort()
180                threshold_keys.reverse()
181               
182                for key in threshold_keys:
183                       
184                        if ((threshold[key] < minimum) and \
185                                 (threshold[key] > 0)):
186                                minimum = key
187               
188               
189                return(minimum)
190       
191       
192        ##################################################################
193       
194        def configureNetworkBrainstorms(self):
195               
196                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
197               
198                self.brainstormsClient = \
199                   brainstorms_client.puzzlebox_brainstorms_network_client( \
200                           self.log, \
201                           bluetooth_device=bluetooth_device, \
202                           parent=self)
203               
204                self.brainstormsClient.sendCommand('connect', \
205                                                   bluetooth_device=bluetooth_device)
206       
207       
208        ##################################################################
209       
210        def connectToBrainstormsServer(self):
211               
212                # Prevent attempting to connect to a device which no longer exists
213                if (sys.platform != 'win32'):
214                        device = str(self.comboBoxNXTPortSelect.currentText())
215                        if ((not device.startswith(DEVICE_PATH)) or \
216                            (not os.path.exists(device))):
217                                self.searchForDevices()
218                                return
219               
220               
221                if self.DEBUG:
222                        print "<---- [%s] Connecting to Brainstorms Server" % self.name
223               
224                self.configureNetworkBrainstorms()
225               
226                #if (self.brainstormsClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
227                        #QtGui.QMessageBox.information(self, \
228                                                                #self.brainstormsClient.socket.name, \
229                                           #"Failed to connect to Brainstorms socket server")
230               
231                #else:
232                self.disconnect(self.pushButtonNXTConnect, \
233                                                        QtCore.SIGNAL("clicked()"), \
234                                                        self.connectToBrainstormsServer)
235               
236                self.connect(self.pushButtonNXTConnect, \
237                                                        QtCore.SIGNAL("clicked()"), \
238                                                        self.disconnectFromBrainstormsServer)
239               
240                self.textLabelNXTStatus.setText("Status: Connected")
241                self.pushButtonNXTConnect.setText('Disconnect')
242               
243                self.comboBoxNXTPortSelect.setEnabled(False)
244                self.pushButtonNXTSearch.setEnabled(False)
245               
246                self.pushButtonTurnLeft.setEnabled(True)
247                self.pushButtonForward.setEnabled(True)
248                self.pushButtonTurnRight.setEnabled(True)
249                self.pushButtonTurnLeftReverse.setEnabled(True)
250                self.pushButtonReverse.setEnabled(True)
251                self.pushButtonTurnRightReverse.setEnabled(True)
252               
253                self.pushButtonNXTMessageOne.setEnabled(True)
254                self.pushButtonNXTMessageTwo.setEnabled(True)
255                self.pushButtonNXTMessageThree.setEnabled(True)
256                self.pushButtonNXTMessageFour.setEnabled(True)
257                self.pushButtonNXTMessageFive.setEnabled(True)
258                self.pushButtonNXTMessageSix.setEnabled(True)
259               
260                self.pushButtonConcentrationEnable.setEnabled(True)
261                self.pushButtonRelaxationEnable.setEnabled(True)
262                self.pushButtonSpeedEnable.setEnabled(True)
263               
264                self.pushButtonMessageOne.setEnabled(True)
265                self.pushButtonMessageTwo.setEnabled(True)
266                self.pushButtonMessageThree.setEnabled(True)
267                self.pushButtonMessageFour.setEnabled(True)
268                self.pushButtonMessageFive.setEnabled(True)
269                self.pushButtonMessageSix.setEnabled(True)
270               
271                self.pushButtonHelicopterConcentrationEnable.setEnabled(True)
272                self.pushButtonHelicopterRelaxationEnable.setEnabled(True)
273                self.pushButtonHelicopterSpeedEnable.setEnabled(True)
274       
275       
276        ##################################################################
277       
278        def disconnectFromBrainstormsServer(self):
279               
280                if self.DEBUG:
281                        print "- - [%s] Disconnecting from Brainstorms Server" % self.name
282               
283                self.stopMotors()
284               
285                # Ensure the stopMotors command has been received by the server
286                # so the NXT robot will stop before the client disconnects
287                self.brainstormsClient.socket.flush()
288               
289                self.brainstormsClient.socket.disconnectFromHost()
290               
291                self.disconnect(self.pushButtonNXTConnect, \
292                                  QtCore.SIGNAL("clicked()"), \
293                                  self.disconnectFromBrainstormsServer)
294               
295                self.connect(self.pushButtonNXTConnect, \
296                                  QtCore.SIGNAL("clicked()"), \
297                                  self.connectToBrainstormsServer)
298               
299                self.textLabelNXTStatus.setText("Status: Disconnected")
300                self.pushButtonNXTConnect.setText('Connect')
301               
302                self.comboBoxNXTPortSelect.setEnabled(True)
303                self.pushButtonNXTSearch.setEnabled(True)
304               
305                self.pushButtonTurnLeft.setEnabled(False)
306                self.pushButtonForward.setEnabled(False)
307                self.pushButtonTurnRight.setEnabled(False)
308                self.pushButtonTurnLeftReverse.setEnabled(False)
309                self.pushButtonReverse.setEnabled(False)
310                self.pushButtonTurnRightReverse.setEnabled(False)
311               
312                self.pushButtonNXTMessageOne.setEnabled(False)
313                self.pushButtonNXTMessageTwo.setEnabled(False)
314                self.pushButtonNXTMessageThree.setEnabled(False)
315                self.pushButtonNXTMessageFour.setEnabled(False)
316                self.pushButtonNXTMessageFive.setEnabled(False)
317                self.pushButtonNXTMessageSix.setEnabled(False)
318               
319                self.pushButtonConcentrationEnable.setEnabled(False)
320                self.pushButtonRelaxationEnable.setEnabled(False)
321                self.pushButtonSpeedEnable.setEnabled(False)
322               
323                self.pushButtonMessageOne.setEnabled(False)
324                self.pushButtonMessageTwo.setEnabled(False)
325                self.pushButtonMessageThree.setEnabled(False)
326                self.pushButtonMessageFour.setEnabled(False)
327                self.pushButtonMessageFive.setEnabled(False)
328                self.pushButtonMessageSix.setEnabled(False)
329               
330                self.brainstormsClient = None
331               
332                self.searchForDevices()
333       
334       
335        ##################################################################
336       
337        def connectToThinkGearHost(self):
338               
339                if self.DEBUG:
340                        print "Connecting to ThinkGear Host"
341               
342                server_host = str(self.lineEditThinkGearHost.text())
343                server_port = int(self.lineEditThinkGearPort.text())
344               
345                self.thinkgearClient = \
346                   thinkgear_client.puzzlebox_brainstorms_network_client_thinkgear( \
347                           self.log, \
348                           server_host=server_host, \
349                           server_port=server_port, \
350                           DEBUG=0, \
351                           parent=self)
352               
353                if (self.thinkgearClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
354                        QtGui.QMessageBox.information(self, \
355                                                                self.thinkgearClient.socket.name, \
356                                           "Failed to connect to ThinkGear socket server")
357               
358                else:
359                        self.disconnect(self.pushButtonThinkGearConnect, \
360                                                         QtCore.SIGNAL("clicked()"), \
361                                                         self.connectToThinkGearHost)
362                       
363                        self.connect(self.pushButtonThinkGearConnect, \
364                                                         QtCore.SIGNAL("clicked()"), \
365                                                         self.disconnectFromThinkGearHost)
366                       
367                        self.pushButtonThinkGearConnect.setText('Disconnect')
368                       
369                        self.comboBoxEEGHeadsetModel.setEnabled(False)
370                        self.comboBoxEEGSource.setEnabled(False)
371                        self.lineEditThinkGearHost.setEnabled(False)
372                        self.lineEditThinkGearPort.setEnabled(False)
373       
374       
375        ##################################################################
376       
377        def disconnectFromThinkGearHost(self):
378               
379                if self.DEBUG:
380                        print "Disconnecting from ThinkGear Host"
381               
382                self.thinkgearClient.disconnectFromHost()
383               
384                self.disconnect(self.pushButtonThinkGearConnect, \
385                                  QtCore.SIGNAL("clicked()"), \
386                                  self.disconnectFromThinkGearHost)
387               
388                self.connect(self.pushButtonThinkGearConnect, \
389                                  QtCore.SIGNAL("clicked()"), \
390                                  self.connectToThinkGearHost)
391               
392                self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
393               
394                self.pushButtonThinkGearConnect.setText('Connect')
395               
396                self.comboBoxEEGHeadsetModel.setEnabled(True)
397                self.comboBoxEEGSource.setEnabled(True)
398                self.lineEditThinkGearHost.setEnabled(True)
399                self.lineEditThinkGearPort.setEnabled(True)
400               
401                self.progressBarConcentration.setValue(0)
402                self.progressBarRelaxation.setValue(0)
403                self.progressBarSpeed.setValue(0)
404       
405                self.progressBarHelicopterConcentration.setValue(0)
406                self.progressBarHelicopterRelaxation.setValue(0)
407                self.progressBarHelicopterSpeed.setValue(0)
408       
409                self.progressBarWheelchairConcentration.setValue(0)
410                self.progressBarWheelchairRelaxation.setValue(0)
411                self.progressBarWheelchairSpeed.setValue(0)
412       
413       
414        ##################################################################
415       
416        def connectToRCHelicopter(self):
417               
418                device_selection = self.comboBoxHelicopterPortSelect.currentText()
419               
420                self.helicopter = \
421                   helicopter_control.puzzlebox_brainstorms_helicopter_control( \
422                      device_address=device_selection,
423                      command='neutral', \
424                      DEBUG=self.DEBUG)
425               
426                self.helicopter.start()
427               
428                self.disconnect(self.pushButtonHelicopterConnect, \
429                                  QtCore.SIGNAL("clicked()"), \
430                                  self.connectToRCHelicopter)
431               
432                self.connect(self.pushButtonHelicopterConnect, \
433                                  QtCore.SIGNAL("clicked()"), \
434                                  self.disconnectFromRCHelicopter)
435               
436                self.pushButtonHelicopterConnect.setText('Disconnect')
437               
438                self.comboBoxHelicopterTransmitter.setEnabled(False)
439                self.comboBoxHelicopterPortSelect.setEnabled(False)
440                self.pushButtonHelicopterSearch.setEnabled(False)
441               
442                self.pushButtonHelicopterHover.setEnabled(True)
443                self.pushButtonHelicopterFlyForward.setEnabled(True)
444                self.pushButtonHelicopterLand.setEnabled(True)
445                self.pushButtonHelicopterThrottle.setEnabled(True)
446                self.verticalSliderHelicopterThrottle.setEnabled(True)
447                self.pushButtonHelicopterElevatorForward.setEnabled(True)
448                self.verticalSliderHelicopterElevatorForward.setEnabled(True)
449                self.pushButtonHelicopterElevatorReverse.setEnabled(True)
450                self.verticalSliderHelicopterElevatorReverse.setEnabled(True)
451                self.pushButtonHelicopterRudderLeft.setEnabled(True)
452                self.horizontalSliderHelicopterRudderLeft.setEnabled(True)
453                self.pushButtonHelicopterRudderRight.setEnabled(True)
454                self.horizontalSliderHelicopterRudderRight.setEnabled(True)
455                self.pushButtonHelicopterAileronLeft.setEnabled(True)
456                self.horizontalSliderHelicopterAileronLeft.setEnabled(True)
457                self.pushButtonHelicopterAileronRight.setEnabled(True)
458                self.horizontalSliderHelicopterAileronRight.setEnabled(True)
459       
460       
461        ##################################################################
462       
463        def disconnectFromRCHelicopter(self):
464               
465                self.helicopter.command = 'neutral'
466                self.helicopter.processCommand()
467               
468                self.helicopter.stop()
469               
470                self.disconnect(self.pushButtonHelicopterConnect, \
471                                  QtCore.SIGNAL("clicked()"), \
472                                  self.disconnectFromRCHelicopter)
473               
474                self.connect(self.pushButtonHelicopterConnect, \
475                                  QtCore.SIGNAL("clicked()"), \
476                                  self.connectToRCHelicopter)
477               
478                self.pushButtonHelicopterConnect.setText('Connect')
479               
480                self.comboBoxHelicopterTransmitter.setEnabled(True)
481                self.comboBoxHelicopterPortSelect.setEnabled(True)
482                self.pushButtonHelicopterSearch.setEnabled(True)
483               
484                self.pushButtonHelicopterHover.setEnabled(False)
485                self.pushButtonHelicopterFlyForward.setEnabled(False)
486                self.pushButtonHelicopterLand.setEnabled(False)
487                self.pushButtonHelicopterThrottle.setEnabled(False)
488                self.verticalSliderHelicopterThrottle.setEnabled(False)
489                self.pushButtonHelicopterElevatorForward.setEnabled(False)
490                self.verticalSliderHelicopterElevatorForward.setEnabled(False)
491                self.pushButtonHelicopterElevatorReverse.setEnabled(False)
492                self.verticalSliderHelicopterElevatorReverse.setEnabled(False)
493                self.pushButtonHelicopterRudderLeft.setEnabled(False)
494                self.horizontalSliderHelicopterRudderLeft.setEnabled(False)
495                self.pushButtonHelicopterRudderRight.setEnabled(False)
496                self.horizontalSliderHelicopterRudderRight.setEnabled(False)
497                self.pushButtonHelicopterAileronLeft.setEnabled(False)
498                self.horizontalSliderHelicopterAileronLeft.setEnabled(False)
499                self.pushButtonHelicopterAileronRight.setEnabled(False)
500                self.horizontalSliderHelicopterAileronRight.setEnabled(False)
501       
502       
503        ##################################################################
504       
505        def connectToWheelchair(self):
506               
507                self.disconnect(self.pushButtonWheelchairConnect, \
508                                  QtCore.SIGNAL("clicked()"), \
509                                  self.connectToWheelchair)
510               
511                self.connect(self.pushButtonWheelchairConnect, \
512                                  QtCore.SIGNAL("clicked()"), \
513                                  self.disconnectFromWheelchair)
514               
515                self.pushButtonWheelchairConnect.setText('Disconnect')
516               
517                self.comboBoxWheelchairTransmitter.setEnabled(False)
518                self.comboBoxWheelchairPortSelect.setEnabled(False)
519                self.pushButtonWheelchairSearch.setEnabled(False)
520               
521                self.pushButtonWheelchairForward.setEnabled(True)
522                self.pushButtonWheelchairReverse.setEnabled(True)
523                self.pushButtonWheelchairLeft.setEnabled(True)
524                self.pushButtonWheelchairRight.setEnabled(True)
525                self.pushButtonWheelchairStop.setEnabled(True)
526                self.dialWheelchairSpeed.setEnabled(True)
527       
528       
529        ##################################################################
530       
531        def disconnectFromWheelchair(self):
532               
533                self.disconnect(self.pushButtonWheelchairConnect, \
534                                  QtCore.SIGNAL("clicked()"), \
535                                  self.disconnectFromWheelchair)
536               
537                self.connect(self.pushButtonWheelchairConnect, \
538                                  QtCore.SIGNAL("clicked()"), \
539                                  self.connectToWheelchair)
540               
541                self.pushButtonWheelchairConnect.setText('Connect')
542               
543                self.comboBoxWheelchairTransmitter.setEnabled(True)
544                self.comboBoxWheelchairPortSelect.setEnabled(True)
545                self.pushButtonWheelchairSearch.setEnabled(True)
546               
547                self.pushButtonWheelchairForward.setEnabled(False)
548                self.pushButtonWheelchairReverse.setEnabled(False)
549                self.pushButtonWheelchairLeft.setEnabled(False)
550                self.pushButtonWheelchairRight.setEnabled(False)
551                self.pushButtonWheelchairStop.setEnabled(False)
552                self.dialWheelchairSpeed.setEnabled(False)
553       
554       
555        ##################################################################
556       
557        def updateConcentrationButton(self):
558               
559                if self.pushButtonConcentrationEnable.isChecked():
560                       
561                        self.pushButtonConcentrationEnable.setText('Enabled')
562               
563                else:
564                       
565                        self.pushButtonConcentrationEnable.setText('Disabled')
566                        self.progressBarConcentration.setValue(0)
567               
568               
569                self.updateSpeed()
570       
571       
572        ##################################################################
573       
574        def updateRelaxationButton(self):
575               
576                if self.pushButtonRelaxationEnable.isChecked():
577               
578                        self.pushButtonRelaxationEnable.setText('Enabled')
579               
580                else:
581                       
582                        self.pushButtonRelaxationEnable.setText('Disabled')
583                        self.progressBarRelaxation.setValue(0)
584               
585               
586                self.updateNXTSpeed()
587       
588       
589        ##################################################################
590       
591        def updateSpeedButton(self):
592               
593                if self.pushButtonSpeedEnable.isChecked():
594               
595                        self.pushButtonSpeedEnable.setText('Enabled')
596                        self.updateSpeed()
597               
598                else:
599                       
600                        self.pushButtonSpeedEnable.setText('Disabled')
601                        self.progressBarSpeed.setValue(0)
602                        self.stopMotors()
603       
604       
605        ##################################################################
606       
607        def updateHelicopterConcentrationButton(self):
608               
609                if self.pushButtonHelicopterConcentrationEnable.isChecked():
610                       
611                        self.pushButtonHelicopterConcentrationEnable.setText('Enabled')
612               
613                else:
614                       
615                        self.pushButtonHelicopterConcentrationEnable.setText('Disabled')
616                        self.progressBarHelicopterConcentration.setValue(0)
617               
618               
619                self.updateHelicopterSpeed()
620       
621       
622        ##################################################################
623       
624        def updateHelicopterRelaxationButton(self):
625               
626                if self.pushButtonHelicopterRelaxationEnable.isChecked():
627               
628                        self.pushButtonHelicopterRelaxationEnable.setText('Enabled')
629               
630                else:
631                       
632                        self.pushButtonHelicopterRelaxationEnable.setText('Disabled')
633                        self.progressBarHelicopterRelaxation.setValue(0)
634               
635               
636                self.updateHelicopterSpeed()
637       
638       
639        ##################################################################
640       
641        def updateHelicopterSpeedButton(self):
642               
643                if self.pushButtonHelicopterSpeedEnable.isChecked():
644               
645                        self.pushButtonHelicopterSpeedEnable.setText('Enabled')
646                        self.updateHelicopterSpeed()
647               
648                else:
649                       
650                        self.pushButtonHelicopterSpeedEnable.setText('Disabled')
651                        self.progressBarHelicopterSpeed.setValue(0)
652                        self.stopMotors()
653       
654       
655        ##################################################################
656       
657        def updateWheelchairConcentrationButton(self):
658               
659                if self.pushButtonWheelchairConcentrationEnable.isChecked():
660                       
661                        self.pushButtonWheelchairConcentrationEnable.setText('Enabled')
662               
663                else:
664                       
665                        self.pushButtonWheelchairConcentrationEnable.setText('Disabled')
666                        self.progressBarWheelchairConcentration.setValue(0)
667               
668               
669                self.updateWheelchairSpeed()
670       
671       
672        ##################################################################
673       
674        def updateWheelchairRelaxationButton(self):
675               
676                if self.pushButtonWheelchairRelaxationEnable.isChecked():
677               
678                        self.pushButtonWheelchairRelaxationEnable.setText('Enabled')
679               
680                else:
681                       
682                        self.pushButtonWheelchairRelaxationEnable.setText('Disabled')
683                        self.progressBarWheelchairRelaxation.setValue(0)
684               
685               
686                self.updateWheelchairSpeed()
687       
688       
689        ##################################################################
690       
691        def updateWheelchairSpeedButton(self):
692               
693                if self.pushButtonWheelchairSpeedEnable.isChecked():
694               
695                        self.pushButtonWheelchairSpeedEnable.setText('Enabled')
696                        self.updateWheelchairSpeed()
697               
698                else:
699                       
700                        self.pushButtonWheelchairSpeedEnable.setText('Disabled')
701                        self.progressBarWheelchairSpeed.setValue(0)
702                        self.stopMotors()
703       
704       
705        ##################################################################
706       
707        def connectWidgets(self):
708               
709                # LEGO Mindstorms Buttons
710                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("pressed()"), \
711                             self.turnLeft)
712                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("released()"), \
713                             self.stopMotors)
714               
715                self.connect(self.pushButtonForward, QtCore.SIGNAL("pressed()"), \
716                             self.driveForward)
717                self.connect(self.pushButtonForward, QtCore.SIGNAL("released()"), \
718                             self.stopMotors)
719               
720                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("pressed()"), \
721                             self.turnRight)
722                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("released()"), \
723                             self.stopMotors)
724               
725                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("pressed()"), \
726                             self.turnLeftInReverse)
727                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("released()"), \
728                             self.stopMotors)
729               
730                self.connect(self.pushButtonReverse, QtCore.SIGNAL("pressed()"), \
731                             self.driveReverse)
732                self.connect(self.pushButtonReverse, QtCore.SIGNAL("released()"), \
733                             self.stopMotors)
734               
735                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("pressed()"), \
736                             self.turnRightInReverse)
737                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("released()"), \
738                             self.stopMotors)
739               
740               
741                self.connect(self.pushButtonNXTSearch, \
742                                  QtCore.SIGNAL("clicked()"), \
743                                  self.searchForDevices)
744               
745                self.connect(self.pushButtonNXTConnect, \
746                                  QtCore.SIGNAL("clicked()"), \
747                                  self.connectToBrainstormsServer)
748               
749               
750                self.connect(self.pushButtonConcentrationEnable, \
751                                  QtCore.SIGNAL("clicked()"), \
752                                  self.updateConcentrationButton)
753               
754                self.connect(self.pushButtonRelaxationEnable, \
755                                  QtCore.SIGNAL("clicked()"), \
756                                  self.updateRelaxationButton)
757               
758                self.connect(self.pushButtonSpeedEnable, \
759                                  QtCore.SIGNAL("clicked()"), \
760                                  self.updateSpeedButton)
761               
762               
763                self.connect(self.pushButtonNXTMessageOne, QtCore.SIGNAL("pressed()"), \
764                             self.sendMessageOne)
765               
766                self.connect(self.pushButtonNXTMessageTwo, QtCore.SIGNAL("pressed()"), \
767                             self.sendMessageTwo)
768               
769                self.connect(self.pushButtonNXTMessageThree, QtCore.SIGNAL("pressed()"), \
770                             self.sendMessageThree)
771               
772                self.connect(self.pushButtonNXTMessageFour, QtCore.SIGNAL("pressed()"), \
773                             self.sendMessageFour)
774               
775                self.connect(self.pushButtonNXTMessageFive, QtCore.SIGNAL("pressed()"), \
776                             self.sendMessageFive)
777               
778                self.connect(self.pushButtonNXTMessageSix, QtCore.SIGNAL("pressed()"), \
779                             self.sendMessageSix)
780               
781               
782               
783                # RC Helicopter Buttons
784                self.connect(self.pushButtonHelicopterSearch, \
785                                  QtCore.SIGNAL("clicked()"), \
786                                  self.searchForDevices)
787               
788                self.connect(self.pushButtonHelicopterConnect, \
789                                  QtCore.SIGNAL("clicked()"), \
790                                  self.connectToRCHelicopter)
791               
792               
793                self.connect(self.pushButtonHelicopterConcentrationEnable, \
794                                  QtCore.SIGNAL("clicked()"), \
795                                  self.updateHelicopterConcentrationButton)
796               
797                self.connect(self.pushButtonHelicopterRelaxationEnable, \
798                                  QtCore.SIGNAL("clicked()"), \
799                                  self.updateHelicopterRelaxationButton)
800               
801                self.connect(self.pushButtonHelicopterSpeedEnable, \
802                                  QtCore.SIGNAL("clicked()"), \
803                                  self.updateHelicopterSpeedButton)
804               
805               
806                self.connect(self.pushButtonHelicopterHover, \
807                                  QtCore.SIGNAL("clicked()"), \
808                                  self.enableHelicopterHover)
809               
810                self.connect(self.pushButtonHelicopterFlyForward, \
811                                  QtCore.SIGNAL("clicked()"), \
812                                  self.enableHelicopterFlyForward)
813               
814                self.connect(self.pushButtonHelicopterLand, \
815                                  QtCore.SIGNAL("clicked()"), \
816                                  self.landHelicopter)
817               
818               
819               
820                # Wheelchair Buttons
821                self.connect(self.pushButtonWheelchairSearch, \
822                                  QtCore.SIGNAL("clicked()"), \
823                                  self.searchForDevices)
824               
825                self.connect(self.pushButtonWheelchairConnect, \
826                                  QtCore.SIGNAL("clicked()"), \
827                                  self.connectToWheelchair)
828               
829               
830                self.connect(self.pushButtonWheelchairConcentrationEnable, \
831                                  QtCore.SIGNAL("clicked()"), \
832                                  self.updateWheelchairConcentrationButton)
833               
834                self.connect(self.pushButtonWheelchairRelaxationEnable, \
835                                  QtCore.SIGNAL("clicked()"), \
836                                  self.updateWheelchairRelaxationButton)
837               
838                self.connect(self.pushButtonWheelchairSpeedEnable, \
839                                  QtCore.SIGNAL("clicked()"), \
840                                  self.updateWheelchairSpeedButton)
841               
842               
843                self.connect(self.pushButtonWheelchairForward, \
844                                  QtCore.SIGNAL("clicked()"), \
845                                  self.driveWheelchairForward)
846               
847                self.connect(self.pushButtonWheelchairReverse, \
848                                  QtCore.SIGNAL("clicked()"), \
849                                  self.driveWheelchairReverse)
850               
851                self.connect(self.pushButtonWheelchairLeft, \
852                                  QtCore.SIGNAL("clicked()"), \
853                                  self.driveWheelchairLeft)
854               
855                self.connect(self.pushButtonWheelchairRight, \
856                                  QtCore.SIGNAL("clicked()"), \
857                                  self.driveWheelchairRight)
858               
859                self.connect(self.pushButtonWheelchairStop, \
860                                  QtCore.SIGNAL("clicked()"), \
861                                  self.stopWheelchair)
862               
863               
864               
865                # Control Panel Buttons
866                self.connect(self.pushButtonMessageOne, QtCore.SIGNAL("pressed()"), \
867                             self.sendMessageOne)
868               
869                self.connect(self.pushButtonMessageTwo, QtCore.SIGNAL("pressed()"), \
870                             self.sendMessageTwo)
871               
872                self.connect(self.pushButtonMessageThree, QtCore.SIGNAL("pressed()"), \
873                             self.sendMessageThree)
874               
875                self.connect(self.pushButtonMessageFour, QtCore.SIGNAL("pressed()"), \
876                             self.sendMessageFour)
877               
878                self.connect(self.pushButtonMessageFive, QtCore.SIGNAL("pressed()"), \
879                             self.sendMessageFive)
880               
881                self.connect(self.pushButtonMessageSix, QtCore.SIGNAL("pressed()"), \
882                             self.sendMessageSix)
883               
884               
885                self.connect(self.pushButtonThinkGearConnect, \
886                                  QtCore.SIGNAL("clicked()"), \
887                                  self.connectToThinkGearHost)
888               
889                self.connect(self.pushButtonSendFeedback, \
890                                  QtCore.SIGNAL("clicked()"), \
891                                  self.sendFeedback)
892               
893               
894                #shortcut = QtGui.QShortcut(self)
895                #shortcut.setKey(tr("Down"))
896                #self.connect(shortcut, QtCore.SIGNAL("pressed()"), self.driveReverse)
897               
898               
899                action = QtGui.QAction(self)
900                action.setShortcut(QtGui.QKeySequence("W"))
901                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
902                self.addAction(action)
903               
904                action = QtGui.QAction(self)
905                action.setShortcut(QtGui.QKeySequence("Up"))
906                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
907                self.addAction(action)
908               
909               
910                action = QtGui.QAction(self)
911                action.setShortcut(QtGui.QKeySequence("Left"))
912                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
913                self.addAction(action)
914               
915                action = QtGui.QAction(self)
916                action.setShortcut(QtGui.QKeySequence("A"))
917                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
918                self.addAction(action)
919               
920               
921                action = QtGui.QAction(self)
922                action.setShortcut(QtGui.QKeySequence("S"))
923                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
924                self.addAction(action)
925               
926                action = QtGui.QAction(self)
927                action.setShortcut(QtGui.QKeySequence("Down"))
928                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
929                self.addAction(action)
930               
931               
932                action = QtGui.QAction(self)
933                action.setShortcut(QtGui.QKeySequence("D"))
934                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
935                self.addAction(action)
936               
937                action = QtGui.QAction(self)
938                action.setShortcut(QtGui.QKeySequence("Right"))
939                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
940                self.addAction(action)
941               
942               
943                action = QtGui.QAction(self)
944                action.setShortcut(QtGui.QKeySequence("Z"))
945                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeftReverse, QtCore.SLOT("animateClick()"))
946                self.addAction(action)
947               
948               
949                action = QtGui.QAction(self)
950                action.setShortcut(QtGui.QKeySequence("C"))
951                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRightReverse, QtCore.SLOT("animateClick()"))
952                self.addAction(action)
953               
954               
955               
956                # RC Helicopter Buttons
957               
958                action = QtGui.QAction(self)
959                action.setShortcut(QtGui.QKeySequence("Home"))
960                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterHover, QtCore.SLOT("animateClick()"))
961                self.addAction(action)
962               
963                action = QtGui.QAction(self)
964                action.setShortcut(QtGui.QKeySequence("PgUp"))
965                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterFlyForward, QtCore.SLOT("animateClick()"))
966                self.addAction(action)
967               
968                action = QtGui.QAction(self)
969                action.setShortcut(QtGui.QKeySequence("End"))
970                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonHelicopterLand, QtCore.SLOT("animateClick()"))
971                self.addAction(action)
972               
973               
974               
975                # Wheelchair Buttons
976               
977                action = QtGui.QAction(self)
978                action.setShortcut(QtGui.QKeySequence("i"))
979                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairForward, QtCore.SLOT("animateClick()"))
980                self.addAction(action)
981               
982                action = QtGui.QAction(self)
983                action.setShortcut(QtGui.QKeySequence("k"))
984                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairReverse, QtCore.SLOT("animateClick()"))
985                self.addAction(action)
986               
987                action = QtGui.QAction(self)
988                action.setShortcut(QtGui.QKeySequence("j"))
989                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairLeft, QtCore.SLOT("animateClick()"))
990                self.addAction(action)
991               
992                action = QtGui.QAction(self)
993                action.setShortcut(QtGui.QKeySequence("l"))
994                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairRight, QtCore.SLOT("animateClick()"))
995                self.addAction(action)
996               
997                action = QtGui.QAction(self)
998                action.setShortcut(QtGui.QKeySequence("Space"))
999                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonWheelchairStop, QtCore.SLOT("animateClick()"))
1000                self.addAction(action)
1001               
1002               
1003               
1004                # Control Panel Buttons
1005               
1006                action = QtGui.QAction(self)
1007                action.setShortcut(QtGui.QKeySequence("1"))
1008                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageOne, QtCore.SLOT("animateClick()"))
1009                self.addAction(action)
1010               
1011                action = QtGui.QAction(self)
1012                action.setShortcut(QtGui.QKeySequence("2"))
1013                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageTwo, QtCore.SLOT("animateClick()"))
1014                self.addAction(action)
1015               
1016                action = QtGui.QAction(self)
1017                action.setShortcut(QtGui.QKeySequence("3"))
1018                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageThree, QtCore.SLOT("animateClick()"))
1019                self.addAction(action)
1020               
1021                action = QtGui.QAction(self)
1022                action.setShortcut(QtGui.QKeySequence("4"))
1023                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFour, QtCore.SLOT("animateClick()"))
1024                self.addAction(action)
1025               
1026                action = QtGui.QAction(self)
1027                action.setShortcut(QtGui.QKeySequence("5"))
1028                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFive, QtCore.SLOT("animateClick()"))
1029                self.addAction(action)
1030               
1031                action = QtGui.QAction(self)
1032                action.setShortcut(QtGui.QKeySequence("6"))
1033                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageSix, QtCore.SLOT("animateClick()"))
1034                self.addAction(action)
1035               
1036               
1037                #self.pushButtonForward.setAutoRepeat(False)
1038                #self.pushButtonForward.setAutoRepeatDelay(0)
1039                #self.pushButtonForward.setAutoRepeatInterval(0)
1040       
1041       
1042        ##################################################################
1043       
1044        def searchForDevices(self):
1045               
1046                nxt_devices = []
1047                rc_helicopter_devices = []
1048                wheelchair_devices = []
1049               
1050                #if (sys.platform != 'win32'):
1051                if False: # temporarily disabled
1052                       
1053                        # Bluetooth module doesn't compile properly under Windows
1054                       
1055                        bluetooth_devices = []
1056                       
1057                        try:
1058                                bluetooth_devices = bluetooth.discover_devices( \
1059                                                       duration=5, \
1060                                                       flush_cache=True, \
1061                                                       lookup_names=False)
1062                        except:
1063                                #command = '%s con' % PATH_TO_HCITOOL
1064                                command = '%s scan' % PATH_TO_HCITOOL
1065                               
1066                                output = os.popen(command, 'r')
1067                               
1068                                for line in output.readlines():
1069                                        print line
1070                                        try:
1071                                                address = line.split(' ')[2]
1072                                        except:
1073                                                pass
1074                                        else:
1075                                                bluetooth_devices.append(address)
1076                       
1077                        for address in bluetooth_devices:
1078                                device_name = bluetooth.lookup_name(address)
1079                                if ((device_name == 'NXT') and \
1080                                    (address not in nxt_devices)):
1081                                        nxt_devices.append(address)
1082                       
1083                       
1084                        if self.DEBUG:
1085                                print "Bluetooth NXT devices found:",
1086                                print nxt_devices
1087               
1088               
1089                # List all serial devices
1090                serial_devices = self.enumerateSerialPorts()
1091               
1092                for serial_device in serial_devices:
1093                        #serial_device = self.fullPortName(serial_device)
1094                        nxt_devices.append(serial_device)
1095                        rc_helicopter_devices.append(serial_device)
1096                        wheelchair_devices.append(serial_device)
1097               
1098               
1099                # Configure combo boxes
1100                if nxt_devices == []:
1101                        nxt_devices.append('N/A')
1102               
1103                if rc_helicopter_devices == []:
1104                        rc_helicopter_devices.append('N/A')
1105               
1106                if wheelchair_devices == []:
1107                        wheelchair_devices.append('N/A')
1108               
1109               
1110                # Don't reset combo boxes if already connected
1111                if self.pushButtonNXTConnect.text != 'Disconnect':
1112                       
1113                        self.comboBoxNXTPortSelect.clear()
1114                       
1115                        #nxt_devices.reverse()
1116                        for nxt_device in nxt_devices:
1117                                self.comboBoxNXTPortSelect.addItem(nxt_device)
1118               
1119               
1120                if self.pushButtonHelicopterConnect.text != 'Disconnect':
1121                       
1122                        self.comboBoxHelicopterPortSelect.clear()
1123                       
1124                        #rc_helicopter_devices.reverse()
1125                        for rc_helicopter in rc_helicopter_devices:
1126                                self.comboBoxHelicopterPortSelect.addItem(rc_helicopter)
1127       
1128       
1129                if self.pushButtonWheelchairConnect.text != 'Disconnect':
1130                       
1131                        self.comboBoxWheelchairPortSelect.clear()
1132                       
1133                        #rc_helicopter_devices.reverse()
1134                        for wheelchair in wheelchair_devices:
1135                                self.comboBoxWheelchairPortSelect.addItem(wheelchair)
1136       
1137       
1138        ##################################################################
1139       
1140        def enumerateSerialPorts(self):
1141               
1142                """ Uses the Win32 registry to return an
1143                iterator of serial (COM) ports
1144                existing on this computer.
1145               
1146                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
1147                """
1148               
1149                serial_ports = []
1150               
1151                if (sys.platform == 'win32'):
1152                       
1153                        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
1154                        try:
1155                                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
1156                        except WindowsError:
1157                                #raise IterationError
1158                                #return
1159                                pass
1160                       
1161                        for i in itertools.count():
1162                                try:
1163                                        val = winreg.EnumValue(key, i)
1164                                        #yield str(val[1])
1165                                        serial_ports.append( str(val[1]) )
1166                                except EnvironmentError:
1167                                        break
1168               
1169               
1170                else:
1171                       
1172                        if os.path.exists(DEVICE_PATH):
1173                                device_list = os.listdir(DEVICE_PATH)
1174                               
1175                                device_list.sort()
1176                       
1177                                for device in device_list:
1178                                        if device.startswith('ttyUSB'):
1179                                                serial_ports.append( DEVICE_PATH + '/' + device )
1180                                        if device.startswith('rfcomm'):
1181                                                serial_ports.append( DEVICE_PATH + '/' + device )
1182                                        if device.startswith('ttyACM'):
1183                                                serial_ports.append( DEVICE_PATH + '/' + device )
1184                                        if device.startswith('ttyS'):
1185                                                serial_ports.append( DEVICE_PATH + '/' + device )
1186               
1187               
1188                return(serial_ports)
1189       
1190       
1191        ##################################################################
1192       
1193        def fullPortName(self, portname):
1194               
1195                """ Given a port-name (of the form COM7,
1196                COM12, CNCA0, etc.) returns a full
1197                name suitable for opening with the
1198                Serial class.
1199                """
1200               
1201                m = re.match('^COM(\d+)$', portname)
1202                if m and int(m.group(1)) < 10:
1203                        return portname
1204               
1205                return '\\\\.\\' + portname
1206       
1207       
1208        ##################################################################
1209       
1210        # LEGO Mindstorms Controls
1211       
1212        def turnLeft(self):
1213                self.brainstormsClient.sendCommand('turn_left')
1214                self.drive_state = 'turn_left'
1215       
1216        def driveForward(self):
1217                #if self.DEBUG:
1218                        #print "driveForward"
1219                self.pushButtonForward.setDown(True)
1220                if (self.drive_state != 'drive_forward'):
1221                        self.updateNXTSpeed(new_speed=DEFAULT_NXT_POWER_LEVEL)
1222                self.brainstormsClient.sendCommand('drive_forward', power=self.current_speed)
1223                self.drive_state = 'drive_forward'
1224       
1225        def turnRight(self):
1226                self.brainstormsClient.sendCommand('turn_right')
1227                self.drive_state = 'turn_right'
1228       
1229        def turnLeftInReverse(self):
1230                self.brainstormsClient.sendCommand('turn_left_in_reverse')
1231                self.drive_state = 'turn_left_in_reverse'
1232       
1233        def driveReverse(self):
1234                self.brainstormsClient.sendCommand('drive_reverse')
1235                self.drive_state = 'drive_reverse'
1236       
1237        def turnRightInReverse(self):
1238                self.brainstormsClient.sendCommand('turn_right_in_reverse')
1239                self.drive_state = 'turn_right_in_reverse'
1240       
1241        def stopMotors(self):
1242                self.pushButtonForward.setDown(False)
1243                if (self.current_speed != 0):
1244                        self.updateNXTSpeed(new_speed=0)
1245                if self.brainstormsClient != None:
1246                        self.brainstormsClient.sendCommand('stop_motors')
1247                self.drive_state = 'stop_motors'
1248       
1249        def sendMessageOne(self):
1250                message = str(self.lineEditMessageOne.text())
1251                self.brainstormsClient.sendCommand('send_message_1')
1252       
1253        def sendMessageTwo(self):
1254                message = str(self.lineEditMessageTwo.text())
1255                self.brainstormsClient.sendCommand('send_message_2')
1256       
1257        def sendMessageThree(self):
1258                message = str(self.lineEditMessageThree.text())
1259                self.brainstormsClient.sendCommand('send_message_3')
1260       
1261        def sendMessageFour(self):
1262                message = str(self.lineEditMessageFour.text())
1263                self.brainstormsClient.sendCommand('send_message_4')
1264       
1265        def sendMessageFive(self):
1266                message = str(self.lineEditMessageFive.text())
1267                self.brainstormsClient.sendCommand('send_message_5')
1268       
1269        def sendMessageSix(self):
1270                message = str(self.lineEditMessageSix.text())
1271                self.brainstormsClient.sendCommand('send_message_6')
1272       
1273       
1274        ##################################################################
1275       
1276        def enableHelicopterHover(self):
1277               
1278                self.helicopter.command = 'hover'
1279                self.helicopter.processCommand()
1280               
1281                self.disconnect(self.pushButtonHelicopterHover, \
1282                                                        QtCore.SIGNAL("clicked()"), \
1283                                                        self.enableHelicopterHover)
1284               
1285                self.connect(self.pushButtonHelicopterHover, \
1286                                  QtCore.SIGNAL("clicked()"), \
1287                                  self.disableHelicopterHover)
1288               
1289                if self.pushButtonHelicopterFlyForward.isChecked():
1290                        self.pushButtonHelicopterFlyForward.toggle()
1291                        self.disableHelicopterFlyForward()
1292       
1293       
1294        ##################################################################
1295       
1296        def disableHelicopterHover(self):
1297               
1298                self.helicopter.command = 'neutral'
1299                self.helicopter.processCommand()
1300               
1301                self.disconnect(self.pushButtonHelicopterHover, \
1302                                                        QtCore.SIGNAL("clicked()"), \
1303                                                        self.disableHelicopterHover)
1304               
1305                self.connect(self.pushButtonHelicopterHover, \
1306                                  QtCore.SIGNAL("clicked()"), \
1307                                  self.enableHelicopterHover)
1308       
1309       
1310        ##################################################################
1311       
1312        def enableHelicopterFlyForward(self):
1313               
1314                self.helicopter.command = 'fly_forward'
1315                self.helicopter.processCommand()
1316               
1317                self.disconnect(self.pushButtonHelicopterFlyForward, \
1318                                                        QtCore.SIGNAL("clicked()"), \
1319                                                        self.enableHelicopterFlyForward)
1320               
1321                self.connect(self.pushButtonHelicopterFlyForward, \
1322                                  QtCore.SIGNAL("clicked()"), \
1323                                  self.disableHelicopterFlyForward)
1324               
1325                if self.pushButtonHelicopterHover.isChecked():
1326                        self.pushButtonHelicopterHover.toggle()
1327                        self.disableHelicopterHover()
1328       
1329       
1330        ##################################################################
1331       
1332        def disableHelicopterFlyForward(self):
1333               
1334                self.helicopter.command = 'neutral'
1335                self.helicopter.processCommand()
1336               
1337                self.disconnect(self.pushButtonHelicopterFlyForward, \
1338                                                        QtCore.SIGNAL("clicked()"), \
1339                                                        self.disableHelicopterFlyForward)
1340               
1341                self.connect(self.pushButtonHelicopterFlyForward, \
1342                                  QtCore.SIGNAL("clicked()"), \
1343                                  self.enableHelicopterFlyForward)
1344       
1345       
1346        ##################################################################
1347       
1348        def landHelicopter(self):
1349               
1350                self.helicopter.command = 'neutral'
1351                self.helicopter.processCommand()
1352               
1353                if self.pushButtonHelicopterHover.isChecked():
1354                        self.pushButtonHelicopterHover.toggle()
1355                        self.disableHelicopterHover()
1356                if self.pushButtonHelicopterFlyForward.isChecked():
1357                        self.pushButtonHelicopterFlyForward.toggle()
1358                        self.disableHelicopterFlyForward()
1359       
1360       
1361        ##################################################################
1362       
1363        def driveWheelchairForward(self):
1364                print "WheelchairForward"
1365       
1366        def driveWheelchairReverse(self):
1367                print "WheelchairReverse"
1368       
1369        def driveWheelchairLeft(self):
1370                print "WheelchairLeft"
1371       
1372        def driveWheelchairRight(self):
1373                print "WheelchairRight"
1374       
1375        def stopWheelchair(self):
1376                print "stopWheelchair"
1377       
1378       
1379        ##################################################################
1380       
1381        def updateNXTSpeed(self, new_speed=None):
1382               
1383                if new_speed == None:
1384               
1385                        concentration=self.progressBarConcentration.value()
1386                        relaxation=self.progressBarRelaxation.value()
1387                       
1388                        new_speed = self.calculateSpeed(concentration, relaxation)
1389               
1390               
1391                # Update GUI
1392                if self.pushButtonSpeedEnable.isChecked():
1393                        self.progressBarSpeed.setValue(new_speed)
1394               
1395               
1396                # If there is a change between the new and current speeds
1397                # and either the robot is currently driving forward
1398                # or the "speed control" button is enabled,
1399                # then send the updated speed to the robot
1400                if ((self.current_speed != new_speed) and \
1401                         ((self.drive_state == 'drive_forward') or \
1402                          (self.pushButtonSpeedEnable.isChecked()))):
1403                       
1404                        if (new_speed == 0):
1405                                self.current_speed = new_speed
1406                                self.stopMotors()
1407                        else:
1408                                if ((self.brainstormsClient != None) and \
1409                                    (self.pushButtonSpeedEnable.isChecked())):
1410                                        self.pushButtonForward.setDown(True)
1411                                        self.brainstormsClient.sendCommand('drive_forward', power=new_speed)
1412               
1413               
1414                self.current_speed = new_speed
1415       
1416       
1417        ##################################################################
1418       
1419        def updateHelicopterSpeed(self, new_speed=None):
1420               
1421                if new_speed == None:
1422               
1423                        concentration=self.progressBarHelicopterConcentration.value()
1424                        relaxation=self.progressBarHelicopterRelaxation.value()
1425                       
1426                        new_speed = self.calculateSpeed(concentration, relaxation)
1427               
1428               
1429                # Update GUI
1430                if self.pushButtonHelicopterSpeedEnable.isChecked():
1431                        self.progressBarHelicopterSpeed.setValue(new_speed)
1432               
1433               
1434                self.current_speed = new_speed
1435       
1436       
1437        ##################################################################
1438       
1439        def updateWheelchairSpeed(self, new_speed=None):
1440               
1441                if new_speed == None:
1442               
1443                        concentration=self.progressBarWheelchairConcentration.value()
1444                        relaxation=self.progressBarWheelchairRelaxation.value()
1445                       
1446                        new_speed = self.calculateSpeed(concentration, relaxation)
1447               
1448               
1449                # Update GUI
1450                if self.pushButtonWheelchairSpeedEnable.isChecked():
1451                        self.progressBarWheelchairSpeed.setValue(new_speed)
1452               
1453               
1454                self.current_speed = new_speed
1455       
1456        ##################################################################
1457       
1458        def calculateSpeed(self, concentration, relaxation):
1459               
1460                speed = 0
1461               
1462                thresholds = THINKGEAR_POWER_THRESHOLDS
1463               
1464                match = int(concentration)
1465               
1466                while ((match not in thresholds['concentration'].keys()) and \
1467                            (match >= 0)):
1468                        match -= 1
1469               
1470               
1471                if match in thresholds['concentration'].keys():
1472                        speed = thresholds['concentration'][match]
1473               
1474               
1475                match = int(relaxation)
1476               
1477                while ((match not in thresholds['relaxation'].keys()) and \
1478                            (match >= 0)):
1479                        match -= 1
1480               
1481                if match in thresholds['relaxation'].keys():
1482                        speed = speed + thresholds['relaxation'][match]
1483               
1484               
1485                # LEGO Mindstorms power settings cannot exceed 100
1486                # and don't drive well with levels less than 50
1487                if (speed > 100):
1488                        speed = 100
1489                elif (speed < 50):
1490                        speed = 0
1491               
1492               
1493                return(speed)
1494       
1495       
1496        ##################################################################
1497       
1498        def processPacketThinkGear(self, packet):
1499               
1500                if ('eSense' in packet.keys()):
1501                       
1502                        if ('attention' in packet['eSense'].keys()):
1503                                if self.pushButtonConcentrationEnable.isChecked():
1504                                        self.progressBarConcentration.setValue(packet['eSense']['attention'])
1505                                if self.pushButtonHelicopterConcentrationEnable.isChecked():
1506                                        self.progressBarHelicopterConcentration.setValue(packet['eSense']['attention'])
1507                                if self.pushButtonWheelchairConcentrationEnable.isChecked():
1508                                        self.progressBarWheelchairConcentration.setValue(packet['eSense']['attention'])
1509                       
1510                        if ('meditation' in packet['eSense'].keys()):
1511                                if self.pushButtonRelaxationEnable.isChecked():
1512                                        self.progressBarRelaxation.setValue(packet['eSense']['meditation'])
1513                                if self.pushButtonHelicopterRelaxationEnable.isChecked():
1514                                        self.progressBarHelicopterRelaxation.setValue(packet['eSense']['meditation'])
1515                                if self.pushButtonWheelchairRelaxationEnable.isChecked():
1516                                        self.progressBarWheelchairRelaxation.setValue(packet['eSense']['meditation'])
1517               
1518               
1519                self.updateNXTSpeed()
1520                self.updateHelicopterSpeed()
1521                self.updateWheelchairSpeed()
1522       
1523       
1524        ##################################################################
1525
1526        def sendFeedback(self):
1527               
1528                values = {}
1529
1530                values['name'] = str(self.lineEditFeedbackName.text())
1531                values['email'] = str(self.lineEditFeedbackEmail.text())
1532                values['comment'] = str(self.textEditFeedback.toPlainText())
1533               
1534                values['subject'] = '[brainstorms feedback]'
1535                values['capcha_contact'] = 'brainstorms'
1536               
1537               
1538                url_data = urllib.urlencode(values)
1539               
1540                try:
1541                        page = urllib.urlopen(BRAINSTORMS_FEEDBACK_URL, url_data)
1542                       
1543                        reply = QtGui.QMessageBox.information( \
1544                              self, \
1545                              'Feedback Sent', \
1546                              'Thank you for your feedback', \
1547                              'OK')
1548                       
1549                        self.lineEditFeedbackName.setText('')
1550                        self.lineEditFeedbackEmail.setText('')
1551                        self.textEditFeedback.setText('')
1552               
1553                except:
1554                        reply = QtGui.QMessageBox.information( \
1555                              self, \
1556                              'Feedback Sent', \
1557                              'We\'re sorry but there was an error submitting your feedback.\nPlease email contact@puzzlebox.info instead.', \
1558                              'OK')
1559       
1560       
1561        ##################################################################
1562       
1563        def closeEvent(self, event):
1564               
1565                quit_message = "Are you sure you want to exit the program?"
1566               
1567                reply = QtGui.QMessageBox.question( \
1568                           self, \
1569                          'Quit Puzzlebox Brainstorms', \
1570                           quit_message, \
1571                           QtGui.QMessageBox.Yes, \
1572                           QtGui.QMessageBox.No)
1573               
1574                if reply == QtGui.QMessageBox.Yes:
1575                       
1576                        if self.brainstormsClient != None:
1577                                self.stopMotors()
1578                                self.brainstormsClient.socket.flush()
1579                               
1580                                if self.brainstormsServer != None:
1581                                       
1582                                        if self.brainstormsServer.rc == None:
1583                                               
1584                                                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
1585                                                self.brainstormsServer.executeCommand( \
1586                                                        'stop_motors', \
1587                                                        bluetooth_device=bluetooth_device)
1588                                               
1589                                        else:
1590                                                self.brainstormsServer.rc.run('stop_motors')
1591                       
1592                       
1593                        event.accept()
1594               
1595                else:
1596                        event.ignore()
1597
1598
1599#####################################################################
1600# Functions
1601#####################################################################
1602
1603#####################################################################
1604# Main
1605#####################################################################
1606
1607if __name__ == '__main__':
1608       
1609        #log = puzzlebox_logger.puzzlebox_logger(logfile='client_interface')
1610        log = None
1611       
1612        app = QtGui.QApplication(sys.argv)
1613       
1614        window = puzzlebox_brainstorms_client_interface(log, DEBUG)
1615        window.show()
1616       
1617        sys.exit(app.exec_())
1618
Note: See TracBrowser for help on using the repository browser.