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));elsereturn QString::number(value.toDouble() * scale, 'f', 10) + (unit.isEmpty() ? "" : (" "  + unit));
}int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);//cat021uchar 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.mzph.cn/news/750118.shtml

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

相关文章

win10 + cpu + pycharm + mindspore

MindSpore是华为公司自研的最佳匹配昇腾AI处理器算力的全场景深度学习框架。 1、打开官网&#xff1a; MindSpore官网 2、选择以下选项&#xff1a; 3、创建conda 环境&#xff0c;这里python 选择3.9.0&#xff0c;也可以选择其他版本&#xff1a; conda create -c conda-…

智慧交通:构建智慧城市的重要一环

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。作为智慧城市的重要组成部分&#xff0c;智慧交通以其高效、便捷、环保的特性&#xff0c;成为推动城市现代化进程的关键力量。本文将从智慧交通的概念、发展现状、面临挑战以及未来趋势等方面&#…

在一个程序页面中加几个字段用于增删改查

文章目录 前言一、单表步骤1&#xff1a;更新实体类步骤2&#xff1a;更新DAO层XML步骤3&#xff1a;更新Service实现类步骤4&#xff1a;更新Controller层步骤5&#xff1a;更新前端Vue模型和组件 二、多表步骤1&#xff1a;新程序的增删改查步骤2&#xff1a;老程序中新增实体…

学习python笔记:7,操作excel表格,生成柱状图,

注意&#xff1a; 注意xlsx的格式&#xff0c;wps一定另存为xlsx才可以&#xff0c;不然就出错。 操作表格 1&#xff0c;在终端里面安装openpyxl pip install openpyxl import openpyxl as xl from openpyxl.chart import BarChart,Reference#注意xlsx的格式&#xff0c;wps…

MySQL语法分类 DDL(1)

DDL&#xff08;1&#xff09;(操作数据库、表) 数据库操作(CRUD) C(Create):创建 //指定字符集创建 create database db_1 character set utf8;//避免重复创建数据库报错可以用一下命令 create database if not exists db_1 character set utf8;R(Retrieve):查询 //查询所…

【DiffusionModel系列】Sora揭底系列模型介绍 (VAE/DDPM/SD/DiT/Sora)

飞书PPT链接 简介 该文档介绍了几种深度学习模型&#xff0c;特别是那些在图像合成和处理方面有显著应用的模型。文档内容涉及变分自编码器&#xff08;VAE&#xff09;、去噪扩散概率模型&#xff08;DDPM&#xff09;、稳定扩散&#xff08;Stable Diffusion&#xff09;、…

物联网竞赛板CubMx全部功能简洁配置汇总

目录 前言&#xff1a;1、按键&LED灯配置&#xff1a;2、OLED配置&#xff1a;3、继电器配置&#xff1a;4、LORA模块配置&#xff1a;5、矩阵模块&#xff1a;6、串口模块&#xff1a;7、RTC配置&#xff1a;8、ADC模块配置&#xff1a;9、温度传感器模块&#xff1a;后续…

cartographer学习与使用

记录一下在配置和使用cartographer建图时遇到的各种问题吧。 我的数据 配置文件&#xff1a; my_rslidar.launch <launch> <param name"/use_sim_time" value"false" /> <!--启动建图节点--> <node name"cartographer_n…

旋转花键的制造工艺

旋转花键的制造工艺是一门精细的技术&#xff0c;涉及多个步骤和精细的操作&#xff0c;以确保最终产品的质量和性能&#xff0c;下面简单介绍下旋转花键的制造工艺。 1、原材料准备&#xff1a;制造旋转花键的核心是选择合适的材料&#xff0c;根据花键的规格和性能要求&#…

MATLAB 矩阵

【MATLAB】&#xff08;四&#xff09;MATLAB在线性代数中的应用_线性代数在matlab中的应用-CSDN博客 矩阵的秩 rank rank&#xff08;a&#xff09; 矩阵的逆矩阵 inv inv&#xff08;a&#xff09; 矩阵的特征值eig和特征向量D [V,D]eig(a) 特征值 deig(a) 特征向量D [V…

考研C语言复习进阶(6)

目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 ​编辑​编辑 2.2 编译本身也分为几个阶段&#xff1a; 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 2.2.3 #define 替换规则 3.2.4…

流水线式并行加速

入门级的并行加速一般会以一个大数组的计算来举例。这种并行加速的方式适用于大量数据的复杂计算&#xff0c;而且这些计算必须是重复的。然而大多数的程序并不会遇到大量数据的相同计算&#xff0c;这种入门级的并行加速就显得无用武之地。 其实并行加速的模型是对一个任务矩阵…

blender 使用“Shape Keys”(形状键)

【Blender教程】形态键动画_哔哩哔哩_bilibili 准备人头模型 首先需要一个人头的基础网格模型,包含眼睛、嘴巴等部位进入编辑模式,确保顶点布局合理,待会儿需要移动这些顶点设置相对形状关键帧 切换到物体数据属性面板,选择Shape Keys选项卡默认情况下只有一个基础形状关键帧点…

uniapp 分包

在uniapp项目中的根目录下找到pages.json文件夹&#xff1a; {"pages": [ {"path": "pages/index/index","style": {"navigationBarTitleText": "index"}}],// 分包"subPackages": [{"root"…

Lua中文语言编程源码-第二节,更改lbaselib.c基础库模块, 使Lua支持中文关键词(与操作相关的)

源码已经更新在CSDN的码库里&#xff1a; git clone https://gitcode.com/funsion/CLua.git 在src文件夹下的lbaselib.c&#xff0c;是Lua的基础库模块。 增加中文保留字标识符列表&#xff0c;保留英文保留字标识符列表。 搜索luaB_collectgarbage函数: 控制和查询Lua垃圾回…

算法中出现的一些报错及其处理办法

Exception in thread “main” java.lang.UnsupportedOperationException 源代码是 Scanner s new Scanner(System.in);int target s.nextInt();Set<Integer> set new HashSet<>();for(int i0;i<target;i)set.add(s.nextInt());List<Integer> list s…

基础练习题之函数

前言 这些题目来自与一些刷题网站,以及c primer plus,继续练习 第一题 给你一个数&#xff0c;让他进行巴啦啦能量&#xff0c;沙鲁沙鲁&#xff0c;小魔仙大变身&#xff0c;如果进行变身的数不满足条件的话&#xff0c;就继续让他变身。。。直到满足条件为止。 巴啦啦能量…

SQLiteC/C++接口详细介绍之sqlite3类(十五)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十四&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十六&#xff09; 47.sqlite3_set_authorizer 用法&#xff…

11.进程的同步与互斥

11.进程的同步与互斥 计数信号量及其初始化 和王道里面学的PV操作一摸一样,带个count变量,带个阻塞队列 //D:\code\x86\code\start\start\source\kernel\include\ipc\sem.h #ifndef OS_SEM_H #define OS_SEM_H#include "tools/list.h"/*** 进程同步用的计数信号量*…

BswM模块配置指导

文章目录 BswM配置的分类自动配置:通信控制Rule:CC_ComMChannel_Rx自动配置:Ecu状态处理自动配置:模块初始化其他配置总结BswM模块是基础软件的模式管理模块,模式/状态控制都是由BswM模块进行,其实现的方式是通过 “请求-仲裁-执行”三步完成。本篇基于基本Can通信所用到…