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://xiahunao.cn/news/2868690.html

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

相关文章

面试官:volatile如何保证可见性的,具体如何实现?

写在开头 在之前的几篇博文中&#xff0c;我们都提到了 volatile 关键字&#xff0c;这个单词中文释义为&#xff1a;不稳定的&#xff0c;易挥发的&#xff0c;在Java中代表变量修饰符&#xff0c;用来修饰会被不同线程访问和修改的变量&#xff0c;对于方法&#xff0c;代码…

前端之用HTML弄一个古诗词

将进酒 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>将进酒</title><h1><big>将进酒</big> 君不见黄河之水天上来</h1><table><tr><td ><img…

【逆向-快速定位关键代码】通过hook常用函数HashMap方法

一生要走多远的路程 经过多少年 才能走到终点 梦想需要多久的时间 多少血和泪 才能慢慢实现 天地间任我展翅高飞 谁说那是天真的预言 &#x1f3b5; Beyond《光辉岁月》 随着移动应用程序的普及&#xff0c;对于安全和隐私的关注也越来越高。安卓应用逆向…

【力扣白嫖日记】1934.确认率

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1934.确认率 表&#xff1a;Signups 列名类型user_idinttime_stampdatetime User_id是该表的主键。每一行都…

JUC之Java对象内存布局

Java对象 对象在堆中的存储布局 它保存了什么 对象指向它的类元数据的指针&#xff0c;虚拟机通过这个指针来确定这个对象是哪个类的实例 对象头有多大&#xff1f;在64位系统中&#xff0c;Mark Word占了8个字节&#xff0c;类型指针占了8个字节&#xff0c;一共是16个字…

鸿蒙开发实现弹幕功能

鸿蒙开发实现弹幕功能如下&#xff1a; 弹幕轮播组件&#xff1a;BannerScroll import type { IDanMuInfoList, IDanMuInfoItem } from ../model/DanMuData //定义组件 Component export default struct BannerScroll {//Watch 用来监视状态数据的变化&#xff0c;包括&#…

git:码云仓库提交以及Spring项目创建

git&#xff1a;码云仓库提交 1 前言 码云访问稳定性优于github&#xff0c;首先准备好码云的账户&#xff1a; 官网下载GIT&#xff0c;打开git bash&#xff1a; 查看当前用户的所有GIT仓库&#xff0c;需要查看全局的配置信息&#xff0c;使用如下命令&#xff1a; git …

Navicat 面试题及答案整理,最新面试题

Navicat 在数据库管理中的主要用途有哪些&#xff1f; Navicat 是一款数据库管理工具&#xff0c;其主要用途包括&#xff1a; 1、多数据库支持&#xff1a; Navicat 支持多种数据库连接&#xff0c;包括 MySQL、Oracle、PostgreSQL、SQLite、SQL Server 等&#xff0c;方便用…

深度强化学习(五)(蒙特卡洛与自举)

深度强化学习&#xff08;五&#xff09;&#xff08;蒙特卡洛与自举&#xff09; 一.蒙特卡洛与自举 上一节介绍了多步 TD 目标。单步 TD 目标、回报是多步 TD 目标的两种特例。如下图所示, 如果设 m 1 m1 m1, 那么多步 TD 目标变成单步 T D \mathrm{TD} TD 目标。如果设…

compile→错误: 不支持发行版本 17

错误: 不支持发行版本 17 具体错误描述如下&#xff1a; [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project big-event: Fatal error compiling: 错误: 不支持发行版本 17 -> [Help 1] [ERROR] …

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem

Chapter 13 Techniques of Design-Oriented Analysis: The Feedback Theorem 从这一章开始讲负反馈Control系统和小信号建模. 13.2 The Feedback Theorem 首先介绍 Middlebrook’s Feedback Theorem 考虑下面负反馈系统 传输函数 Guo/ui G ( s ) u o u i G ∞ T 1 T G…

Artemis Finance引领Metis流动性质押,并启动积分空投活动

在以太坊可扩展性解决方案中&#xff0c; Optimism、Arbitrum等Layer2链主要面临两个问题&#xff1a;欺诈/有效性证明以及去中心化排序器Sequencers。在实际的发展过程中&#xff0c;Optimism或Arbitrum等Layer2链仍然侧重于在欺诈证明和有效性证明方面进行努力&#xff0c;在…

2024年AI辅助研发趋势

标题 《2024年AI辅助研发趋势》摘要 &#x1f680;引言 &#x1f31f;技术进展&#xff1a;AI在研发中的革命性应用 &#x1f4a1;行业应用案例&#xff1a;AI助力解决复杂研发难题 &#x1f3ed;面临的挑战与机遇&#xff1a;化解难题迎接未来 &#x1f6e0;️未来趋势预测&am…

在命令行中输入py有效,输入python无效,输入python会跳转到microsoft store

这里写自定义目录标题 如果你已经尝试过将python添加到系统变量如果你还未将python添加到系统变量没有python安装包且没有配置系统变量 如果你已经尝试过将python添加到系统变量 打开 运行&#xff0c;输入cmd&#xff0c;在命令行中输入 where python。 如果看到了这个 win…

【海贼王的数据航海】排序——概念|直接插入排序|希尔排序

目录 1 -> 排序的概念及其运用 1.1 -> 排序的概念 1.2 -> 常见的排序算法 2 -> 插入排序 2.1 -> 基本思想 2.2 -> 直接插入排序 2.2.1 -> 代码实现 2.3 -> 希尔排序(缩小增量排序) 2.3.1 -> 代码实现 1 -> 排序的概念及其运用 1.1 -&g…

C++ //练习 10.35 使用普通迭代器逆序打印一个vector。

C Primer&#xff08;第5版&#xff09; 练习 10.35 练习 10.35 使用普通迭代器逆序打印一个vector。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /********************************************************************…

vue学习笔记26-插槽Slots

插槽Slots 组件接收模板内容&#xff08;html结构&#xff09;&#xff0c;在某些场景中我们想要为子组件传递一些模板片段。让子组件在它们的组件中渲染这些片段 将子组件在父组件引用后&#xff0c;比以往更改一下,将<子组件名/>➡️<子组件名></子组件名&g…

调皮的String及多种玩法(下部)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

redis 入门01

1.安装与配置 在官网下压缩包并传送给自己的虚拟机或者使用wget直接下载都可以 注意:redis是运行在linux下的基于内存的kv键值对数据库 安装与配置参考 2.经典Hello World 注意设置redis在后台运行,默认是前台进行的 我们配置完成之后首先启动服务器 redis-server 配置文件 这里…

【NTN 卫星通信】 TN和多NTN配合的应用场景

1 场景描述 此场景描述了农村环境&#xff0c;其中MNO (运营商TerrA)仅在城市附近提供本地地面覆盖&#xff0c;而MNO (SatA)提供广泛的NTN覆盖。SatA使用GSO轨道和NGSO轨道上的卫星。SatA与TerrA有漫游协议&#xff0c;允许:   所有TerrA用户的连接&#xff0c;当这些用户不…