簡體   English   中英

在 Python3 中使用結構記錄解析串行數據

[英]Parsing serial data with a Structure Record in Python3

我正在嘗試解析通過串行端口從監視器收到的數據。 我已經在 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 中並沒有幫助。 但是,我的問題是針對 Header。 如果,Struct: 只是一個具有多種數據類型的自定義變量。 Header 的結構是否直接對應於我的數據列表中的第一個整數? 例如:r_len = 198, r_nbr = 2, r_time = 0? 我是否繼續按順序向下移動列表以獲取子記錄? 如果是這樣,時間定義為自 1970 年 1 月 1 日以來的秒數。 那么這怎么可能來自單個 integer? 我將非常感謝您提供的任何提示。 感謝您閱讀我的長文。 數據的結構記錄結構記錄第 2 頁

嗨,羅伯特,感謝您完成我剛剛完成的任務!

規范絕對意味着它以字節為單位傳遞數據,由類似 C 的結構描述。 我看不出你是如何讀取數據的,但猜測是你在這里得到了一個字節列表,因為每個值都小於 256。

因此,通過查看結構,我可以嘗試將其轉換為人類可讀的形式。 這是通過 python 中的struct模塊完成的:

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

解釋

在這里,我將l視為字節的初始列表。 鑒於您提供的記錄結構,我為 header 構建了格式字符串:

hBBHLBBHH意思是:短、字節、字節、字、雙字、字節、字節、字、字。

<開頭的意思是字節順序是小端的

打印的結果是

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

這里第一個值是r_len ,等於 710。列表len(l)的長度是 711,所以很可能我最初對列表格式和字節序的猜測是正確的,最后你有一個冗余字節意外。

下一步

雖然我們基本上已經完成了單行,但我們還沒有閱讀 sr_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包含從 header 末尾的偏移量。 這很明顯,因為sr_data[0].offset始終為0但無論如何。

完整的腳本在這里: https://repl.it/@FooBarrior/CreativePartialOpenlook

祝你好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM