基于JT808协议的自动化测试----解析二进制数据
思路: 本文运用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)