Qt 实现 Asterix 报文解析库

news2024/11/24 10:39:19

【写在前面】

        最近工作中需要解析 Cat 21Cat 62 ADS-B 数据 ( 自己的工作包含航空领域 )。

        然后,因为整个 Asterix 协议类别非常之多,每个类别的版本也多,纯手工实现每个版本解析根本不现实 ( 然鹅公司之前的解析库就是这么做的且做的太烂 )。

        于是花了很多时间去寻找一个好用的解析库,比如 Wireshark 的 Asterix 解析部分 ( 可惜因为是插件,有点难移出来 )。

        最后找了很久( Asterix 好像应用比较局限,资料实在太少 ),终于找到一个实现相当良好的工具:AsterixInspector 一个显示Asterix数据文件内容的工具icon-default.png?t=N7T8https://asterix.sourceforge.net/        基于该工具,我将核心部分移植出来并进行简化,最终实现 :Asterix数据报文解析库。icon-default.png?t=N7T8https://github.com/mengps/AsterixParser


【正文开始】

        该库目前支持的类别有:

  - Cat1 (track UAP only)

  - Cat2

  - Cat4

  - Cat7 (downlink UAP only)

  - Cat8

  - Cat10

  - Cat11

  - Cat20

  - Cat21

  - Cat23

  - Cat34

  - Cat48

  - Cat62

  - Cat63

  - Cat64

  - Cat65

  - Cat240

  - Cat247

        因为自己做的工作仅仅是包装得更好用罢了,所以这里简单讲一下用法即可( 偷懒直接用了我的注释 ):

        SimpleAsterixRecordBlock 是报文解析后数据项的存储块。

/**
 * @brief The SimpleAsterixRecordBlock struct
 */
struct SimpleAsterixRecordBlock
{
    /*! [字段引用编号] */
    int frn;
    /*! [数据项ID,例如(I062/070)] */
    QString id;
    /*! [数据项名称] */
    QString name;
    /*! [数据项原始值] */
    QByteArray rawValue;
    /*! [数据项刻度] */
    qreal scale;
    /*! [数据项单位] */
    QString unit;
    /*! [数据项实际值] */
    QVariant value;
    /*! [子数据块列表] */
    QList<SimpleAsterixRecordBlock> subBlock;
};

        SimpleReservedExpansionField 是报文数据项 [RE] 解析后的存储块 ( 目前只支持Cat 21 )。

/**
 * @brief The SimpleReservedExpansionField struct
 */
struct SimpleReservedExpansionField
{
    struct SubField {
        /*! [字段名称] */
        QString name;
        /*! [字段原始值] */
        QByteArray value;
    };
    /*! [字段类型] */
    quint8 type = 0;
    /*! [子字段列表] */
    QList<SubField> subField;
};

        AsterixParser 提供的接口:

    /**
     * @brief getCategory 获取类别
     * @param asterixData Asterix数据包
     * @return int
     */
    int getCategory(const uchar *asterixData);

    /**
     * @brief getU8 字节转U8
     * @param data 原始字节
     * @return quint8
     */
    quint8 getU8(const QByteArray &data);

    /**
     * @brief getU16 字节转U16
     * @param data 原始字节
     * @return quint16
     */
    quint16 getU16(const QByteArray &data);

    /**
     * @brief getU32 字节转U32
     * @param data 原始字节
     * @return quint32
     */
    quint32 getU32(const QByteArray &data);

    /**
     * @brief parseToFsnMap 解析为{fsn, block}映射
     * @param asterixData Asterix数据包
     * @return QMap<int, SimpleAsterixRecordBlock>
     */
    QMap<int, SimpleAsterixRecordBlock> parseToFsnMap(const uchar *asterixData);

    /**
     * @brief parseToIdMap 解析为{id, block}映射
     * @param asterixData Asterix数据包
     * @return QMap<int, SimpleAsterixRecordBlock>
     */
    QMap<QString, SimpleAsterixRecordBlock> parseToIdMap(const uchar *asterixData);

    /**
     * @brief parseReservedExpansionField 解析保留扩展字段
     * @warning 目前仅实现[cat021]
     * @param cat 类别
     * @param ref 扩展字段记录块
     * @return QMap<int, SimpleReservedExpansionField>
     */
    QMap<int, SimpleReservedExpansionField> parseReservedExpansionField(int cat, const SimpleAsterixRecordBlock &ref);

【使用示例】

        使用起来就非常简单了:

#include <QCoreApplication>
#include <QDebug>
#include <QtEndian>

#include "asterixparser.h"

