Qt 实现 Asterix 报文解析库

【写在前面】

        最近工作中需要解析 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VMware 与 SmartX 分布式存储缓存机制浅析与性能对比

作者&#xff1a;深入细节的 SmartX 一线技术团队 近日&#xff0c;VMware 发布了 vSAN 8&#xff0c;对存储架构进行了重大更新。其中最主要的变化&#xff0c;即引入了新的 Express Storage Architecture&#xff08;ESA&#xff09;架构&#xff1a;用“存储池”替代了原存…

使用Kalibr標定vins參數

這裏使用的是realsense D435&#xff0c;使用其灰階雙目的部分&#xff08;把中間红外点阵投影仪遮住應該可以取得更好的效果&#xff09;&#xff0c;廠商有給相機的標定&#xff0c;但由於Kalibr裏可以直接標定相機和imu的相對位置&#xff0c;是vins需要的參數&#xff0c;比…

MySQL数据库概念及安装

一、数据库的基本概率 1.1 数据 记录每个人的信息 或者记录数据 1.2 表 存放信息的集合 或者存放行和列的信息 1.3 数据库 表的集合 二、数据库管理系统&#xff08;DBMS&#xff09; 2.1 DBMS定义 &#xff08;DBMS&#xff09;是一种软件&#xff0c;用于创建和管理…

【开发环境】Ubuntu 18.04 搭建 QT编译环境详细步骤 【亲测有效】

目录 1 查看Ubuntu系统中Qt版本 2 下载Ubuntu系统Qt版本安装包 3 Qt安装 3.1 Qt 安装步骤 3.2 安装qt发现Ubuntu空间不足&#xff0c;怎么去扩容呢&#xff1f; 3.2.1 硬盘操作步骤&#xff08;需要关闭虚拟机进行操作&#xff09; 3.2.2 Ubuntu命令操作&#xff1a;安装…

Python 实现1~100之间的偶数求和

result0 for i in range(101):if i%20:result result i print(result) 或者 result0 for i in range(2,101,2):result result i print(result)

海外代理IP在跨境电商中的五大应用场景

在我国跨境电商的发展中&#xff0c;海外代理IP的应用日益广泛&#xff0c;它不仅帮助商家成功打入国际市场&#xff0c;还为他们在多变的全球电商竞争中保持优势。下面是海外代理IP在跨境电商中五个关键的应用场景。 1、精准的市场分析 了解目标市场的消费者行为、产品趋势以…

数据库系统概论-练手题集合【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下数据库系统概论中的练手题&#xff0c;以供大家期末复习和考研复习的时候使用。 数据库系统概论系列文章传送门&#xff1a; 第一章 绪论 第二/三章 关系数据库和标准语言SQL 第四/五章 数据库安全性和完整性…

Nodejs 第五十九章(文件流下载)

文件流下载是一种通过将文件内容以流的形式发送给客户端&#xff0c;实现文件下载的方法。它适用于处理大型文件或需要实时生成文件内容的情况。 安装依赖 npm install express #启动服务 提供接口 npm install cors #解决跨域nodejs 完整版代码 核心知识响应头 Content-Ty…

考研失败, 学点Java打小工_Day3_卫语句_循环

1 编码规范——卫语句 表达异常分支时&#xff0c;少用if-else方式。   比如成绩判断中对于非法输入的处理&#xff1a; /*>90 <100 优秀>80 <90 良好>70 <80 一般>60 <70 及格<60 不及格*/Testpu…

C++作业day6

编程1&#xff1a; 封装一个动物的基类&#xff0c;类中有私有成员&#xff1a;姓名&#xff0c;颜色&#xff0c;指针成员年纪 再封装一个狗这样类&#xff0c;共有继承于动物类&#xff0c;自己拓展的私有成员有&#xff1a;指针成员&#xff1a;腿的个数&#xff08;整型 …

JVM常用垃圾收集器

JVM 4.1 哪些对象可以作为GC ROOT? 虚拟机栈&#xff08;栈帧中的局部变量表&#xff09;中引用的对象本地方法栈中引用的对象方法区静态变量引用的对象方法区常量引用的对象被同步锁持有的对象JNI&#xff08;Java Native Interface&#xff09;引用的对象 4.2 常用垃圾收集…

【C语言进阶篇】自定义类型:结构体(上)

目录 1. 结构体类型的声明 ​编辑 1.1 结构体的创建和初始化 1.2 结构体的特殊声明 1.3 结构体的自引用 2. 结构体内存对齐 2.1 对齐规则 2.2 为什么存在内存对齐 2.3 修改默认对齐数 在我们描述简单对象的时候&#xff0c;使用已有的类型就足够了&#xff0c;比如: 但是当我们…

竞争优势:大型语言模型 (LLM) 如何重新定义业务策略

人工智能在内容创作中的突破 在当今快节奏的商业环境中&#xff0c;像 GPT-4 这样的大型语言模型 (LLM) 不再只是一种技术新颖性&#xff1b; 它们已成为重新定义跨行业业务战略的基石。 从增强客户服务到推动创新&#xff0c;法学硕士提供了企业不容忽视的竞争优势。 1. 加强…

量子计算+HPC!ORNL与Riverlane、Rigetti合作研发

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨沛贤 1000字丨8分钟阅读 近日&#xff0c;英国量子计算初创公司Riverlane和美国量子计算公司Rigetti Computing宣布将参与由美国能源部橡树岭国家实验室&#xff08;OR…

【工具】vscode终端打不开

问题 1The terminal process failed to launch: A native exception occurred during launch (forkpty(3) failed.). 参考方案 下面参考链接是针对windows系统上vscode 出现的相同问题的解答 参考链接&#xff1a;https://blog.csdn.net/weixin_40921421/article/details/122…

Linux(openEuler)部署SpringBoot前后端分离项目(Nginx负载均衡)

假如数据库在本地&#xff0c;没有放在Linux中 1.先把数据库中root的主机改成% 2.项目中的数据库链接配置换成本机ip 3.打包 4.把打包好的jar包放到Linux中 一般把jar包放到opt下 5.把前端部分拷贝到Linux的nginx中 5.1在package.json中修改build的值为图中这样 5.2同时由于在…

理论学习:with torch.no_grad()

如果不加上“with torch.no_grad():”&#xff0c;模型参数会发生改变吗&#xff1f; 如果不使用with torch.no_grad():&#xff0c;在进行模型推理&#xff08;即计算outputs_cls net(inputs[batch_size//2:])这一步&#xff09;时&#xff0c;模型参数不会发生改变&#xf…

Linux进程优先级

一.什么是优先级 1.1 概念 优先级是指定进程获取某种资源的先后顺序 cpu资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08;priority&#xff09;。优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用&#xff0c;可以改善系统性能。还可以…

项目五 实现对学生信息的简单查询

项目五 实现对学生信息的简单查询 1&#xff0c;查询数据库中部分字段的信息 使用select语句对表的选择及连接等操作&#xff0c;结构会生成一个临时表&#xff0c;将select结果存放到临时表中 查询数据表中所有字段的值 #格式&#xff1a;(*:表示所有列) select * from 表…

CTF题型 SSTI(2) Flask-SSTI典型题巩固

CTF题型 SSTI(2) Flask-SSTI典型题巩固 文章目录 CTF题型 SSTI(2) Flask-SSTI典型题巩固前记1.klf__sstiSSTI_Fuzz字典&#xff08;网上收集自己补充&#xff09; 2.klf_2数字问题如何解决了&#xff1f;|count |length都被禁&#xff1f; 3.klf_3 前记 从基础到自己构造paylo…