Question

I am trying to use bitstring for python to interpret an incoming data packet and break it up into readable sections. the packet will consist of a header( Source (8bits), Destination (8bits), NS(3bits), NR(3bits), RSV(1bit), LST(1bit), OPcode(8bits), LEN(8bits) ), the Payload which is somewhere between 0 and 128 bytes (determined by the LEN in the header) and a CRC of 16bits.

The data will be arriving in a large packet over the com port. The data is originated from a micro controller that is packetizing the data and sending it to the user, which is where the python comes in to play.

Since i am unsure of how to store it before parsing I do not have any code for this.

I am new to python and need a little help getting this off the ground.

Thanks, Erik

EDIT

I currently have a section of code up and running, but it is not producing exactly what i need.... Here is the section of code that i have up and running....

def packet_make(ser):
    src = 10
    p = 0
    lst = 0
    payload_make = 0
    crc = '0x0031'
    ns = 0
    nr = 0
    rsv = 0
    packet_timeout = 0

    top = 256
    topm = 255

    #os.system(['clear','cls'][os.name == 'nt'])
    print("\tBatts:   1 \t| Berry:   2 \t| Bessler: 3")
    print("\tCordell: 4 \t| Dave:    5 \t| Gold:    6")
    print("\tYen:     7   \t| Erik:    8 \t| Tommy:   9")
    print("\tParsons: 10 \t| JP:     11 \t| Sucess: 12")
    dst = raw_input("Please select a destination Adderss: ")

    message = raw_input("Please type a message: ")



    #################### Start Making packet#################
    p_msg = message
    message = message.encode("hex")
    ln = (len(message)/2)
    #print (ln)
    ln_hex = (ln * 2)
    message = list(message)
    num_of_packets = ((ln/128) + 1)
    #print (num_of_packets)

    message = "".join(message)

    src = hex(src)
    dst = hex(int(dst))
    #print (message)

    print("\n########Number of packets = "+str(num_of_packets) + " ############\n\n")

    for p in range (num_of_packets):
        Ack_rx = 0


        if( (p + 1) == (num_of_packets)):
            lst = 1
        else:
            lst = 0

        header_info = 0b00000000

        if ((p % 2) > 0):
            ns = 1
        else:
            ns = 0  


        header_info = (header_info | (ns << 5)) 
        header_info = (header_info | (nr << 2))
        header_info = (header_info | (rsv << 1))
        header_info = (header_info | (lst))
        header_info = hex(header_info)
        #print (header_info)
        op_code = '0x44'

        if (lst == 1):
            ln_packet = ((ln_hex - (p * 256)) % 256)
            if (p > 0):
                ln_packet = (ln_packet + 2)
            else:
                ln_packet = ln_packet
            ln_packet = (ln_packet / 2)
        #   print (ln_packet)
        #   print()
        else:
            ln_packet = 128
        #   print(ln_packet)
        #   print()

        #ll = (p * 128)
        #print(ll)
        #ul = ((ln - ll) % 128)
        #print(ul)
        #print (message[ll:ul])

        if ((p == 0)&(ln_hex > 256)):
            ll = (p * 255)
        #   print(ll)
            payload_make = (message[ll:256])
        #   print (payload_make)
        elif ((p > 0) & ((ln_hex - (p*256)) > 256)):
            ll = (p * 256)
        #   print(ll)
            ll = (ll - 2)
            ul = (ll + 256)
        #   print (ul)

            payload_make = (message[ll:ul])
        #   print(payload_make)
        elif ((p > 0) & ((ln_hex - (p*256)) < 257)):
            ll = (p * 256)
        #   print(ll)
            ll = (ll - 2)
            ul = ((ln_hex - ll) % 256)

            ul = (ll + (ul))
            ul = ul + 2
            print()
            print(ul)
            print(ln_hex)
            print(ln_packet)
            print()
        #   print(ul)
            payload_make = (message[ll:ul])
        #   print(payload)
        elif ((p == 0) & (ln_hex < 257)):
            ll = (p * 255)
            ul = ln_hex
            payload_make = (message[ll:ul])

        print(payload_make)

        packet_m = BitStream()  
