BitString с питоном - PullRequest
       54

BitString с питоном

1 голос
/ 30 марта 2012

Я пытаюсь использовать цепочку битов для python, чтобы интерпретировать входящий пакет данных и разбить его на читаемые разделы. пакет будет состоять из заголовка (источник (8 бит), пункт назначения (8 бит), NS (3 бита), NR (3 бита), RSV (1 бит), LST (1 бит), OPcode (8 бит), LEN (8 бит)), Полезная нагрузка, которая находится где-то между 0 и 128 байтами (определяется LEN в заголовке) и CRC 16 бит.

Данные будут поступать в виде большого пакета через COM-порт. Данные поступают из микроконтроллера, который упаковывает данные и отправляет их пользователю, где питон начинает играть.

Так как я не уверен, как сохранить его перед разбором, у меня нет кода для этого.

Я новичок в python и мне нужна небольшая помощь, чтобы справиться с этим.

Спасибо, Erik

EDIT

В настоящее время у меня есть часть кода, которая работает и работает, но она не производит именно то, что мне нужно ... Вот часть кода, которая у меня есть и работает ....

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

Вывод, который выводится на терминал, следующий, когда источник и полезная нагрузка равны 1:

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

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

Микро на другом конце сериала гласит: 0a0101441310031 когда следует читать 1 1 44 1 31 0031

Python отправляет каждое значение как отдельный символ, а не как один символ. когда он был добавлен в пакет, а не сохранен в правильной длине и типе данных, он, по-видимому, разделил шестнадцатеричный код на 2 8-битные местоположения, а не на 1 8-битное местоположение ....

Раздел кода Python, где я читаю из Micro, работает безупречно при чтении пакета подтверждения. Я не пробовал это с данными, но я не думаю, что это будет проблемой. Сторона C не может прочитать ACK со стороны Python, поскольку она разделяет шестнадцатеричные значения на 2 символа вместо передачи только 8-битного значения ....

Есть идеи ??? Спасибо

1 Ответ

6 голосов
/ 30 марта 2012

Ваша точная проблема немного расплывчата, но я должен быть в состоянии помочь с ее частью.

Вы, вероятно, получили свой полезный груз для анализа как str (или, возможно, bytes, если вы используете Python 3, но не волнуйтесь - он работает так же). Если у вас не так далеко, вам придется задать более простой вопрос. Я собираюсь подготовить некоторые данные для анализа (все это делается с помощью интерактивного сеанса Python):

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

Теперь вы можете распаковать или использовать чтение на вашем BitStream, чтобы извлечь то, что вам нужно. Например:

>>> 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'

Это просто синтаксический анализ байтов и интерпретация кусков как целых чисел без знака, bools или байтов. Посмотрите руководство для более подробной информации.

Если вы просто хотите получить полезную нагрузку, вы можете просто извлечь длину, а затем взять ее, нарезав:

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

и если вы хотите вернуть его как строку Python, используйте интерпретацию байтов:

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

Есть и другие продвинутые вещи, которые вы можете сделать, но хороший способ начать работу с Python - это часто открывать интерактивную сессию и пробовать некоторые вещи.

...