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.hqwc.cn/news/544315.html

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

相关文章

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):查询 //查询所…

C++11:自动类型推导 auto 和 decltype(下)

前面两篇文章分别介绍了 auto 和 decltype&#xff0c;今天聊聊它们两者之间的区别。 语法格式的区别 auto varname value; // auto的语法格式 decltype(exp) varname [ value]; // decltype的语法格式其中&#xff0c;varname 表示变量名&#xff0c;value 表示赋给变量的值…

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

Linux中 vim 编辑器的使用

文章目录 前言一、vim编辑器模式二、简单的插入、保存和退出三、 命令模式下常用命令即其作用1. 命令模式 思维导图 前言 首先&#xff0c;了解一下 什么是vim 编辑器&#xff1f;在不同的系统中&#xff0c;文本的管理也会不同&#xff1b;windos系统就不多说了&#xff0c…

【运维】StarRocks数据迁移到新集群(针对于集群互通、不互通的情况)

文章目录 一. 迁移整体思路1. 对于新旧集群互通的情况2. 对于新旧集群不互通的情况 二、迁移过程&#xff08;两个集群互通的情况&#xff09;1. 备份过程1.1. 通过mysqlclient与starrocks进行关联1.2. 创建仓库与minio建立联系1.3. 备份数据到minio 2. 迁移过程2.1. 通过mysql…

Web核心,HTTP,tomcat,Servlet

1&#xff0c;JavaWeb技术栈 B/S架构:Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的特点是&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源…

【Leetcode】2684. 矩阵中移动的最大次数

文章目录 题目思路代码结果 题目 题目链接&#x1f517; 给你一个下标从 0 开始、大小为 m x n 的矩阵 grid &#xff0c;矩阵由若干 正 整数组成。 你可以从矩阵第一列中的 任一 单元格出发&#xff0c;按以下方式遍历 grid &#xff1a; 从单元格 (row, col) 可以移动到 (…

FPGA和ASIC

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

一款博客网站源码

一款博客网站源码 源码软件库 为大家内置了主题 清爽又强大真正的永久可用的一条源码&#xff0c;该版本为整合版本&#xff0c;内置了Joe主题&#xff0c;搭建后直接启用即可~ 安装环境要求&#xff1a; PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持&#xff…

MySQL基础架构

文章目录 MySQL基础架构一、连接器 - 建立连接&#xff0c;权限认证二、查缓存 - 提高效率三、分析器 - 做什么四、优化器 - 怎么做五、执行器 - 执行语句六、存储引擎1、存储引擎的概述2、存储引擎的对比3、存储引擎的命令4、存储引擎的选择 MySQL基础架构 大体来说&#xff…

Uniapp有奖猜歌游戏系统源码,附带流量主

有奖猜歌游戏是一款基于uni-app、uniCloud、uniAD 开发的小游戏&#xff0c;通过猜歌曲、观看广告赚取现金奖励。 游戏基本特征 玩家可以通过猜歌、做任务等方式直接获取现金奖励 玩家可以通过猜歌、拆红包、做任务等方式获取金币奖励&#xff0c;当金币累积到一定数量可以兑…

SLAM 算法综述

LiDAR SLAM 其主要思想是通过两个算法&#xff1a;一个高频激光里程计进行低精度的运动估计&#xff0c;即使用激光雷达做里程计计算两次扫描之间的位姿变换&#xff1b;另一个是执行低频但是高精度的建图与校正里程计&#xff0c;利用多次扫描的结果构建地图&#xff0c;细化位…