简体   繁体   English

Python解析固定格式的串行十六进制字符串

[英]Python parsing serial hex string with fixed format

I am successfully communicating with a simple device over serial, with a specific request packet, and a fixed format return packet is received. 我已通过一个特定的请求数据包通过串行与一个简单的设备成功通信,并且收到了固定格式的返回数据包。 Im starting with python so I can use this on multiple devices, I'm only really used to PHP/C. 我从python开始,所以我可以在多种设备上使用它,我只真正习惯了PHP / C。

For example, I send the following as hex: 例如,我将以下内容发送为十六进制:

12 05 0b 03 1f

and in return I get 作为回报,我得到

12 05 0b 03 1f 12 1D A0 03 18 00 22 00 00 CA D4 4F 00 00 22 D6 99 18 00 70 80 00 80 00 06 06 00 00 D9

I know how the packet is constructed, the first 5 bytes is the data that was sent. 我知道数据包是如何构造的,前5个字节是发送的数据。 The next 3 bytes are an ID, the packet length, and a response code. 接下来的3个字节是ID,数据包长度和响应代码。 Its commented in my code here: 它在我的代码中在这里评论:

import serial, time

ser = serial.Serial(port='COM1', baudrate=9600, timeout=0, parity=serial.PARITY_EVEN,      stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)

while True:
    # Send The Request - 0x12 0x05 0x0B 0x03 0x1F
    ser.write("\x12\x05\x0B\x03\x1F")
    # Clear first 5 bytes (Original Request is Returned)    
    ser.read(5)

    # Response Header (3 bytes)
    # - ID (Always 12)
    # - Packet Length (inc these three)
    # - General Response (a0 = Success, a1 = Busy, ff = Bad Command)
    ResponseHeader = ser.read(3).encode('hex')
    PacketLength = int(ResponseHeader[2:4],16)
    if ResponseHeader[4:6] == "a0":
        # Response Success
        ResponseData = ser.read(PacketLength).encode('hex')
        # Read First Two Bytes        
        Data1 = int(ResponseData[0:4],16)
        print Data1
    else:
        # Clear The Buffer
        RemainingBuffer = ser.inWaiting()
        ser.read(RemainingBuffer)

time.sleep(0.12)

To keep it simple for now, I was just trying to read the first two bytes of the actual response (ResponseData), which should give me the hex 0318. I then want to output that as a decimal =792. 为了简单起见,我只是尝试读取实际响应的前两个字节(ResponseData),应该给我十六进制的0318。然后,我想将其输出为十进制= 792。 The program is meant to run in a continuous loop. 该程序应在连续循环中运行。

Some of the variables in the packet are one byte, some are two bytes. 数据包中的某些变量是一个字节,有些是两个字节。 Although, up to now I'm just getting an error: 尽管到目前为止,我只是遇到一个错误:

ValueError: invalid literal for int() with base 16: ''

I'm guessing this is due to the format of the data/variables I have set, so not sure if I'm even going about this the right way. 我猜这是由于我设置的数据/变量的格式,所以不确定我是否正在以正确的方式进行操作。 I just want to read the returned HEX data in byte form and be able to access them on an individual level, so I can format/output them as required. 我只想读取字节形式的返回HEX数据,并能够在单个级别上访问它们,因此我可以根据需要格式化/输出它们。

Is there a better way to do this? 有一个更好的方法吗? Many thanks. 非常感谢。

我建议使用struct模块读取二进制数据,而不是使用字符串函数将其重新编码为十六进制并尝试解析十六进制字符串。

As your code stands now, you send binary (not hex) data over the wire, and receive binary (not hex) data back from the device. 就像现在的代码一样,您通过网络发送二进制(非十六进制)数据,并从设备接收回二进制(非十六进制)数据。 Then you convert the binary data to hex, only to convert it again to Python variables. 然后,您将二进制数据转换为十六进制,仅将其再次转换为Python变量。

Let's skip the extra conversion step by using struct.unpack : 让我们通过使用struct.unpack跳过额外的转换步骤:

# UNTESTED
import struct
...
while True:
    # Send The Request - 0x12 0x05 0x0B 0x03 0x1F
    ser.write("\x12\x05\x0B\x03\x1F")
    # Clear first 5 bytes (Original Request is Returned)    
    ser.read(5)

    # Response Header (3 bytes)
    # - ID (Always 12)
    # - Packet Length (inc these three)
    # - General Response (a0 = Success, a1 = Busy, ff = Bad Command)
    ResponseHeader = ser.read(3)
    ID,PacketLength,Response = struct.unpack("!BBB", ResponseHeader)
    if Response == 0xa0:
        # Response Success
        ResponseData = ser.read(PacketLength)
        # Read First Two Bytes        
        Data1 = struct.unpack("!H", ResponseData[0:2])
        print Data1
    else:
        # Clear The Buffer
        RemainingBuffer = ser.inWaiting()
        ser.read(RemainingBuffer)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM