source: trunk/brainstorms/Puzzlebox/Brainstorms/Helicopter_Control.py @ 240

Last change on this file since 240 was 240, checked in by sc, 12 years ago

puzzlebox_brainstorms_wheelchair_noisebridge.pde:

  • relocated to necessary location for ide

trunk/brainstorms/Puzzlebox/Brainstorms/Wheelchair_Control.py:

  • object model adopted

trunk/brainstorms/Puzzlebox/Brainstorms/Helicopter_Control.py:

  • whitespace cleanup
  • Property svn:executable set to *
File size: 20.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Helicopter Control
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.22
13
14"""
15
16import sys, time
17import signal
18import serial
19
20try:
21        import PySide as PyQt4
22        from PySide import QtCore
23except:
24        print "Using PyQt4 module"
25        from PyQt4 import QtCore
26else:
27        print "Using PySide module"
28
29#import Configuration as configuration
30
31#import Puzzlebox.Synapse.Protocol as protocol
32#from Puzzlebox.Synapse import Protocol
33
34#####################################################################
35# Globals
36#####################################################################
37
38DEBUG = 2
39
40DEFAULT_COMMAND = 'dump_packets'
41
42SERIAL_DEVICE = '/dev/ttyUSB0'
43#SERIAL_DEVICE = '/dev/ttyACM0'
44#DEFAULT_SERIAL_BAUDRATE = 115200 # This is the closest "standard" baud rate the USB-to-Serial device will support
45#DEFAULT_SERIAL_BAUDRATE = 125000 # This is the speed reported by the forum post
46#DEFAULT_SERIAL_BAUDRATE = 128000 # This is the next closest somewhat commonly-found baud rate (though not supported by device)
47DEFAULT_SERIAL_BAUDRATE = 133333 # This is the speed reported by the logic analyzer
48#DEFAULT_SERIAL_BAUDRATE = 230400 # This is the next highest "standard" baud rate the USB-to-Serial device will support
49DEFAULT_MODE = 'read'
50
51PROTOCOL_SYNC_TIME = 5
52PROTOCOL_SYNC_HEAD1 = '\x00'
53PROTOCOL_SYNC_HEAD2 = '\x00'
54PROTOCOL_ADD_SYNC_TO_HEAD = False
55PROTOCOL_ADD_SYNC_TO_TAIL = False
56PACKET_LENGTH = 14
57PAYLOAD_MINIMUM_LENGTH = 12
58PACKET_READ_SIZE = 14
59ECHO_ON = False
60
61#DEVICE_BUFFER_TIMER = 22  # Frame cycle 22ms
62DEVICE_BUFFER_TIMER = 21  # Frame cycle 22ms
63
64COMMAND_PACKET = {
65        'neutral':        '\x00\x00\x00\xfa\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa',  # default neutral setting to use for all commands
66        'no_thrust':      '\x00\x00\x00\x5a\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa',  # lowest trim setting for throttle
67        'minimum_thrust': '\x00\x00\x00\xca\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa',  # lowest trim level at which throttle kicks in
68        'minimum_thrust_minus_one': '\x00\x00\x00\xc6\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa',  # lowest trim level at which throttle kicks in
69        'maximum_thrust': '\x00\x00\x03\x54\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa',  # maximum possible throttle and trim
70        'fifty_percent_thrust': '\x00\x00\x01\x7d\x05\xc5\x09\xde\x0e\x0b\x13\x54\x14\xaa', # calculated 50% throttle
71        'test_packet':    '\x00\x00\x03\x54\x06\x15\x09\xca\x0e\x2f\x13\x54\x14\xaa', # test packet from saleae logic screenshot
72        'maximum_forward': '\x00\x00\x00\x5a\x05\xc5\x0b\x54\x0e\x0b\x13\x54\x14\xaa', # maximum possible elevator and trim
73            'fly_forward': '\x00\x00\x01\x7d\x05\xc5\x0a\xde\x0e\x0b\x13\x54\x14\xaa', \
74}
75
76DEFAULT_COMMAND_PACKET = COMMAND_PACKET['neutral']
77
78#####################################################################
79# Classes
80#####################################################################
81
82class puzzlebox_brainstorms_helicopter_control(QtCore.QThread):
83       
84        def __init__(self, \
85                     device_address=SERIAL_DEVICE, \
86                     command=DEFAULT_COMMAND, \
87                     DEBUG=DEBUG, \
88                     parent=None):
89               
90                QtCore.QThread.__init__(self, parent)
91               
92                self.log = None
93                self.DEBUG = DEBUG
94                self.parent = parent
95               
96                self.device_address = device_address
97                self.command = command
98                self.mode = DEFAULT_MODE
99               
100                self.serial_device = None
101                self.protocol = None
102               
103               
104                #self.configureRemote()
105       
106       
107        ##################################################################
108       
109        def configureRemote(self):
110               
111                self.serial_device = \
112                        SerialDevice( \
113                                self.log, \
114                                device_address=self.device_address, \
115                                mode=self.mode, \
116                                DEBUG=self.DEBUG, \
117                                parent=self)
118               
119                self.serial_device.start()
120               
121               
122                self.protocol = \
123                        ProtocolHandler( \
124                                self.log, \
125                                self.serial_device, \
126                                mode=self.mode, \
127                                DEBUG=self.DEBUG, \
128                                parent=self)
129               
130                self.protocol.start()
131       
132       
133        ##################################################################
134       
135        def processPacket(self, packet):
136               
137                if self.DEBUG:
138                        print "data_payload:",
139                        #print packet['data_payload']
140                        print packet['data_payload'].encode("hex")
141                       
142                        #if packet['data_payload'].encode("hex") == '80acdf22cdb08b8d54':
143                                #print True
144                                #import cPickle as pickle
145                                #file = open('packet.data', 'w')
146                                #pickle.dump(packet['data_payload'], file)
147                                #file.close()
148                                #sys.exit(app.exec_())
149               
150                #if (packet != {}):
151                        #self.packet_queue.append(packet)
152                        ###self.sendPacketQueue()
153               
154                if (self.parent != None):
155                        self.parent.processPacket(self.protocol.data_packet)
156       
157       
158        ##################################################################
159       
160        def dump_packets(self):
161               
162                pass
163       
164       
165        ##################################################################
166       
167        def sync_to_helicopter(self):
168               
169                self.protocol.command_packet = COMMAND_PACKET['no_thrust']
170                QtCore.QThread.msleep(PROTOCOL_SYNC_TIME * 1000) # 4 seconds minimum to sync
171       
172       
173        ##################################################################
174       
175        def neutral(self):
176               
177                if self.DEBUG:
178                        print "--> RC Helicopter Command: neutral"
179               
180                #self.protocol.command_packet = COMMAND_PACKET['neutral']
181                self.protocol.command_packet = COMMAND_PACKET['no_thrust']
182       
183       
184        ##################################################################
185       
186        def test_packet(self):
187               
188                if self.DEBUG:
189                        print "--> RC Helicopter Command: test_packet"
190               
191                self.protocol.command_packet = COMMAND_PACKET['test_packet']
192       
193       
194        ##################################################################
195       
196        def test_mode(self):
197               
198                if self.DEBUG:
199                        print "--> RC Helicopter Command: test_mode"
200               
201                #self.sync_to_helicopter()
202               
203                self.protocol.command_packet = COMMAND_PACKET['minimum_thrust']
204                QtCore.QThread.msleep(2 * 1000) # 1 second
205               
206                self.protocol.command_packet = COMMAND_PACKET['no_thrust']
207       
208       
209        ##################################################################
210       
211        def hover(self, duration=2):
212               
213                if self.DEBUG:
214                        print "--> RC Helicopter Command: hover"
215               
216                #self.sync_to_helicopter()
217               
218                self.protocol.command_packet = COMMAND_PACKET['fifty_percent_thrust']
219               
220                if duration != None:
221                        QtCore.QThread.msleep(duration * 1000)
222                       
223                        self.protocol.command_packet = COMMAND_PACKET['no_thrust']
224       
225       
226        ##################################################################
227       
228        def fly_forward(self, duration=2):
229               
230                if self.DEBUG:
231                        print "--> RC Helicopter Command: fly_forward"
232               
233                #self.sync_to_helicopter()
234               
235                self.protocol.command_packet = COMMAND_PACKET['fly_forward']
236               
237                if duration != None:
238                        QtCore.QThread.msleep(duration * 1000)
239                       
240                        self.protocol.command_packet = COMMAND_PACKET['no_thrust']
241       
242       
243        ##################################################################
244       
245        def processCommand(self):
246               
247                if (self.command == 'dump_packets') or (self.command == 'read'):
248                        self.mode = 'read'
249                else:
250                        self.mode = 'write'
251               
252               
253                self.configureRemote()
254               
255               
256                if (self.command == 'dump_packets'):
257                        self.mode = 'read'
258                        self.dump_packets()
259               
260                elif (self.command == 'neutral'):
261                        self.mode = 'write'
262                        self.neutral()
263               
264                elif (self.command == 'test_packet'):
265                        self.mode = 'write'
266                        self.test_packet()
267               
268                elif (self.command == 'test_mode'):
269                        self.mode = 'write'
270                        self.sync_to_helicopter()
271                        self.test_mode()
272               
273                elif (self.command == 'hover'):
274                        self.mode = 'write'
275                        self.sync_to_helicopter()
276                        self.hover()
277               
278                elif (self.command == 'fly_forward'):
279                        self.mode = 'write'
280                        self.sync_to_helicopter()
281                        self.fly_forward(duration=2)
282       
283       
284        ##################################################################
285       
286        def stop(self):
287               
288                #self.connection.close()
289                pass
290       
291       
292        ##################################################################
293       
294        def run(self):
295               
296                if self.DEBUG:
297                        print "<---- [%s] Main thread running" % "Helicopter Remote"
298               
299               
300                self.processCommand()
301               
302                self.exec_()
303       
304       
305        ##################################################################
306       
307        def exitThread(self, callThreadQuit=True):
308               
309                try:
310                        self.emulationTimer.stop()
311                except:
312                        pass
313               
314                if self.serial_device != None:
315                        self.serial_device.exitThread()
316               
317                if self.protocol != None:
318                        self.protocol.exitThread()
319               
320                self.socket.close()
321               
322                if callThreadQuit:
323                        QtCore.QThread.quit(self)
324               
325                if self.parent == None:
326                        sys.exit()
327
328
329#####################################################################
330#####################################################################
331
332class ProtocolHandler(QtCore.QThread):
333       
334        def __init__(self, log, \
335                               serial_device, \
336                               mode=DEFAULT_MODE, \
337                               DEBUG=DEBUG, \
338                               parent=None):
339               
340                QtCore.QThread.__init__(self,parent)
341               
342                self.log = log
343                self.DEBUG = DEBUG
344                self.parent = parent
345               
346                self.device = None
347                self.mode = mode
348               
349                self.device = serial_device
350               
351                self.packet_count = 0
352                self.bad_packets = 0
353               
354                self.keep_running = True
355               
356                self.command_packet = DEFAULT_COMMAND_PACKET
357       
358       
359        ##################################################################
360       
361        def processDataPayload(self, data_payload, payload_timestamp):
362               
363                packet_update = {}
364                packet_update['data_payload'] = data_payload
365                packet_update['payload_timestamp'] = payload_timestamp
366               
367               
368                if (self.parent != None):
369                        self.parent.processPacket(packet_update)
370       
371       
372        ##################################################################
373       
374        def parseStream(self):
375               
376                # Loop forever, parsing one packet per loop
377                packet_count = 0
378               
379                while self.keep_running:
380                       
381                        # Synchronize on [SYNC] bytes
382                        byte = self.device.read()
383                        #print byte.encode("hex")
384                       
385                        #if (byte != PROTOCOL_SYNC):
386                        if (byte != PROTOCOL_SYNC_HEAD1):
387                                continue
388                       
389                        byte = self.device.read()
390                        if (byte != PROTOCOL_SYNC_HEAD2):
391                                continue
392                       
393                       
394                        payload_timestamp = time.time()
395                       
396                        data_payload = self.device.getBuffer()
397                        data_payload = "%s%s%s" % (PROTOCOL_SYNC_HEAD1, PROTOCOL_SYNC_HEAD2, data_payload)
398                       
399                       
400                        if len(data_payload) < PAYLOAD_MINIMUM_LENGTH:
401                        #if len(data_payload) != PACKET_LENGTH:
402                                continue
403                       
404                       
405                        self.processDataPayload(data_payload, payload_timestamp)
406                       
407                       
408                        #if self.DEBUG > 1:
409                                #packet_count += 1
410                                #if packet_count >= DEBUG_PACKET_COUNT:
411                                        #print "max debugging count reached, disconnecting"
412                                        #self.keep_running = False
413                                        #self.device.stop()
414                                        #QtCore.QThread.quit(self)
415                                        ##sys.exit()
416       
417       
418        ##################################################################
419       
420        def writeStream(self):
421               
422                # Loop forever, writing one packet per loop
423                packet_count = 0
424               
425                #import cPickle as pickle
426                #file = open('packet.data', 'r')
427                #packet = pickle.loads(file.read())
428                #file.close()
429               
430                while self.keep_running:
431                       
432                        # Preppend or Append [SYNC] bytes
433                        #if PROTOCOL_ADD_SYNC_TO_HEAD:
434                                #buffer = PROTOCOL_SYNC_HEAD1
435                                #buffer += PROTOCOL_SYNC_HEAD2
436                                #buffer += self.command_packet
437                       
438                        #if PROTOCOL_ADD_SYNC_TO_TAIL:
439                                #buffer = self.command_packet
440                                #buffer += PROTOCOL_SYNC_HEAD1
441                                #buffer += PROTOCOL_SYNC_HEAD2
442                               
443                        buffer = self.command_packet
444                        self.device.buffer = buffer
445                        #self.device.buffer = packet
446                        #print packet.encode("hex")
447                       
448                        # Sleep for 20 ms
449                        # Based on 50 Hz refresh rate of Blade MLP4DSM RC device
450                        # (1/50) * 1000 = 20
451                        QtCore.QThread.msleep(DEVICE_BUFFER_TIMER)
452       
453       
454        ##################################################################
455       
456        def run(self):
457               
458                self.packet_count = 0
459                self.bad_packets = 0
460                self.session_start_timestamp = time.time()
461               
462                if self.mode == 'read':
463                        self.parseStream()
464               
465                elif self.mode == 'write':
466                        self.writeStream()
467       
468       
469        ##################################################################
470       
471        def exitThread(self, callThreadQuit=True):
472               
473                try:
474                        self.device.stop()
475                except:
476                        pass
477               
478                #self.wait()
479                if callThreadQuit:
480                        QtCore.QThread.quit(self)
481
482
483#####################################################################
484#####################################################################
485
486class SerialDevice(QtCore.QThread):
487       
488        def __init__(self, log, \
489                               device_address=SERIAL_DEVICE, \
490                               mode=DEFAULT_MODE, \
491                               DEBUG=DEBUG, \
492                               parent=None):
493               
494                QtCore.QThread.__init__(self, parent)
495               
496                self.log = log
497                self.DEBUG = DEBUG
498               
499                self.device_address = device_address
500                self.mode = mode
501                self.device = None
502                self.buffer = ''
503               
504                if (self.device_address.count(':') == 5):
505                        # Device address is a Bluetooth MAC address
506                        self.device = self.initializeBluetoothDevice()
507                else:
508                        # Device address is a serial port address
509                        self.device = self.initializeSerialDevice()
510               
511                #self.buffer_check_timer = QtCore.QTimer()
512                #QtCore.QObject.connect(self.buffer_check_timer, \
513                                       #QtCore.SIGNAL("timeout()"), \
514                                       #self.checkBuffer)
515                #self.buffer_check_timer.start(DEVICE_BUFFER_TIMER)
516               
517                self.keep_running = True
518       
519       
520        ##################################################################
521       
522        #def initializeBluetoothDevice(self):
523               
524                #socket = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
525               
526                #try:
527                        #socket.connect((self.device_address, THINKGEAR_DEVICE_BLUETOOTH_CHANNEL))
528               
529                #except Exception, e:
530                        #if self.DEBUG:
531                                #print "ERROR:",
532                                #print e
533                                #sys.exit()
534               
535               
536                #return socket
537       
538       
539        ###################################################################
540       
541        def initializeSerialDevice(self):
542               
543                baudrate = DEFAULT_SERIAL_BAUDRATE
544                bytesize = 8
545                parity = 'NONE'
546                stopbits = 1
547                software_flow_control = 'f'
548                rts_cts_flow_control = 'f'
549                #timeout = 15
550                timeout = 5
551               
552                # convert bytesize
553                if (bytesize == 5):
554                        init_byte_size = serial.FIVEBITS
555                elif (bytesize == 6):
556                        init_byte_size = serial.SIXBITS
557                elif (bytesize == 7):
558                        init_byte_size = serial.SEVENBITS
559                elif (bytesize == 8):
560                        init_byte_size = serial.EIGHTBITS
561                else:
562                        #self.log.perror("Invalid value for %s modem byte size! Using default (8)" % modem_type)
563                        init_byte_size = serial.EIGHTBITS
564               
565                # convert parity
566                if (parity == 'NONE'):
567                        init_parity = serial.PARITY_NONE
568                elif (parity == 'EVEN'):
569                        init_parity = serial.PARITY_EVEN
570                elif (parity == 'ODD'):
571                        init_parity = serial.PARITY_ODD
572                else:
573                        #self.log.perror("Invalid value for %s modem parity! Using default (NONE)" % modem_type)
574                        init_parity = serial.PARITY_NONE
575               
576                # convert stopbits
577                if (stopbits == 1):
578                        init_stopbits = serial.STOPBITS_ONE
579                elif (stopbits == 2):
580                        init_stopbits = serial.STOPBITS_TWO
581                else:
582                        #self.log.perror("Invalid value for %s modem stopbits! Using default (8)" % modem_type)
583                        init_byte_size = serial.STOPBITS_ONE
584               
585                # convert software flow control
586                if (software_flow_control == 't'):
587                        init_software_flow_control = 1
588                else:
589                        init_software_flow_control = 0
590               
591                # convert rts cts flow control
592                if (rts_cts_flow_control == 't'):
593                        init_rts_cts_flow_control = 1
594                else:
595                        init_rts_cts_flow_control = 0
596               
597               
598                try:
599                       
600                        device = serialWrapper(port = self.device_address, \
601                                                    baudrate = baudrate, \
602                                                    bytesize = init_byte_size, \
603                                                    parity = init_parity, \
604                                                    stopbits = init_stopbits, \
605                                                    xonxoff = init_software_flow_control, \
606                                                    rtscts = init_rts_cts_flow_control, \
607                                                    timeout = timeout)
608               
609                except Exception, e:
610                        if self.DEBUG:
611                                print "ERROR:",
612                                print e,
613                                print self.device_address
614                                sys.exit()
615               
616               
617                #device.flushInput()
618                ##device.flushOutput()
619               
620               
621                return(device)
622       
623       
624        ###################################################################
625       
626        #def checkBuffer(self):
627               
628                #if self.DEBUG > 1:
629                        #print "INFO: Buffer size check:",
630                        #print len(self.buffer),
631                        #print "(maximum before reset is %i)" % DEVICE_BUFFER_MAX_SIZE
632               
633                #if (DEVICE_BUFFER_MAX_SIZE <= len(self.buffer)):
634                       
635                        #if self.DEBUG:
636                                #print "ERROR: Buffer size has grown too large, resetting"
637                       
638                        #self.reset()
639       
640       
641        ###################################################################
642       
643        def getBuffer(self):
644               
645                data_payload = self.buffer
646               
647                self.resetBuffer()
648               
649               
650                return(data_payload)
651       
652       
653        ###################################################################
654       
655        def resetBuffer(self):
656               
657                self.buffer = ''
658       
659       
660        ###################################################################
661       
662        def read(self, length=1):
663               
664                # Sleep for 20 ms if buffer is empty
665                # Based on 50 Hz refresh rate of Blade MLP4DSM RC device
666                # (1/50) * 1000 = 20
667                while len(self.buffer) < length:
668                        QtCore.QThread.msleep(DEVICE_BUFFER_TIMER)
669                       
670                bytes = self.buffer[:length]
671               
672                self.buffer = self.buffer[length:]
673               
674                return(bytes)
675       
676       
677        ###################################################################
678       
679        def stop(self):
680               
681                #self.buffer_check_timer.stop()
682                self.keep_running = False
683       
684       
685        ###################################################################
686       
687        def exitThread(self, callThreadQuit=True):
688               
689                self.stop()
690                self.close()
691               
692                if callThreadQuit:
693                        QtCore.QThread.quit(self)
694       
695       
696        ###################################################################
697       
698        def close(self):
699               
700                self.device.close()
701       
702       
703        ###################################################################
704       
705        def readBuffer(self):
706       
707                self.buffer = ''
708               
709                while self.keep_running:
710                       
711                       
712                        # High-Speed Echo Mode
713                        if (self.DEBUG > 3) and ECHO_ON:
714                                byte = self.device.recv(PACKET_READ_SIZE)
715                                self.device.write(byte)
716                                continue
717                       
718                       
719                        try:
720                                #byte = self.device.read()
721                                byte = self.device.recv(PACKET_READ_SIZE)
722                               
723                                #if ECHO_ON:
724                                self.device.write(byte)
725                               
726                                if (len(byte) != 0):
727                                        if self.DEBUG > 2:
728                                                print "Device read:",
729                                                print byte,
730                                                if ECHO_ON:
731                                                        print byte.encode("hex"),
732                                                        print "wrote:",
733                                                print byte.encode("hex")
734                                               
735                                        self.buffer += byte
736                       
737                        except:
738                                if self.DEBUG:
739                                        print "ERROR: failed to read from serial device"
740                                break
741               
742               
743                self.exitThread()
744       
745       
746        ###################################################################
747       
748        def writeBuffer(self):
749       
750                self.buffer = ''
751                #beacon_timer = 0
752               
753                while self.keep_running:
754                       
755                        if (len(self.buffer) != 0):
756                                buffer = self.buffer
757                                self.buffer = ''
758                               
759                               
760                                #if beacon_timer >= 750:
761                                        #buffer += '\xaa' + buffer
762                                        #beacon_timer = 0
763                               
764                               
765                                try:
766                                        self.device.write(buffer)
767                                       
768                                        if self.DEBUG > 1:
769                                                print "Device wrote:",
770                                                #print buffer,
771                                                print buffer.encode("hex")
772                               
773                                except:
774                                        if self.DEBUG:
775                                                print "ERROR: failed to write to serial device"
776                                        break
777                       
778                       
779                        # Sleep for 20 ms if buffer is empty
780                        # Based on 50 Hz refresh rate of Blade MLP4DSM RC device
781                        # (1/50) * 1000 = 20
782                        QtCore.QThread.msleep(DEVICE_BUFFER_TIMER)
783                        #beacon_timer += DEVICE_BUFFER_TIMER
784               
785               
786                self.exitThread()
787       
788       
789        ###################################################################
790       
791        def run(self):
792               
793                if self.mode == 'read':
794                        self.readBuffer()
795               
796                elif self.mode == 'write':
797                        self.writeBuffer()
798
799
800#####################################################################
801#####################################################################
802
803class serialWrapper(serial.Serial):
804       
805        #__init__(port=None, baudrate=9600, bytesize=EIGHTBITS, parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, writeTimeout=None, dsrdtr=False, interCharTimeout=None)
806       
807        def recv(self, size=1):
808               
809                return(self.read(size))
810
811
812#####################################################################
813# Functions
814#####################################################################
815
816#####################################################################
817# Main
818#####################################################################
819
820if __name__ == '__main__':
821       
822        # Perform correct KeyboardInterrupt handling
823        signal.signal(signal.SIGINT, signal.SIG_DFL)
824       
825        # Collect default settings and command line parameters
826        device = SERIAL_DEVICE
827        command = DEFAULT_COMMAND
828       
829        for each in sys.argv:
830               
831                if each.startswith("--device="):
832                        device = each[ len("--device="): ]
833                elif each.startswith("--command="):
834                        command = each[ len("--command="): ]
835       
836       
837        app = QtCore.QCoreApplication(sys.argv)
838       
839        rc = puzzlebox_brainstorms_helicopter_control(device_address=device, command=command, DEBUG=DEBUG)
840       
841        rc.start()
842       
843        sys.exit(app.exec_())
844
Note: See TracBrowser for help on using the repository browser.