思路: 本文運用python3中的bitstring庫來解析二進制數據
一. 按bit位來解析二進制數據
1.1 協議說明
1.2 解析代碼
# -*- coding: utf-8 -*- # @Time : 2021/4/22 17:15 # @Author : chinablue # @File : tmp0422.py import bitstring # 十六進制數據消息(大端模式) recv_data = "30CFD6D4DAB2E2CAD4545453D3EFD2F4B2A5B1A8" # 解析消息 bs = bitstring.BitStream(hex=recv_data) fmt_head = """ pad:2, bin:1=infoType, bin:1=isAdShow, bin:1=isTTS, bin:1=isDisplayShow, pad:1, bin:1=isEmergency, """ res_list = bs.readlist(fmt_head) context = bitstring.BitStream(hex=bs.hex[2:]).tobytes().decode("gbk") # 保存消息 res_dict = {} res_dict.setdefault("infoType", res_list[0]) res_dict.setdefault("isAdShow", int(res_list[1], base=16)) res_dict.setdefault("isTTS", int(res_list[2], base=16)) res_dict.setdefault("isDisplayShow", res_list[3]) res_dict.setdefault("isEmergency", res_list[4]) res_dict.setdefault("context", context) print(res_dict)
1.3 注意事項
- fmt_head中, pad:2 表示讀取2個bit, 不返回數據; bin:1=infoType 表示讀取1個bit,返回二進制數據, 別名為infoType
- bitstring.BitStream(hex=bs.hex[2:]).tobytes().decode("gbk") 表示獲取到除了第一個字節的所有字節, 並GBK編碼
二. 按固定字節來解析二進制數據
2.1 協議說明
2.2 解析代碼
# -*- coding: utf-8 -*- # @Time : 2021/4/22 17:15 # @Author : chinablue # @File : tmp0422.py import bitstring # 十六進制數據消息 recv_data = "020016000B0102057D404080" # 解析消息 bs = bitstring.BitStream(hex=recv_data) fmt_head = """ hex:8=channelId, hex:16=shootCmd, hex:16=time, hex:8=saveFlag, hex:8=dpi, hex:8=quality, hex:8=luminance, hex:8=contrast, hex:8=saturation, hex:8=chroma, """ res_list = bs.readlist(fmt_head) # 保存消息 res_dict = {} res_dict.setdefault("channelId", res_list[0]) res_dict.setdefault("shootCmd", int(res_list[1], base=16)) res_dict.setdefault("time", int(res_list[2], base=16)) res_dict.setdefault("saveFlag", res_list[3]) res_dict.setdefault("dpi", res_list[4]) res_dict.setdefault("quality", int(res_list[5], base=16)) res_dict.setdefault("luminance", int(res_list[6], base=16)) res_dict.setdefault("contrast", int(res_list[7], base=16)) res_dict.setdefault("saturation", int(res_list[8], base=16)) res_dict.setdefault("chroma", int(res_list[9], base=16)) print(res_dict)
2.3 注意事項
- fmt_head中, hex:8=channelId 表示讀取1個字節(8個bit), 並返回字節對應的十六進制, 別名為channelId
三. 動態讀取解析二進制數據
3.1 協議說明
3.2 解析代碼
# -*- coding: utf-8 -*- # @Time : 2021/4/22 17:15 # @Author : chinablue # @File : tmp0422.py import bitstring # 十六進制數據消息 recv_data = "0200000002040000000C00000013093132372E302E302E31" # 解析消息 bs = bitstring.BitStream(hex=recv_data) fmt_head1 = """ hex:8=count, """ res_list = bs.readlist(fmt_head1) count = int(res_list[0], base=16) res_dict = {} res_dict.setdefault("count", count) tmp_list = [] res_dict.setdefault("list", tmp_list) for _ in range(count): tmp_dict = {} fmt_head2 = """ hex:32=id_hex, hex:8=valueLen_hex, """ res_list = bs.readlist(fmt_head2) id_hex = res_list[0] valueLen_hex = res_list[1] valueLen = int(valueLen_hex, base=16) tmp_dict.setdefault("id_hex", id_hex) tmp_dict.setdefault("valueLen_hex", valueLen_hex) tmp_dict.setdefault("valueLen", valueLen) fmt_head3 = """ hex:valueLen_hex=value_hex, """ res_list = bs.readlist(fmt_head3, valueLen_hex=valueLen * 8) value_hex = res_list[0] # 按整數或字符串解析 if id_hex in ["00000013", "00000017"]: value = bitstring.BitStream(hex=value_hex).tobytes().decode("gbk") else: value = int(value_hex, base=16) tmp_dict.setdefault("value_hex", value_hex) tmp_dict.setdefault("value", value) tmp_list.append(tmp_dict) print(res_dict)
3.3 注意事項
- 通過fmt_head1來獲取字段[參數總數], 通過fmt_head2來獲取每個參數的字段[參數id]和字段[參數長度], 通過fmt_head3來獲取每個參數的字段[參數值](需要通過參數長度來獲取)
- fmt_head3中hex:valueLen_hex=value_hex 表示讀取valueLen_hex個bit, 並返回字節對應的十六進制, 別名為value_hex
- 動態讀取數據時, 需要在readlist方法中填寫對應的動態參數. 如: bs.readlist(fmt_head3, valueLen_hex=valueLen * 8)