QString applyUnitAndScale(const QVariant &value, qreal scale, const QString &unit)
{
    if (qFuzzyCompare(scale, 1))
        return QString::number(value.toDouble()) + (unit.isEmpty() ? "" : (" "  + unit));
    else
        return QString::number(value.toDouble() * scale, 'f', 10) + (unit.isEmpty() ? "" : (" "  + unit));
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    //cat021
    uchar test[] = {
          0x15, 0x00, 0x35, 0xcb, 0x19, 0x71
        , 0x11, 0xc1, 0x01, 0x04, 0x16, 0x00, 0x11, 0x44, 0x4c, 0x65, 0x80, 0x09, 0xf1, 0x80, 0x2c, 0x25
        , 0xd8, 0x59, 0xe5, 0xff, 0xe0, 0x07, 0x4c, 0x65, 0x80, 0x02, 0x7b, 0x2d, 0x35, 0x08, 0x12, 0x00
        , 0x03, 0x34, 0x81, 0x37, 0xcf, 0x5d, 0xa0, 0x01, 0x07, 0x88, 0x10, 0x01, 0x11, 0x11, 0x02
    };

    //cat062
    /*uchar test[] = {
        0x3e, 0x00, 0x2b, 0x19, 0x31, 0x10, 0x47, 0x88, 0xf6, 0x00, 0x56, 0xfe, 0x34, 0x01, 0x27, 0xad,
        0x07, 0x00, 0x60, 0x6c, 0x31, 0x00, 0x00, 0x00, 0xc1, 0x01, 0x32, 0xff, 0xe1, 0x01, 0x60, 0x6c,
        0x31, 0x00, 0x00, 0x00, 0x4e, 0xee, 0x00, 0x93, 0x00, 0x00, 0x00
    };*/

    AsterixParser parser(QT_STRINGIFY(PWD_PATH) + QString("/../asterixSpecification"));

    auto map = parser.parseToFsnMap(test);

    for (const auto &block: map) {
        qDebug() << block.frn << block.id << block.name << block.rawValue;
        if (!block.subBlock.isEmpty()) {
            for (const auto &subBlock: block.subBlock)
                qDebug() << "  "
                         << subBlock.frn
                         << subBlock.id
                         << subBlock.name
                         << subBlock.value
                         << applyUnitAndScale(subBlock.value, subBlock.scale, subBlock.unit);
        }
    }

    auto ref_map = parser.parseReservedExpansionField(parser.getCategory(test), map[48]);
    for (const auto &ref: ref_map) {
        for (const auto &subField: ref.subField)
            qDebug() << "  "
                     << subField.name
                     << (subField.value.size() == 1 ? (parser.getU8(subField.value)) : (parser.getU16(subField.value)));
    }


    return app.exec();
}

【效果展示】

        Cat 21 解析结果:

        Cat 62 解析结果:


【结语】

        关于规范文件生成部分[asterixSpecification]:

        一般做法是:[规范pdf] ->  [.ast] → [.xml],具体可以看我的项目主页提供的资料。

        项目链接(多多star呀..⭐_⭐):

        CSDN 的:

https://download.csdn.net/download/u011283226/88975636icon-default.png?t=N7T8https://download.csdn.net/download/u011283226/88975636        Github 的:

https://github.com/mengps/AsterixParsericon-default.png?t=N7T8https://github.com/mengps/AsterixParser

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1522532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

01_什么是深度学习

人工智能包含了机器学习&#xff0c;而深度学习是机器学习的一个分支。 人工智能 试图将通常由人类完成的智力任务自动化—这就是人工智能。 用硬编码的方式实现人工智能&#xff0c;这称作符号主义人工智能Symbolic AI。其中包含专家系统。 机器学习 机器学习是一种替代符…

Linux操作系统-汇编LED驱动程序基础

一、汇编LED原理分析 IMX6ULL-LED灯硬件原理分析&#xff1a; 1、使能时钟&#xff0c;CCGR0-CCGR6这7个寄存器控制着IMX6ULL所有外设时钟的使能。为了简单&#xff0c;设置CCGR0-CCGR6这7个寄存器全部为0XFFFFFFFF&#xff0c;相当于使能全部外设时钟。&#xff08;在IMX6ULL芯…

【Stable Diffusion】入门-04:不同模型分类+代表作品+常用下载网站+使用技巧

目录 1 模型简介2 模型文件构成和加载位置2.1 存储位置2.2 加载模型 3 模型下载渠道3.1 HuggingFace3.2 Civitai 4 模型分类4.1 二次元模型4.2 写实模型4.3 2.5D模型 1 模型简介 拿图片给模型训练的这个过程&#xff0c;通常被叫做“喂图”。模型学习的内容不仅包括对具体事物…

Rust学习02:推荐一本入门书,免费的

都说Rust的学习曲线很陡峭&#xff0c;试过才知雀实不容易。 先说我的基础&#xff0c;非科班&#xff0c;自学Python&#xff0c;写过几个小程序。 我买书从来不扣扣嗖嗖的&#xff0c;所以先啃了几本Rust的入门书&#xff0c;包括&#xff1a; Tim McNamara的《Rust实战》&am…

Day40:安全开发-JavaEE应用SpringBoot框架JWT身份鉴权打包部署JARWAR

目录 SpringBoot-身份鉴权-JWT技术 SpringBoot-打包部署-JAR&WAR 思维导图 Java知识点 功能&#xff1a;数据库操作&#xff0c;文件操作&#xff0c;序列化数据&#xff0c;身份验证&#xff0c;框架开发&#xff0c;第三方组件使用等. 框架库&#xff1a;MyBatis&…

