Changeset 126


Ignore:
Timestamp:
07/28/10 02:18:53 (11 years ago)
Author:
sc
Message:

thinkgear_emulator/puzzlebox_thinkgear_serial_protocol.py:

  • timed check added to ensure device buffer size does not exceed the maximum data packet size, which would mean the processing algorithm had fallen behind at least one entire packet
  • comment cleanup
File:
1 edited

Legend:

Unmodified
Added
Removed
  • thinkgear_emulator/puzzlebox_thinkgear_serial_protocol.py

    r125 r126  
    9292PROTOCOL_EXCODE = '\x55' 
    9393 
     94DEVICE_BUFFER_CHECK_TIMER = 60 * 1000 # Check buffer size once every minute 
     95DEVICE_BUFFER_MAX_SIZE = 180 # Reset buffer if it grow this large 
     96                             # as this would indicate the processing 
     97                             # algorithm is not keeping up with the device 
     98                             # According to protocol specification, 
     99                             # "...a complete, valid Packet is ... a maximum 
     100                             # of 173 bytes long (possible if the Data Payload 
     101                             # is the maximum 169 bytes long)." 
     102                             # Therefore we reset if our buffer has grown longer 
     103                             # than the maximum packet length as this means 
     104                             # the processing algorthim is at least one full 
     105                             # packet behind. 
     106 
    94107DEBUG_BYTE_COUNT = 819200 
    95108DEBUG_PACKET_COUNT = 128 
     
    116129                self.buffer = '' 
    117130                 
    118                 #self.device = self.initialize_device() 
    119                  
    120131                self.device = serial_device 
    121          
    122          
    123         ################################################################## 
    124          
    125         #def initialize_device(self): 
    126                  
    127                 #baudrate = DEFAULT_SERIAL_BAUDRATE 
    128                 #bytesize = 8 
    129                 #parity = 'NONE' 
    130                 #stopbits = 1 
    131                 #software_flow_control = 'f' 
    132                 #rts_cts_flow_control = 'f' 
    133                 ##timeout = 15 
    134                 #timeout = 5 
    135                  
    136                 ## convert bytesize 
    137                 #if (bytesize == 5): 
    138                         #init_byte_size = serial.FIVEBITS 
    139                 #elif (bytesize == 6): 
    140                         #init_byte_size = serial.SIXBITS 
    141                 #elif (bytesize == 7): 
    142                         #init_byte_size = serial.SEVENBITS 
    143                 #elif (bytesize == 8): 
    144                         #init_byte_size = serial.EIGHTBITS 
    145                 #else: 
    146                         ##self.log.perror("Invalid value for %s modem byte size! Using default (8)" % modem_type) 
    147                         #init_byte_size = serial.EIGHTBITS 
    148                  
    149                 ## convert parity 
    150                 #if (parity == 'NONE'): 
    151                         #init_parity = serial.PARITY_NONE 
    152                 #elif (parity == 'EVEN'): 
    153                         #init_parity = serial.PARITY_EVEN 
    154                 #elif (parity == 'ODD'): 
    155                         #init_parity = serial.PARITY_ODD 
    156                 #else: 
    157                         ##self.log.perror("Invalid value for %s modem parity! Using default (NONE)" % modem_type) 
    158                         #init_parity = serial.PARITY_NONE 
    159                  
    160                 ## convert stopbits 
    161                 #if (stopbits == 1): 
    162                         #init_stopbits = serial.STOPBITS_ONE 
    163                 #elif (stopbits == 2): 
    164                         #init_stopbits = serial.STOPBITS_TWO 
    165                 #else: 
    166                         ##self.log.perror("Invalid value for %s modem stopbits! Using default (8)" % modem_type) 
    167                         #init_byte_size = serial.STOPBITS_ONE 
    168                  
    169                 ## convert software flow control 
    170                 #if (software_flow_control == 't'): 
    171                         #init_software_flow_control = 1 
    172                 #else: 
    173                         #init_software_flow_control = 0 
    174                  
    175                 ## convert rts cts flow control 
    176                 #if (rts_cts_flow_control == 't'): 
    177                         #init_rts_cts_flow_control = 1 
    178                 #else: 
    179                         #init_rts_cts_flow_control = 0 
    180                  
    181                  
    182                 ## Initialize the modem 
    183                 ##self.log.pdebug("Initializing %s modem" % modem_code) 
    184                  
    185                 #device = serial.Serial(port = serial_port, \ 
    186                                             #baudrate = baudrate, \ 
    187                                             #bytesize = init_byte_size, \ 
    188                                             #parity = init_parity, \ 
    189                                             #stopbits = init_stopbits, \ 
    190                                             #xonxoff = init_software_flow_control, \ 
    191                                             #rtscts = init_rts_cts_flow_control, \ 
    192                                             #timeout = timeout) 
    193                  
    194                  
    195                 #return(device) 
    196132         
    197133         
     
    454390        ################################################################## 
    455391         
    456         def process_packet(self, packet): 
    457                  
    458                 '''Each Packet begins with its Header, followed by its Data Payload,  
    459                 and ends with the Payload's Check-sum Byte, as follows: 
    460                 [SYNC] [SYNC] [PLENGTH]      [PAYLOAD...]         [CHKSUM] 
    461                 _______________________      _____________     ____________ 
    462                 ^^^^^^^^(Header)^^^^^^^      ^^(Payload)^^     ^(Checksum)^''' 
    463                  
    464                 valid_length = False 
    465                 valid_checksum = False 
    466                  
    467                 if self.DEBUG > 3: 
    468                         print packet 
    469                  
    470                  
    471                 # SPEC: [PLENGTH] byte indicates the length, in bytes, of the  
    472                 # Packet's Data Payload [PAYLOAD...] section, and may be any value  
    473                 # from 0 up to 169. Any higher value indicates an error  
    474                 # (PLENGTH TOO LARGE). Be sure to note that [PLENGTH] is the length  
    475                 # of the Packet's Data Payload, NOT of the entire Packet.  
    476                 # The Packet's complete length will always be [PLENGTH] + 4. 
    477                  
    478                 packet_length = packet[2] 
    479                 packet_length = packet_length.encode("hex") 
    480                 packet_length = int(packet_length, 16) 
    481                  
    482                 print "packet_length:", 
    483                 print packet_length 
    484                 print "  len(packet):", 
    485                 print len(packet) 
    486                  
    487                  
    488                 if ((packet_length <= 169) and \ 
    489                          (packet_length + 4) == (len(packet))): 
    490                          
    491                         if self.DEBUG > 2: 
    492                                 print "packet length correct" 
    493                          
    494                         valid_length = True 
    495                  
    496                 else: 
    497                         if self.DEBUG: 
    498                                 print "ERROR: packet length bad" 
    499                  
    500                  
    501                 if valid_length: 
    502                          
    503                         data_payload = packet[3:-1] 
    504                          
    505                         # SPEC: The [CHKSUM] Byte must be used to verify the integrity of the 
    506                         # Packet's Data Payload. The Payload's Checksum is defined as: 
    507                         #  1. summing all the bytes of the Packet's Data Payload 
    508                         #  2. taking the lowest 8 bits of the sum 
    509                         #  3. performing the bit inverse (one's compliment inverse) 
    510                         #     on those lowest 8 bits 
    511                          
    512                         packet_checksum = packet[-1] 
    513                         packet_checksum = packet_checksum.encode("hex") 
    514                         packet_checksum = int(packet_checksum, 16) 
    515                          
    516                         payload_checksum = 0 
    517                         for byte in data_payload: 
    518                                 value = byte.encode("hex") 
    519                                 value = int(value, 16) 
    520                                 payload_checksum += value 
    521                          
    522                         # Take the lowest 8 bits of the calculated payload_checksum 
    523                         # and invert them. Serious C code mojo. 
    524                         payload_checksum &= 0xff 
    525                         payload_checksum = ~payload_checksum & 0xff 
    526                          
    527                          
    528                         if packet_checksum != payload_checksum: 
    529                                 if self.DEBUG > 1: 
    530                                         print "ERROR: packet checksum does not match" 
    531                                         print "       packet_checksum:", 
    532                                         print packet_checksum 
    533                                         print "       payload_checksum:", 
    534                                         print payload_checksum 
    535                          
    536                         else: 
    537                                 valid_checksum = True 
    538                                 if self.DEBUG > 2: 
    539                                         print "packet checksum correct" 
     392        #def process_packet(self, packet): 
     393                 
     394                #'''Each Packet begins with its Header, followed by its Data Payload,  
     395                #and ends with the Payload's Check-sum Byte, as follows: 
     396                #[SYNC] [SYNC] [PLENGTH]      [PAYLOAD...]         [CHKSUM] 
     397                #_______________________      _____________     ____________ 
     398                #^^^^^^^^(Header)^^^^^^^      ^^(Payload)^^     ^(Checksum)^''' 
     399                 
     400                #valid_length = False 
     401                #valid_checksum = False 
     402                 
     403                #if self.DEBUG > 3: 
     404                        #print packet 
     405                 
     406                 
     407                ## SPEC: [PLENGTH] byte indicates the length, in bytes, of the  
     408                ## Packet's Data Payload [PAYLOAD...] section, and may be any value  
     409                ## from 0 up to 169. Any higher value indicates an error  
     410                ## (PLENGTH TOO LARGE). Be sure to note that [PLENGTH] is the length  
     411                ## of the Packet's Data Payload, NOT of the entire Packet.  
     412                ## The Packet's complete length will always be [PLENGTH] + 4. 
     413                 
     414                #packet_length = packet[2] 
     415                #packet_length = packet_length.encode("hex") 
     416                #packet_length = int(packet_length, 16) 
     417                 
     418                 
     419                #if ((packet_length <= 169) and \ 
     420                         #(packet_length + 4) == (len(packet))): 
     421                         
     422                        #if self.DEBUG > 2: 
     423                                #print "packet length correct" 
     424                         
     425                        #valid_length = True 
     426                 
     427                #else: 
     428                        #if self.DEBUG: 
     429                                #print "ERROR: packet length bad" 
     430                                #print "packet_length:", 
     431                                #print packet_length 
     432                                #print "len(packet)+4:", 
     433                                #print (len(packet) + 4) 
     434                 
     435                #if valid_length: 
     436                         
     437                        #data_payload = packet[3:-1] 
     438                         
     439                        ## SPEC: The [CHKSUM] Byte must be used to verify the integrity of the 
     440                        ## Packet's Data Payload. The Payload's Checksum is defined as: 
     441                        ##  1. summing all the bytes of the Packet's Data Payload 
     442                        ##  2. taking the lowest 8 bits of the sum 
     443                        ##  3. performing the bit inverse (one's compliment inverse) 
     444                        ##     on those lowest 8 bits 
     445                         
     446                        #packet_checksum = packet[-1] 
     447                        #packet_checksum = packet_checksum.encode("hex") 
     448                        #packet_checksum = int(packet_checksum, 16) 
     449                         
     450                        #payload_checksum = 0 
     451                        #for byte in data_payload: 
     452                                #value = byte.encode("hex") 
     453                                #value = int(value, 16) 
     454                                #payload_checksum += value 
     455                         
     456                        ## Take the lowest 8 bits of the calculated payload_checksum 
     457                        ## and invert them. Serious C code mojo. 
     458                        #payload_checksum &= 0xff 
     459                        #payload_checksum = ~payload_checksum & 0xff 
     460                         
     461                         
     462                        #if packet_checksum != payload_checksum: 
     463                                #if self.DEBUG > 1: 
     464                                        #print "ERROR: packet checksum does not match" 
     465                                        #print "       packet_checksum:", 
     466                                        #print packet_checksum 
     467                                        #print "       payload_checksum:", 
     468                                        #print payload_checksum 
     469                         
     470                        #else: 
     471                                #valid_checksum = True 
     472                                #if self.DEBUG > 2: 
     473                                        #print "packet checksum correct" 
    540474                                         
    541                                 self.process_data_payload(data_payload) 
    542                  
    543                  
    544                 return(valid_length, valid_checksum) 
    545          
    546          
    547         ################################################################## 
    548          
    549         def process_byte(self, byte): 
    550                  
    551                 self.buffer += byte 
    552                 self.byte_count += 1 
    553                  
    554                 if (len(self.buffer) > 2): 
    555                         if self.buffer[-2:] == '\xAA\xAA': 
    556                                 # New packet header found 
     475                                #self.process_data_payload(data_payload) 
     476                 
     477                 
     478                #return(valid_length, valid_checksum) 
     479         
     480         
     481        ################################################################## 
     482         
     483        #def process_byte(self, byte): 
     484                 
     485                #self.buffer += byte 
     486                #self.byte_count += 1 
     487                 
     488                #if (len(self.buffer) > 2): 
     489                        #if self.buffer[-2:] == '\xAA\xAA': 
     490                                ## New packet header found 
    557491                                 
    558                                 (valid_length, valid_checksum) = self.process_packet(self.buffer[:-2]) 
     492                                #(valid_length, valid_checksum) = self.process_packet(self.buffer[:-2]) 
    559493                                 
    560                                 if ((valid_length) or \ 
    561                                          (len(self.buffer) > 173)): 
    562                                         # If processing the packet returned valid checks then we 
    563                                         # restart reading the buffer to examine new packages. 
    564                                         # However if the current buffer size is larger than 173 bytes 
    565                                         # (the maximum possible packet length according to the protocol 
    566                                         # specification document, then we still want to reset the buffer 
    567                                         # because an error has occured in the stream) 
    568                                         self.buffer = '\xAA\xAA' 
    569                                         self.packet_count += 1 
    570                  
    571                  
    572                 elif self.buffer == "AT+BRSF=24\r": 
    573                         # This string is received when connecting to the wrong  
    574                         # Bluetooth serial device channel of the ThinkGear device 
    575                         if self.DEBUG: 
    576                                 print "--> Received:", 
    577                                 print self.buffer 
    578                         response = '\r\nOK\r\n' 
    579                         if self.DEBUG: 
    580                                 print "<-- Sending:", 
    581                                 print response.replace('\r\n', '') 
    582                         self.device.write(response) 
    583                         self.buffer = '' 
    584                          
    585                         if self.DEBUG: 
    586                                 print "ERROR: Serial device connected to wrong channel" 
    587                                 print "(Consider changing from channel 1 to channel 3", 
    588                                 print " or another COM port for example)" 
    589                          
    590                         self.device.close() 
    591                         sys.exit() 
    592                  
    593                  
    594                 if ((self.DEBUG > 3) and \ 
    595                          ((self.byte_count >= DEBUG_BYTE_COUNT) or \ 
    596                           (self.packet_count >= DEBUG_PACKET_COUNT))): 
    597                         if self.DEBUG: 
    598                                 print "max debugging count reached, disconnecting" 
    599                         self.device.close() 
    600                         sys.exit() 
     494                                #if ((valid_length) or \ 
     495                                         #(len(self.buffer) > 173)): 
     496                                        ## If processing the packet returned valid checks then we 
     497                                        ## restart reading the buffer to examine new packages. 
     498                                        ## However if the current buffer size is larger than 173 bytes 
     499                                        ## (the maximum possible packet length according to the protocol 
     500                                        ## specification document, then we still want to reset the buffer 
     501                                        ## because an error has occured in the stream) 
     502                                        #self.buffer = '\xAA\xAA' 
     503                                        #self.packet_count += 1 
     504                 
     505                 
     506                #elif self.buffer == "AT+BRSF=24\r": 
     507                        ## This string is received when connecting to the wrong  
     508                        ## Bluetooth serial device channel of the ThinkGear device 
     509                        #if self.DEBUG: 
     510                                #print "--> Received:", 
     511                                #print self.buffer 
     512                        #response = '\r\nOK\r\n' 
     513                        #if self.DEBUG: 
     514                                #print "<-- Sending:", 
     515                                #print response.replace('\r\n', '') 
     516                        #self.device.write(response) 
     517                        #self.buffer = '' 
     518                         
     519                        #if self.DEBUG: 
     520                                #print "ERROR: Serial device connected to wrong channel" 
     521                                #print "(Consider changing from channel 1 to channel 3", 
     522                                #print " or another COM port for example)" 
     523                         
     524                        #self.device.close() 
     525                        #sys.exit() 
     526                 
     527                 
     528                #if ((self.DEBUG > 3) and \ 
     529                         #((self.byte_count >= DEBUG_BYTE_COUNT) or \ 
     530                          #(self.packet_count >= DEBUG_PACKET_COUNT))): 
     531                        #if self.DEBUG: 
     532                                #print "max debugging count reached, disconnecting" 
     533                        #self.device.close() 
     534                        #sys.exit() 
    601535         
    602536         
     
    699633                                        print "       payload_checksum:", 
    700634                                        print payload_checksum 
     635                                         
     636                                        #self.device.check_buffer() 
    701637                                 
    702638                                continue 
     
    747683                 
    748684                self.device = self.initialize_device() 
     685                 
     686                self.buffer_check_timer = QtCore.QTimer() 
     687                QtCore.QObject.connect(self.buffer_check_timer, \ 
     688                                       QtCore.SIGNAL("timeout()"), \ 
     689                                       self.check_buffer) 
     690                self.buffer_check_timer.start(DEVICE_BUFFER_CHECK_TIMER) 
    749691         
    750692         
     
    826768        ################################################################## 
    827769         
     770        def check_buffer(self): 
     771                 
     772                if self.DEBUG > 1: 
     773                        print "INFO: Buffer size check:", 
     774                        print len(self.buffer), 
     775                        print "(maximum before reset is %i)" % DEVICE_BUFFER_MAX_SIZE 
     776                 
     777                if (DEVICE_BUFFER_MAX_SIZE <= len(self.buffer)): 
     778                         
     779                        if self.DEBUG: 
     780                                print "ERROR: Buffer size has grown too large, resetting" 
     781                         
     782                        self.reset() 
     783         
     784         
     785        ################################################################## 
     786         
     787        def reset(self): 
     788                 
     789                self.buffer = '' 
     790         
     791         
     792        ################################################################## 
     793         
    828794        def read(self, length=1): 
    829795                 
     
    903869                                                            DEBUG=DEBUG) 
    904870         
    905         #server.parse_stream() 
    906871        protocol.start() 
    907872         
     
    909874         
    910875         
    911          
Note: See TracChangeset for help on using the changeset viewer.