Search code examples
pythonarrayshexchecksumpacket

Convert byte array to string with a checksum. Getting additional null bytes on re-iteration in python


Ok here's my question. Actually two.

I am getting additional null bytes when running my code after the first pass, what am I doing wrong?

2nd question, how do I form the packet from the byte array and with the added checksum?

I have a bytearray that I need to do an XOR on to get a checksum value. The starting checksum has to be 5A before the XOR. This needs to be appended to the end of the array and sent to my external device.

I 'THINK' I am doing this right, but I am not getting a response from the device. I have checked the device and it is working correctly, so I am assuming it is my code.

So with that I have put up the code below. Any help forming the packet to send out would be very helpful as I have been knocking my head against the wall. I am not a very experienced python programmer but I can usually figure things out when they are explained or examples given.

import struct
import sys
import string
import select
import time
from socket import *
import binascii


port = 8010
# region Read Codes
getBoardTemp = [0x02, 0x53, 0x00, 0x00]
#Communication utilities

class CommUtilities:
    def unhex(self, inp):
        return binascii.unhexlify(inp)

    def hexit(self, inp):
        return binascii.a2b_hex(inp)

    def calculateChecksum(self, buf):
        checksum = 0x5A #Starting checksum
        #For each byte, bitwise XOR it with our checksum
        for b in buf:
            checksum ^= b
        print 'Checksum: {}'.format(checksum)
        return checksum

    #Append the one byte checksum to a command
    #returns the complete byte array
    def appendChecksum(self, buff):
        buff.append(self.calculateChecksum(buff))
        return buff


def send_server(data, host):
        sock=socket(AF_INET,SOCK_STREAM)
        sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.setblocking(0)
        sock.settimeout(3)
        sock.connect((host, 1000))
        sock.sendall(data)
        print 'Sent Data'
        print 'Waiting for return data'
        result = sock.recv(1024)

        sock.close()
        return result


def main():
    c = CommUtilities()
    host = "172.16.2.52"
    while True:
        try:
            #Connect to server and send data
            print 'Requesting Board Temp'
            data = c.appendChecksum(getBoardTemp)
            """ The checksum should have appended a 0B byte into the array
            """
            data = bytearray(data)
            print data
            print'sending "%s"' % data
            """  The sending "%s" is where I noticed extra nulls being appedned
            on each pass.  They accumulate as the application keeps running.
            """
            received = send_server(data, host)
            """ I have yet to receive any return data, other than the ACK
            packets from the device.  So I am assuming my data I am sending is wrong.
            """
        except Exception, e:
            print >>sys.stderr, 'send/receive error {}'.format(e)
            received = e
        finally:
            print "received: {}".format(received)

        time.sleep(2)

if __name__ == '__main__':
    main()

I thank you in advance for you help!


Solution

  • The problem is CommUtilities.appendChecksum() modifies the contents of its buff argument (and after the first iteration, the checksum it calculates is zero). You can fix that with by simply making a copy first:

        def appendChecksum(self, buff):
            buff = buff[:]  # make copy
            buff.append(self.calculateChecksum(buff))
            return buff
    

    I'm not sure, but that may also answer your second question.