idea将非UTF-8的properties修改为UTF-8编码的文件

需求背景 由于项目初始化时&#xff0c;properties文件的编码格式为ASCII编码格式&#xff0c;此时用idea打开该文件会默认展示UTF-8的编码内容&#xff0c;其中汉字可以正常展示&#xff0c;但是使用notepad打开却依旧时ASCII编码格式 idea配置 打开idea-setting-editor-f…

使用Lua编写Wireshark解析ProtoBuf插件

文章目录 Wireshark Protobuf Lua-dissectorStep 1: 获取 WiresharkStep 2: 配置ProtoBuf相关设置添加ProtoBuf查找路径 Step 3 运行和调试Lua代码1. 添加Lua脚本2. 运行和调试 Step 4: 写Lua Dissector代码 :)Step 5(Optional): Decode AsGithub工程地址 Wireshark Protobuf L…

YOLOv8训练好模型后,追加轮数继续训练、或者提前终止训练,缩减训练轮数

一、前言 而且此教程适用的情况是你已经训练好了此模型&#xff0c;想继续追加一些轮数。比如训练进度是120/120&#xff0c;已经完成了&#xff0c;继续追加10轮&#xff0c;或者你原先定的是200轮&#xff0c;希望缩减到150轮&#xff0c;可以使用我说的这个方法。为什么缩减…

【C语言】最大公约数

给定两个数&#xff0c;求这两个数的最大公约数 方法&#xff1a;辗转相除法 例&#xff1a;36与24的最小公约数 36/241...12 24/122...0 那么12就是36与24的最大公约数。 代码如下&#xff1a; #include <stdio.h> int main() { int a 0; int b 0; scan…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:RowSplit)

将子组件横向布局&#xff0c;并在每个子组件之间插入一根纵向的分割线。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含子组件。 RowSplit通过分割线限制子组件的宽度。初始化…

FPGA和ASIC

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我所总结作为学习的笔记第16篇,在本篇文章给大家介绍FPGA和ASIC。 一个四核i7的CPU的晶体管中有20亿的晶体管&#xff0c;需要链接起20亿的晶体管可不是一件容易的事情&#xff0c;所以设计一个CPU需要用年来算&#x…

挑战杯 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

第七课-----分支切平面

割平面方法的基本思想是对于一个优化问题而言&#xff0c;通过不断添加约束条件来切割可行域&#xff0c; 最终将可行域不断变小&#xff0c;相当于搜索空间变小。在LP中讲过&#xff0c;一个等式约束就等价于一个超平面&#xff0c;一个不等式约束就代表一个半空间&#xff0c…

17.搜索二维矩阵Ⅱ

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,2…

2.26回顾章节主体线索脉络,课程要求(评分)

3)翻译程序、汇编程序、编译程序、解释程序有什么差别&#xff1f;各自的特性是什么&#xff1f; 翻译程序是指把高级语言源程序翻译成机器语言程序&#xff08;目标代码&#xff09;的软件。 翻译程序有两种&#xff1a;一种是编译程序&#xff0c;它将高级语言源程序一次全部…

lua脚本的基础内容

官方地址&#xff1a;http://luajit.org/ 官方wiki地址&#xff1a;http://wiki.luajit.org/Home 推荐书籍&#xff1a; OpenResty 最佳实践&#xff1a;https://moonbingbing.gitbooks.io/openresty-best-practices/content/ lua基础文档&#xff1a;https://www.runoob.com/l…

mac电脑修改终端zsh显示的用户名

电脑名称一直没有修改&#xff0c;所以电脑名称都是Apple的MacBook Pro&#xff0c;如下图所示&#xff1a; mac电脑终端显示用户名太长一点也不美观&#xff0c;而且占用很长的行&#xff0c;浪费空间&#xff0c;可以通过修改来调整要显示什么内容&#xff1a; 方式一 要想换…

解决Linux中Eclipse启动时找不到Java环境的问题

按照报错的意思是没有在/usr/local/eclipse/jre/bin/java下找到java环境&#xff0c;我检查了一下eclipse的目录结构发现在/usr/local/eclipse没有jre/bin/java&#xff0c;我的想法是自己建对应文件夹然后软连接到我的java环境 cd /usr/local/eclipse sudo mkdir jre cd jre s…

Java中为什么只有值传递?

Java中为什么只有值传递&#xff1f; 对于对象参数而言&#xff0c;实际参数传递给形式参数的只是一个内存地址&#xff0c;让形式参数也指向实际参数所指向的地址&#xff0c;传递的值的内容是对象的引用。 为什么会是这样&#xff1f;让我慢慢为你讲解。 对于Java的传递类…

自定义协议

应用层 有许多现成的协议(HTTP协议做网站必备),也有许多需要程序员自定义的协议. 1.自定义协议 自定义协议: 1.明确传递的信息是什么 2.约定好信息按照什么样的格式来组织成二进制字符串 举个例子: 当我们点外卖时,打开软件,会显示商家列表,列表中有很多项,每一项都包含了一…