• 基于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)
  • 相关阅读:
    css 网格布局简单应用
    服务器常用状态码
    js 操作数组
    下拉框 tree 基于 EasyUi
    c# 导出Excel
    select 多选 (EasyUI)
    如何提高sql查询速度
    总结JS中string、math、array的常用的方法
    php 验证邮箱 php验证手机号码 ph验证身份证
    jquery+php ajax上传多图片即时显示
  • 原文地址:https://www.cnblogs.com/reconova-56/p/14690691.html
Copyright © 2020-2023  润新知