########################HEADER#########################
        packet_m.append('0x0')
        packet_m.append(src)                        #src
        packet_m.append('0x0')  
        packet_m.append(dst)                        #dst
        if(int(header_info,16) < 16):
            packet_m.append('0x0')
        packet_m.append(header_info)                # Ns, Nr, RSV, Lst
        packet_m.append(op_code)                    #op Code
        #if(ln_packet < 16):
            #packet_m.append('0x0')
        packet_m.append((hex(ln_packet)))           #Length
###################END OF HEADER#######################     
        packet_m.append(("0x"+payload_make))    #Payload
        #packet_m.append(BitArray(p_msg))   #Payload
        packet_m.append(crc)                    #CRC    
        #print()
        #print(packet)
        temp_ack = '0x00'
        print(packet_m)
        print(ln_packet)
        while((Ack_rx == 0) & (packet_timeout <= 5)):
            try: 
                ###### Send the packet
                #ser.write(chr(0x31))

                str_pack = list(str(packet_m)[2:])
                "".join(str_pack)

                ser.write(chr(0x02))
                #ser.write((str(packet_m)[2:]))
                for i in range (len(str_pack)):
                    t = ord(str_pack[i])
                    ser.write(chr(t))
                    print(chr(t))


                ser.write(chr(0x04))
                ser.write(chr(0x10))

                ack_packet = BitStream(ser.read())
                if((len(ack_packet) > 3)):
                    temp_ack = ACK_parse(ack_packet)
                else:
                    packet_timeout = (packet_timeout + 1)
                    print "why so serious\n\n"
                if(temp_ack == '0x41'):
                    Ack_rx = 1
                elif (temp_ack == '0x4E'):
                    Ack_rx = 0
                else:
                    Acl_rx = 0 

            except serial.SerialTimeoutException: #if timeout occurs increment counter and resend last packet
                Ack_rx = 0
                packet_timeout = (packet_timeout + 1)


            except serial.SerialException:
                print "Error ... is not Active!!!", port

The output that is printed to the terminal is as follows when source and payload are both 1:

#######Number of packets = 1 #######

31
0x0a0101441310031
1
0
.... etc..

The micro on the other end of the serial reads : 0a0101441310031 when it should read a 1 1 44 1 31 0031

Python is sending each value as a separate character rather than putting it as one char. when it was appended into the packet rather than storing into the proper length and data type it seems to have separated the hex into 2 8 bit locations rather than 1 8 bit location....

The section of python code where i am reading from the Micro works flawlessly when reading an acknowledgement packet. I have not tried it with data, but i don't think that will be an issue. The C side can not read the ACK from the python side since it is separating the hex values into 2 char rather than transmitting just the 8 bit value....

Any ideas??? Thanks

Was it helpful?

Solution

Your exact problem is a bit vague, but I should be able to help with the bitstring portion of it.

You've probably got your payload to analyse as a str (or possibly bytes if you're using Python 3 but don't worry - it works the same way). If you haven't got that far then you're going to have to ask a more basic question. I'm going to make up some data to analyse (all this is being done with an interactive Python session):

>>> from bitstring import BitStream
>>> packet_data = '(2\x06D\x03\x124V\x03\xe8'
>>> b = BitStream(bytes=packet_data)

Now you can unpack or use reads on your BitStream to extract the things you need. For example:

>>> b.read('uint:8')
40
>>> b.read('uint:8')
50
>>> b.readlist('uint:3, uint:3')
[0, 1]
>>> b.readlist('2*bool')
[True, False]
>>> b.readlist('2*uint:8')
[68, 3]
>>> b.read('bytes:3')
'\x124V'

This is just parsing the bytes and interpreting chunks as unsigned integers, bools or bytes. Take a look at the manual for more details.

If you just want the payload, then you can just extract the length then grab it by slicing:

>>> length = b[32:40].uint
>>> b[40:40 + length*8]
BitStream('0x123456')

and if you want it back as a Python str, then use the bytes interpretation:

>>> b[40:40 + 3*8].bytes
'\x124V'

There are more advance things you can do too, but a good way to get going in Python is often to open an interactive session and try some things out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top