在python构造库(用于解析二进制数据)中,如何将其余数据分组为一个字段?

在python构造库(用于解析二进制数据)中,如何将其余数据分组为一个字段?,python,parsing,protocols,construct,Python,Parsing,Protocols,Construct,我正在使用Python构造库解析蓝牙协议。图书馆的链接是 由于协议非常复杂,我将解析细分为多个阶段,而不是构建一个千兆构造。现在,我已经将大型原始数据解析为以下结构: Container({'CRC': 'd\xcbT', 'CRC_OK': 1, 'Channel': 38, 'RSSI': 43, 'access_addr': 2391391958L, 'header': Container({'TxAdd': False, 'PDU_length': 34, 'PDU_Type'

我正在使用Python构造库解析蓝牙协议。图书馆的链接是

由于协议非常复杂,我将解析细分为多个阶段,而不是构建一个千兆构造。现在,我已经将大型原始数据解析为以下结构:

Container({'CRC': 'd\xcbT',
 'CRC_OK': 1,
 'Channel': 38,
 'RSSI': 43,
 'access_addr': 2391391958L,
 'header': Container({'TxAdd': False, 'PDU_length': 34, 'PDU_Type': 'ADV_IND', 'RxAdd': False}),
 'payload': '2\x15\x00a\x02\x00\x02\x01\x06\x07\x03\x03\x18\x02\x18\x04\x18\x03\x19\x00\x02\x02\n\xfe\t\tAS-D1532'})
如您所见,有效负载的长度表示为PDU_长度,即34。有效载荷具有以下结构:

Container({'CRC': 'd\xcbT',
 'CRC_OK': 1,
 'Channel': 38,
 'RSSI': 43,
 'access_addr': 2391391958L,
 'header': Container({'TxAdd': False, 'PDU_length': 34, 'PDU_Type': 'ADV_IND', 'RxAdd': False}),
 'payload': '2\x15\x00a\x02\x00\x02\x01\x06\x07\x03\x03\x18\x02\x18\x04\x18\x03\x19\x00\x02\x02\n\xfe\t\tAS-D1532'})
[前6个八位字节:广告地址][0-31个八位字节的其余数据:广告数据]

然而,当我开始将负载作为独立结构进行解析时,在负载构造的上下文中,我丢失了34的长度。我如何构造一个将前6个八位字节解析为AdvertAddress并将其余数据分组为AdvertData的结构

我当前的解决方案如下所示:

length = len(payload) #I didn't use PDU_length but len(payload) gives me back 34 also.
ADVERT_PAYLOAD = Struct("ADVERT_PAYLOAD",
    Field("AdvertAddress",6),
    Field("AdvertData",length-6),
)
print ADVERT_PAYLOAD.parse(payload)
这将提供正确的输出。但显然,并非所有有效载荷的大小都是34。此方法要求我在每次需要解析新负载时构造此
ADVERT\u负载

我看了很多次这些文件,但没有找到任何相关的。我无法将有效负载长度的知识传递到
ADVERT\u payload
的上下文中,也无法获得传递到
parse
方法中的参数长度

也许这个问题没有解决办法。但是,大多数人如何解析这样的协议数据呢?随着您深入研究有效负载,它会细分为更多类型,您需要更多更小的构造来解析它们。我应该构建一个父构造,嵌入更小的构造,而嵌入更小的构造吗?我无法想象如何着手建造这么大的东西


提前感谢。

GreedyRange
将获得一个字符列表,
JoinAdapter
将所有字符连接在一起:

class JoinAdapter(Adapter):
    def _decode(self, obj, context):
        return "".join(obj)

ADVERT_PAYLOAD = Struct("ADVERT_PAYLOAD",
    Field("AdvertAddress",6),
    JoinAdapter(GreedyRange(Field("AdvertData", 1)))
)

payload = '2\x15\x00a\x02\x00\x02\x01\x06\x07\x03\x03\x18\x02\x18\x04\x18\x03\x19\x00\x02\x02\n\xfe\t\tAS-D1532'
print ADVERT_PAYLOAD.parse(payload)
输出:

Container:
    AdvertAddress = '2\x15\x00a\x02\x00'
    AdvertData = '\x02\x01\x06\x07\x03\x03\x18\x02\x18\x04\x18\x03\x19\x00\x02\x02\n\xfe\t\tAS-D1532'

我曾想过使用range或greedyrange,但当我看到两者都能生成列表时,我放弃了。我想可能没有别的办法了。我接受这个答案。顺便问一下,对于这种深层结构的协议,您是构造一个大的嵌套结构还是一步一步地解析它们?请注意,我需要解析的AdverData中有更多的结构。一步一步很容易实现,我将首先一步一步地进行,然后尝试将其转换为一个大的嵌套结构。