Ignore:
Timestamp:
07/22/10 15:49:51 (11 years ago)
Author:
sc
Message:

thinkgear_emulator/puzzlebox_thinkgear_serial_protocol.py:

  • packet structure properly parsed and checksum'd
File:
1 edited

Legend:

Unmodified
Added
Removed
  • thinkgear_emulator/puzzlebox_thinkgear_serial_protocol.py

    r120 r121  
    1212# 
    1313##################################################################### 
     14# Example: 
     15#    rfcomm connect rfcomm0 00:13:EF:00:1B:FE 3 
     16##################################################################### 
    1417 
    1518import sys 
     
    2730DEBUG = 2 
    2831 
    29 DEFAULT_SERIAL_PORT_WINDOWS = 'COM6' 
     32DEFAULT_SERIAL_PORT_WINDOWS = 'COM2' 
    3033DEFAULT_SERIAL_PORT_LINUX = '/dev/rfcomm0' 
    3134 
     
    5558                self.serial_port = serial_port 
    5659                self.device = None 
     60                self.buffer = '' 
    5761                 
    5862                self.device = self.initialize_device() 
     
    136140        ################################################################## 
    137141         
    138         def start(self): 
     142        def communicate_with_handsfree_profile(self): 
    139143                 
    140144                #"AT+CKPD=200" - Indicates a Bluetooth button press 
     
    232236                                self.device.close() 
    233237                                sys.exit() 
     238         
     239         
     240        ################################################################## 
     241         
     242        def process_data_payload(self, data_payload): 
     243                 
     244                pass 
     245         
     246         
     247        ################################################################## 
     248         
     249        def process_packet(self, packet): 
     250                 
     251                valid_length = False 
     252                valid_checksum = False 
     253                 
     254                if self.DEBUG > 1: 
     255                        print packet 
     256                 
     257                 
     258                # SPEC: [PLENGTH] byte indicates the length, in bytes, of the  
     259                # Packet's Data Payload [PAYLOAD...] section, and may be any value  
     260                # from 0 up to 169. Any higher value indicates an error  
     261                # (PLENGTH TOO LARGE). Be sure to note that [PLENGTH] is the length  
     262                # of the Packet's Data Payload, NOT of the entire Packet.  
     263                # The Packet's complete length will always be [PLENGTH] + 4. 
     264 
     265                packet_length = packet[2] 
     266                packet_length = packet_length.encode("hex") 
     267                packet_length = int(packet_length, 16) 
     268                 
     269                if ((packet_length <= 169) and \ 
     270                         (packet_length + 4) == (len(packet))): 
     271                        if self.DEBUG > 1: 
     272                                print "packet length correct" 
     273                        valid_length = True 
     274                else: 
     275                        if self.DEBUG: 
     276                                print "ERROR: packet length bad" 
     277                 
     278                 
     279                if valid_length: 
     280                         
     281                        data_payload = packet[3:-1] 
     282                         
     283                        # SPEC: The [CHKSUM] Byte must be used to verify the integrity of the 
     284                        # Packet's Data Payload. The Payload's Checksum is defined as: 
     285                        #  1. summing all the bytes of the Packet's Data Payload 
     286                        #  2. taking the lowest 8 bits of the sum 
     287                        #  3. performing the bit inverse (one's compliment inverse) 
     288                        #     on those lowest 8 bits 
     289                         
     290                        packet_checksum = packet[-1] 
     291                        packet_checksum = packet_checksum.encode("hex") 
     292                        packet_checksum = int(packet_checksum, 16) 
     293                         
     294                        payload_checksum = 0 
     295                        for byte in data_payload: 
     296                                value = byte.encode("hex") 
     297                                value = int(value, 16) 
     298                                payload_checksum += value 
     299                         
     300                        # Take the lowest 8 bits of the calculated payload_checksum 
     301                        # and invert them. Serious C code mojo. 
     302                        payload_checksum &= 0xff 
     303                        payload_checksum = ~payload_checksum & 0xff 
     304                         
     305                         
     306                        if packet_checksum != payload_checksum: 
     307                                if self.DEBUG > 1: 
     308                                        print "ERROR: packet checksum does not match" 
     309                                        print "       packet_checksum:", 
     310                                        print packet_checksum 
     311                                        print "       payload_checksum:", 
     312                                        print payload_checksum 
     313                        else: 
     314                                valid_checksum = True 
     315                                if self.DEBUG > 1: 
     316                                        print "packet checksum correct" 
     317                                         
     318                                self.process_data_payload(data_payload) 
     319                 
     320                 
     321                return(valid_length, valid_checksum) 
     322         
     323         
     324        ################################################################## 
     325         
     326        def process_byte(self, byte): 
     327                 
     328                self.buffer += byte 
     329                self.byte_count += 1 
     330                 
     331                if (len(self.buffer) > 2): 
     332                        if self.buffer[-2:] == '\xAA\xAA': 
     333                                # New packet header found 
     334                                 
     335                                (valid_length, valid_checksum) = self.process_packet(self.buffer[:-2]) 
     336                                 
     337                                if ((valid_length) or \ 
     338                                         (len(self.buffer) > 173)): 
     339                                        # If processing the packet returned valid checks then we 
     340                                        # restart reading the buffer to examine new packages. 
     341                                        # However if the current buffer size is larger than 173 bytes 
     342                                        # (the maximum possible packet length according to the protocol 
     343                                        # specification document, then we still want to reset the buffer 
     344                                        # because an error has occured in the stream) 
     345                                        self.buffer = '\xAA\xAA' 
     346                                        self.packet_count += 1 
     347                 
     348                 
     349                elif self.buffer == "AT+BRSF=24\r": 
     350                        # This string is received when connecting to the wrong  
     351                        # Bluetooth serial device channel of the ThinkGear device 
     352                        if self.DEBUG: 
     353                                print "--> Received:", 
     354                                print self.buffer 
     355                        response = '\r\nOK\r\n' 
     356                        if self.DEBUG: 
     357                                print "<-- Sending:", 
     358                                print response.replace('\r\n', '') 
     359                        self.device.write(response) 
     360                        self.buffer = '' 
     361                         
     362                        if self.DEBUG: 
     363                                print "ERROR: Serial device connected to wrong channel" 
     364                                print "(Consider changing from channel 1 to channel 3", 
     365                                print " or another COM port for example)" 
     366                         
     367                        self.device.close() 
     368                        sys.exit() 
     369                 
     370                 
     371                if ((self.DEBUG > 1) and \ 
     372                         ((self.byte_count >= 8192) or \ 
     373                          (self.packet_count >= 10))): 
     374                        if self.DEBUG: 
     375                                print "max debugging count reached, disconnecting" 
     376                        self.device.close() 
     377                        sys.exit() 
     378         
     379         
     380        ################################################################## 
     381         
     382        def start(self): 
     383                 
     384                self.buffer = '' 
     385                self.packet_count = 0 
     386                self.byte_count = 0 
     387                 
     388                while True: 
     389                         
     390                        byte = self.device.read() 
     391                         
     392                        if (len(byte) != 0): 
     393                                if DEBUG > 2: 
     394                                        print byte 
     395                                         
     396                                self.process_byte(byte) 
    234397 
    235398 
Note: See TracChangeset for help on using the changeset viewer.