使用Python解包数据结构

时间:2014-10-18 16:08:32

标签: python tcp struct

我通过TCP套接字从设备接收一些数据。我有结构的规格,但不知道如何使用它来打开它。我假设这意味着为struct.unpack函数编写格式化字符串,但考虑到制造商的规格,我无法确定这一点。这些32位片段中的每一个都是" DWORD",但我不确定如何解释它,并拉出相关位:

  

状态标头是混合数据类型的22x32位(88字节)结构,位于前面并提供有关正在传输的数据的信息。下表显示了该结构的相关成员。阴影成员字段保留用于将来扩展,内部用于仪器监视和控制,或者尚未实现。

Imgur Imgur

以下是两个示例结构:

b'\x08\x04i!\x13\x02\x00\x1f\x00\x00\x80\x0c\x01\x00p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x84\x9e\x00\x00\x85\x9e\x01\x00:B\x04\x00\x08\xf4DT\x01\x00k\x01\xdc\x8c\x00\x00c\x03X\x00\x9eR\xa4QTV\xf0U\xd0\x83\xd0\x83\xd0\x83\xd0\x83\x01\x00\x00\x00@B\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

b'\x08Ti!\x1a\x02\x00\x1f\x00\x00x\x0c\x01\x00p\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x91\x00\x00\xd5\x91\x01\x00`y\x00\x00\x05\xf4DT\x01\x00\xbb\x00\xdb\x8c\x00\x00c\x03X\x00\x9eR\xa4QTV\xf0U\xd0\x83\xd0\x83\xd0\x83\xd0\x83\x01\x00\x00\x00@B\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

1 个答案:

答案 0 :(得分:2)

这应该让你开始。使用struct.unpack解压缩接收的字节,然后对由少于1个字节的数据表示的字段进行一些解析。

from struct import unpack

# data recieved, 88 random bytes for example purpose
data = b'\xdb[\x91wdI\t\xef\xc6c\xde\x14\xac\x1e\x08\x10.f\xc0\xbd\xfd\xa15\x8cP\x101\xed\xc5\xd9\x98X\xb5\xc2\x00Z\xd2\xb9\xb0Xa\x04\xfa\xb8\xceA\x94_7\xc7\xde\t\xf2kX\x9d2\xc3\x84\xb3\x19\x8e\xf5\x99\xc3\xba\x08\xaa0$\x17\xfbd\xbb\x7f\xfd&\xf5\x1aU\t`\x11@zD\xce\xff'

# unpack the struct into variables
(
    abcde, fw_ver, cur_layer, fs_radix,  # 0 needs parse
    fghij, knpl, fbg_thermistor,  # 1 needs parse
    tx_ambient_temp, reserved2,  # 2
    num_ffpi_peaks, num_fbg_peaks,  # 3
    num_dut2_peaks, num_dut1_peaks,  # 4
    num_dut4_peaks, num_dut3_peaks,  # 5
    reserved7, qr, acq_counter3,  # 6 needs parse
    serial_number,  # 7
    kernel_timestamp_microseconds,  # 8
    kernel_timestamp_seconds,  # 9
    kernel_src_buffer, kernel_buffers,  # 10
    error_and_kernel_rt_loc0,  # 11 needs parse
    header_length, header_ver, buffers,  # 12
    dut2_gain, dut1_gain,  # 13
    dut4_gain, dut3_gain,  # 14
    dut2_noise_thresh, dut1_noise_thresh,  # 15
    dut4_noise_thresh, dut3_noise_thresh,  # 16
    hw_clk_div, peak_data_rate_div,  # 17
    granularity,  # 18
    reserved4,  # 19
    starting_lambda,  # 20
    ending_lambda  # 21
) = unpack(
    '>'  # big endian
    'BBBB'  # 0 needs parse
    'BBH'  # 1 needs parse
    'HH'  # 2
    'HH'  # 3
    'HH'  # 4
    'HH'  # 5
    'BBH'  # 6 needs parse
    'I'  # 7
    'I'  # 8
    'I'  # 9
    'HH'  # 10
    'I'  # 11 needs parse
    'HBB'  # 12
    'HH'  # 13
    'HH'  # 14
    'HH'  # 15
    'HH'  # 16
    'HH'  # 17
    'I'  # 18
    'I'  # 19
    'I'  # 20
    'I',  # 21
    data
)

# 0 parse abcde
acq_triggered = bool(abcde & 0x80)
calibration_fault = bool(abcde & 0x40)
start_of_frame = bool(abcde & 0x20)
primary_fan_state = bool(abcde & 0x10)
secondary_fan_state = bool(abcde & 0x08)
s0_mux_state = bool(abcde & 0x04)
s1_mux_state = bool(abcde & 0x02)
s2_mux_state = bool(abcde & 0x01)

# 1 parse fghij
xfer_type = fghij >> 4
soa_therm_limit = bool(fghij & 0x08)
soa_current_limit = bool(fghij & 0x04)
tec_over_temp = bool(fghij & 0x02)
tec_under_temp = bool(fghij & 0x01)

# 1 parse knpl
operating_mode = knpl >> 6
triggering_mode = (knpl & 0x30) >> 4
sm041_mux_level = (knpl & 0x0c) >> 2
sw_position = knpl & 0x03

# 6 parse qr
nrz_command = qr >> 5
reserved6 = qr & 0x1f

# 11 parse
error = error_and_kernel_rt_loc0 >> 24
kernel_rt_loc0 = error_and_kernel_rt_loc0 & 0xffffff

我假设大端,因为这是通过TCP来的,但这可能是错误的。如果所有数据都已关闭,请尝试使用<作为小端。或者,如果你运气不好,某些值可能是一个,而另一些则是另一个,在这种情况下,你必须将它拆分为多个解包。你还必须进一步处理这些值,因为我相信它们中的一些不应被解释为整数。


解压缩格式可以缩短为

(all, those, variables) = unpack('>6B9H2BH3I2HIH2B10H4I', data)

但我不认为这很清楚。