在Python3中使用结构记录解析串行数据

2024-04-20 02:18:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图解析通过串行端口从监视器接收到的数据。我已经成功地用Python编写了一个脚本,将数据作为字节字符串从监视器中检索出来,并按照ISO3309标准进行了必要的数据转换,最后执行了校验和以确保数据的完整性。下面是提取的数据

[198, 2, 40, 4, 0, 0, 131, 35, 158, 94, 0, 0, 0, 0, 0, 0, 0, 0, 1, 22, 1, 1, 44, 2, 4, 189, 189, 255, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 131, 35, 158, 94, 51, 58, 0, 0, 0, 18, 2, 128, 10, 129, 1, 128, 1, 128, 1, 128, 1, 0, 0, 0, 1, 0, 2, 128, 2, 128, 2, 128, 1, 128, 1, 0, 0, 0, 2, 0, 2, 128, 2, 128, 2, 128, 1, 128, 0, 0, 0, 0, 11, 0, 1, 128, 1, 128, 1, 128, 1, 128, 0, 0, 0, 0, 3, 0, 1, 128, 1, 128, 1, 128, 1, 128, 3, 0, 0, 0, 3, 1, 1, 128, 1, 128, 1, 128, 1, 128, 3, 0, 0, 0, 11, 0, 4, 128, 3, 0, 0, 0, 12, 0, 4, 128, 0, 0, 0, 0, 13, 0, 1, 128, 0, 0, 0, 0, 14, 0, 1, 128, 3, 0, 0, 0, 0, 0, 1, 128, 2, 128, 2, 128, 1, 128, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 203, 29, 3, 0, 0, 0, 0, 0, 41, 8, 41, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 1, 128, 0, 0, 0, 0, 11, 0, 1, 128, 1, 128, 1, 128, 1, 128, 32, 0, 0, 0, 0, 0, 1, 128, 1, 128, 255, 141, 2, 128, 1, 128, 1, 128, 0, 0, 0, 0, 173, 1, 1, 128, 0, 0, 0, 0, 13, 0, 1, 128, 1, 128, 1, 128, 1, 128, 0, 0, 0, 0, 14, 0, 1, 128, 1, 128, 1, 128, 1, 128, 0, 0, 0, 0, 65, 0, 131, 35, 158, 94, 0, 0, 0, 0, 18, 2, 1, 128, 1, 128, 1, 128, 1, 128, 3, 0, 0, 0, 0, 0, 1, 128, 1, 128, 4, 128, 1, 128, 1, 128, 1, 128, 73, 13, 0, 0, 176, 192, 0, 0, 226, 1, 0, 0, 198, 2, 0, 0, 240, 127, 170, 1, 0, 0, 0, 0, 9, 49, 28, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 3, 0, 0, 0, 0, 0, 0, 0, 0, 195, 165, 0, 0, 195, 165, 1, 128, 72, 8, 160, 15, 32, 78, 208, 7, 208, 7, 112, 23, 80, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 52, 8, 0, 0, 0, 0, 208, 7, 112, 23, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141]

我有结构记录。请参阅附件 记录可能是用C写的,这没有帮助。但是,我的问题是标题。If,Struct:只是一个具有多种数据类型的自定义变量。标题的结构是否直接对应于我的数据列表中的第一个整数?举个例子:r_len= 198,r_nbr=2,r_时间=0?我是否继续按顺序向下移动列表以获取子记录?如果是,则时间定义为自1970年1月1日起的秒数。那怎么可能是一个整数呢?如果您能提供任何提示,我将不胜感激。谢谢你阅读我的长篇文章。 Structure Record for the dataStructure Record page 2


Tags: 数据端口字符串脚本标题列表标准字节
1条回答
网友
1楼 · 发布于 2024-04-20 02:18:07

嗨,罗伯特,谢谢你给我带来的任务,我刚刚很高兴

该规范明确表示它以字节形式传递数据,由类似C的结构描述。我看不出您是如何读取数据的,但猜测是您在这里得到的正是一个字节列表,因为其中的每个值都小于256

因此,通过查看结构,我可以尝试将其转换为人类可读的形式。这是通过python中的struct模块完成的:

b = bytes(l)
hdr_data = struct.unpack_from('<hBBHLBBHH', b)
print(hdr_data)

解释

这里,我将^ {CD1>}视为字节的初始列表。根据您提供的记录的结构,我为标题构建了格式字符串:

hBBHLBBHH意思是:短、字节、字节、字、双字、字节、字节、字、字

<开头的意思是byte-ordering是小端点

结果打印出来了

(710, 40, 4, 0, 1587422083, 0, 0, 0, 0)

这里第一个值是r_len,等于710。你的列表长度是711,所以我最初对列表格式和尾数的猜测很可能是正确的,最后你意外地得到了一个冗余字节

下一步

虽然我们已经完成了这一行,但我们还没有阅读sru desc,也没有设置合适的名称匹配

让我们将解包行也更改为使用struct sr_desc[8]

hdr_data = struct.unpack_from('<hBBHLBBHH' + 'hB'*8, b)

现在我们将在一个元组中包含所有内容

访问字段的一种非常方便的方法是namedtuple

from collections import namedtuple
D_O_hdr = namedtuple('D_O_hdr',
                     ('r_len', 'r_nbr', 'dri_level', 'plug_id', 
                      'r_time', 'n_subset', 'res', 'dest_plug_id',
                      'r_maintype',))

header = D_O_hdr(*hdr_data[:9])
print(header)

您现在可以看到,您可以轻松访问每个字段,如print(header.r_len)等等

同样,但稍微有点棘手,对于sr_data

struct_sr_desc = namedtuple('sr_desc', ('sr_offset', 'sr_type',))

sr_data = [struct_sr_desc(off, typ) 
           for off, typ in zip(hdr_data[9::2], hdr_data[10::2])]

# Just make sure we've got a list of 8 objects
assert len(sr_data) == 8

这里的问题是,我们需要将普通列表转换为结构列表hdr_data[9::2]sr_desc(即sr_offset)的每个第一个字段,hdr_data[10::2]取第二个字段zip使一对列表成为一对列表

sr_data[3].type包含255个,这意味着在一个结构中只有三个子记录,但解压它们已经在您身上了!只是别忘了sr_data[i].offset包含一个从标头末尾开始的偏移量。这是最明显的,因为sr_data[0].offset总是0,但无论如何

完整的脚本如下:https://repl.it/@FooBarrior/CreativePartialOpenlook

祝你好运

相关问题 更多 >