基于CAPL的DDS子消息解析- Data

article/2025/7/5 14:55:41

1往期回顾

通过《DDS—RTPS一致性测试案例分析》一文,我们了解到 Data 子消息在 Data Distribution Service(DDS) 通信中扮演着至关重要的角色。它不仅负责 DDS 实体的 Simple Participant Discovery Protocol (SPDP) 发现流程,还参与了 Simple Endpoint Discovery Protocol (SEDP) 中的 Topic 和 QoS 确认流程。此外,Data 子消息还承担着发布 Topic 信息、声明存活性以及通知对端自身下线等功能,堪称 DDS 协议中“最忙碌”的子消息。为了更深入地理解 Data 子消息的工作原理,并能够通过 CAPL 仿真和解析该子消息,我们需要揭开其神秘的面纱,详细分析其结构和功能。这不仅有助于我们更好地掌握 DDS 协议的通信机制,还能为 CAPL 脚本开发提供清晰的思路和实用的方法。接下来,我们将从 Data 子消息的结构、字段作用以及实际应用场景入手,逐步解析其核心功能,并通过 CAPL 仿真实例展示如何解析和生成 Data 子消息,为开发高效的 DDS 通信脚本奠定基础。

2 Data详解

Data子消息是由The Real-time Publish-Subscribe Protocol(RTPS) DDS Interoperability Wire Protocol Specification定义的。RTPS 是 DDS 协议的核心实现,负责定义数据分发的具体通信机制。根据 RTPS 协议,Data 子消息的报文结构如下所示:

图1 Data定义

2.1 DATA

表示SubmessageId,为固定值,是0x15。RTPS中定义的消息类型为SubmessageFlag,占1字节,因此在CAPL中可以用byte类型表示,如“byte  submessageId;”。

2.2 Flags

消息类型为SubmessageFlag ,占1字节, Flags只使用了高5位。由低到高分别简写为N、K、D、Q和E,其中N = 1表示serializedPayload采用非标准格式,否则采用DDS规定的标准格式。标准格式指的是PL_CDR_BE、PL_CDR_LE等序列化格式,RTPS V2.5的10章节有介绍,而这些序列化细则主要是在DDS-XTypes协议中定义;Q = 1表示消息中包含inlineQos参数,否则不包含。当Q = 0时,解析Data时要跳过inlineQos参数;E = 1表示为数据格式为Little_Endian,否则为Big_Endian;K和D是组合使用的,如下:

•D=0和K=0表示没有serializedPayload。

•D=1和K=0表示serializedPayload包含序列化的数据。

•D=0和K=1表示serializedPayload包含序列化的Key。

•D=1和K=1在这个版本的协议中是一个无效的组合。

Flags在CAPL中可以用byte类型表示,如“byte  flags;”,但是实际操作中会频繁的用到D、K、E等标志位,所以可以采用struct的数据类型,如下所示:

  struct DataFlags_t {

     byte value;  //原始Flags值

     byte E;

     byte Q;

     byte D;

     byte K;

     byte N;

};

这样在脚本中就可以直观地使用标志位,如Data.flags.E、Data.flags.Q等。

2.3 OctetsToNextHeaderextraFlagsOctetsToInlineQos

OctetsToNextHeader字段表示当前子消息的长度,其值为到下一个子消息头起始位置的字节数。RTPS中定义的消息类型为unsigned short,占2字节,在CAPL中可以用word类型表示,如“word submessageLength;”。

extraFlags未使用,该版本应该将参数设置为零。RTPS中定义的消息类型为unsigned short,占2字节,在CAPL中可以用word类型表示,如“word extraFlags;”。

OctetsToInlineQos表示紧跟该字段的第一个字节开始直到inlineQos的第一个字节的字节数。如果inlineQos不存在,则表示到serializedPayload的第一个字节的字节数。RTPS中定义的消息类型为unsigned short,占2 字节,在CAPL中可以用word类型表示,如“word inlineQosFlag”。

2.4 readerIdwriterId

readerId表示消息接收实体Id,writerId表示消息发送实体Id。应该重点是关注这两个参数,进而判断该消息的实际用途(详见《DDS—RTPS一致性测试案例分析》)。RTPS中定义的数据类型为EntityId_t,其定义如下所示:

typedef octet OctetArray3[3];

struct EntityId_t {

OctetArray3 entityKey;

octet entityKind;

};

其中entityKey表示Entity类型,比如是Participant、Reader、Writer、Reader Group、Writer Group,以及该Entity是built-in Entity、user-defined Entity 或者vendor-specific Entity。

entityKind表示Entity是built-in Entity、user-defined Entity 或者vendor-specific Entity,比如entityKind = 0x02表示User-defined 的Writer (with Key), entityKind = 0x07表示User-defined Entity的Reader(with Key),具体规则详见RTPS V2.5协议的9.3.1.2。

例如,协议规定ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER = {{00,01,00},c2},所以当Data的writerId = {{00,01,00},c2}时,我们就可以知道这是一个SPDP消息。

虽然EntityId_t是一个结构体,但是RTPS协议对EntityId都整体定义好的,所以在CAPL可以简化为dword类型,占4字节,如“dword writerId;”,因此writerId = {{00,01,00},c2}可以等效表示为writerId = 0x000100c2。

2.5 writerSN

表示 Writer 发送 Data 消息的相对顺序。每次发送新的 Data 消息时,writerSN 会递增,从而为每条消息分配一个连续的序号。例如,第一条发送的 Data 消息的 writerSN = 1,之后每发送一条新消息,writerSN 增加 1。如果某条消息丢失,Reader 可以通过 writerSN 检测到丢失的消息,并请求重传缺失writerSN的Data消息,这也是DDS消息的可靠性不依赖于传输协议的机制。

需要注意的是,writerSN 的更新是由每个 Entity 独立管理的,而不是全局统一的。每个 Entity 维护自己的 writerSN 序列。此外,只有 Data 消息的内容发生实质更新时,writerSN 才会递增。例如:

  1. SPDP 消息:由built-in Entity的 SPDP BuiltinParticipantWriter 发送。如果在程序执行周期内,DomainId、单播 IP 或广播 IP 等配置没有发生变化,SPDP 报文内容不会改变,因此 writerSN 并不会增加。
  2. Topic消息:由User-defined Entity的 Writer发送。每次发布Topic 时,其内容通常会发生变化,因此 writerSN 会递增。

RTPS中定义的消息类型为SequenceNumber_t,数据结构如下:

struct SequenceNumber_t {

 long high;

 unsigned long low;

};

其中high表示有符号的高4字节,low表示无符号的低4字节,所以是一个有符号数。因此,在CAPL中也用struct类型表示,如下所示:

  struct SequenceNumber_t  {

     long  high;

     dword low;

  };

2.6 inlineQos

仅当Q = 1才会有效,包含可能影响消息解释的QoS。消息格式定义如下所示:

struct Parameter {

ParameterId_t parameterId;

short length;

octet value[length]; // Pseudo-IDL: array of non-const length

};

parameterId标识独一无二的参数,由协议规定,length表示value的长度。具体规则详见RTPS V2.5协议的9.6.4,这只介绍一个常用的inlineQos来帮助大家熟悉报文分析方法。例如,inlineQos的原始报文为71 00 04 00 00 00 00 03,采用Little_Endian。

这段报文解析为parameterId = 0x0071,length = 0x0004,value[4] = {0,0,0,3}。根据RTPS协议,0x71表示PID_STATUS_INFO,该消息的value表示一个32位的标志,只用到了高3位,由低到高分别是F、U、D,其中:

D = 1表示 Writer 处理了子消息中 Key 对应的数据对象实例,该实例的生命周期结束了。

U = 1表示 Writer 注销了子消息中 Key 对应的数据对象实例,不再管理该实例。

F = 1表示Writer为子消息中 Key 对应的数据对象实例写入了一个样本,但样本未通过 Reader 内容过滤器,也就是没有提交给Reader。

所以,上面的inlineQoS表示DataWriter已经注销了。

在CAPL中可以用struct类型表示,由于CAPL不支持动态创建数组,因此需要预定义较大的数组来保存数据,如下所示:

  struct ParameterList_t{

       word parameterId;

       word length;

       byte value[512]; // value[length]

  };

2.7 serializedPayload

仅当D = 1或者K = 1才显示,如果D = 1则表示为序列化的数据,如果K = 1则表示为序列化后的Key值,标识数据对象的实例,数据结构定义如下:

typedef octet RepresentationIdentifier[2];

typedef octet RepresentationOptions[2];

struct SerializedPayloadHeader {

 RepresentationIdentifier representation_identifier;

 RepresentationOptions representation_options;

};       //SerializedPayload

representation_identifier标识所使用的数据表示方式,如果协议规定PL_CDR_BE = {0x00, 0x02},PL_CDR_LE = {0x00, 0x03},详情请看RTPS V2.5的10.3 -10.6章节。representation_options默认为全0,应该忽略。所以如果脚本需要解析payload需要关注representation_identifier的参数。

在CAPL中可以用struct类型表示,其中buffer表示序列化的payload,并且要额外的记录数据长度,如下所示:

  struct serializedData_t  {

     word kind;

     word option;

     byte buffer[DATA_SERIALIZED_DATA_LENGTH]; 

     dword len;

  };

3 CAPL解析

通过上文的介绍,我们已经知道了Data子消息的构成,因此解析Data子消息前首先要基于CAPL建立其对应的数据结构,如下所示:

图2 Data_t定义

解析时,首先将RTPS消息分割成报头和子消息,根据SubmessageId判断子消息类型,然后进行反序列化完成数据解析,当这个子消息解析完成后,将继续接下一个,直到所有子消息被解析完成,整个流程如下所示:

图3 子消息解析流程和示例代码

解析过程中,需要对“特殊”Data进行解析,比如SPDP报文的解析核心是对serializedPayload解析,由于篇幅有限只为大家展现下某车企的SPDP报文解析结果,如下所示:

图4 SPDP报文解析结果

文中提到的 CAPL 脚本不仅能够解析 Data 子消息,覆盖了 DDS 协议中的全部子消息类型,并支持对报文格式、协议一致性以及 QoS 策略等方面的全面测试。

4结语

通过本文,我们详细介绍了 Data 子消息的结构、字段作用以及实际应用场景,并为大家提供了通过 CAPL 脚本解析报文的思路和方法,希望能够为您的开发工作提供实用参考。由于水平有限,对协议难免有所偏差,如果您对本文内容感兴趣或者有其他疑问,对 CAPL 脚本的实现细节或 DDS 协议测试有进一步需求,欢迎将需求发送至邮箱market@dotrustech.com,我们将竭诚为您提供支持。


http://www.hkcw.cn/article/JcfCIbeHaf.shtml

相关文章

MySQL之数据库的内嵌函数和联合查询

MySQL之数据库的内嵌函数和联合查询 一.数据库的内嵌函数1.1聚合函数1.2日期函数1.3字符串处理函数1.4 数学函数1.5其他常用的函数 二.联合查询2.1笛卡尔积2.2内连接2.3外连接2.4 自连接2.5子查询2.6合并查询 一.数据库的内嵌函数 1.1聚合函数 在MySQL中有着一类聚合函数来方…

【AUTOSAR OS】内存保护模块技术解析

一、模块总体功能概述 Os_Mprot.c 是AUTOSAR Classic Platform(CP)中内存保护模块的核心实现,主要负责验证任务(Task)和中断服务程序(ISR)对内存区域的访问权限,确保系统资源的合法使用。其核心功能包括: 内存访问权限校验:根据任务/中断所属的应用(App)信任级别(…

Docker 跨平台支持:从 Linux 到 macOS 的容器化开发实践

Docker 容器的理念是“一次构建,处处运行”,旨在解决应用程序在不同环境中部署的兼容性问题。然而,这一承诺的实现,在非原生 Linux 系统(如 macOS 和 Windows)上,需要巧妙的底层机制来支撑。 对于开发者而言,理解 Docker Desktop 在这些操作系统上的工作原理,特别是其…

电机试验平台:现代科技与工程应用的典范

电机试验平台作为电机行业中至关重要的一环,扮演着起着举足轻重的角色。随着科技的进步和工程技术的不断发展,电机试验平台也在不断创新和完善。本文将从电机试验平台的基本概念、发展历程、技术特点以及未来趋势等方面展开介绍。通过深入探讨&#xff0…

[paddle]paddle2onnx无法转换Paddle3.0.0的json格式paddle inference模型

使用PDX 3.0rc1 训练时序缺陷检测后导出的模型无法转换 Informations (please complete the following information): Inference engine for deployment: PD INFERENCE 3.0-->onnxruntime Why convert to onnx:在端侧设备上部署 Paddle2ONNX Version: 1.3.1 解…

内核进程基础

进程定义 操作系统作为硬件的使用层,提供使用硬件资源的能力;进程作为操作系统的使用层,提供使用操作系统抽象出的资源层的能力。 进程:是指计算机中已运行的程序。进程本身不是基本的运行单位,而是线程的容器。程序…

nic_monitor-全面监控以太网、IB、RoCE网络流量的工具

本文提供三个工具,1. nic_monitor 使用脚本语言 Bash Shell 编写的,用来监控以太网或者RDMA接口流量使用的。 2. nic_monitor_v2.0_eth.py 通过TUI界面实时显示以太网流量的工具,使用Python3编写的。3. nic_monitor_v2.1_rdma.py 通过TUI界面实时显示 IB 和 RoCE 流量的工具…

【论文解读】CVPR2023 PoseFormerV2:3D人体姿态估计(附论文地址)

论文链接:https://arxiv.org/pdf/2303.17472 源码链接:https://github.com/QitaoZhao/PoseFormerV2 Abstract 本文提出了 PoseFormerV2,通过探索频率域来提高 3D 人体姿态估计的效率和鲁棒性。PoseFormerV2 利用离散余弦变换(DC…

01流程定位

1.以客户为中心,端到端创造价值 大家要思考一个核心问题,企业用什么为客户创造价值? 流程管理大师-迈克而哈默博士回答,不是产品和服务,而是业务流程,是创造、交付产品和服务背后的各种业务流程&#xff0…

【计算机网络】传输层TCP协议——协议段格式、三次握手四次挥手、超时重传、滑动窗口、流量控制、

🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:计算机网络 🌹往期回顾🌹: 【计算机网络】传输层UDP协议 🔖流水不争,争的是滔滔不息 一、TCP协议 UDP&…

AI炼丹日志-24 - MCP 自动操作 提高模型上下文能力 Cursor + Sequential Thinking Server Memory

点一下关注吧!!!非常感谢!!持续更新!!! Java篇: MyBatis 更新完毕目前开始更新 Spring,一起深入浅出! 大数据篇 300: Hadoop&…

yolov8改进模型

YOLOv8 作为当前 YOLO 系列的最新版本,已经具备出色的性能。若要进一步改进,可以从网络架构优化、训练策略增强、多任务扩展和部署效率提升四个方向入手。以下是具体改进思路和实现示例: 1. 网络架构优化 (1) 骨干网络增强 引入 Transform…

单卡4090部署Qwen3-32B-AWQ(4bit量化)-vllm

单卡4090部署Qwen3-32B-AWQ(4bit量化) 模型:Qwen3-32B-AWQ(4bit量化) 显卡:4090 1 张 python版本 python 3.12 推理框架“vllm 重要包的版本 vllm0.9.0创建GPU云主机 这里我使用的是优云智算平台的GPU,使用链接可以看下面的 https://blog.…

【C++并发编程01】初识C++并发编程

1、并发是什么 并发是指两个或更多独立的活动同时发生,现实生活中常见的并发场景如边吃饭边看手机。 1.1、计算机中的并发: 计算机领域的并发是指在单个系统里同时执行多个独立的任务,而非顺序的进行一些活动。 我们在电脑上能够边听音乐边和…

【NLP入门系列一】NLP概述和独热编码

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 博主简介:努力学习的22级本科生一枚 🌟​;探索AI算法,C,go语言的世界;在迷茫中寻找光芒…

【知识点】第2章:Python程序实例解析

文章目录 知识点整理Python程序语法元素分析 练习题判断题填空题选择题 知识点整理 Python程序语法元素分析 Python程序包括格式框架、注释、变量、表达式、分支语句、循环语句、函数等语法元素。 程序的格式框架 Python语言采用严格的 “缩进” 来表明程序的格式框架。缩进…

Webug4.0靶场通关笔记05- 第5关SQL注入之过滤关键字

目录 一、代码审计 1、源码分析 2、SQL注入分析 (1)大小写绕过 (2)双写绕过 二、第05关 过滤型注入 1、进入靶场 2、sqlmap渗透 (1)bp抓包保存报文 (2)sqlmap渗透 &…

001在线拍卖系统技术揭秘:构建高效交互的竞拍平台

在线拍卖系统技术揭秘:构建高效交互的竞拍平台 在互联网经济蓬勃发展的当下,在线拍卖系统以其独特的交易模式,吸引着众多用户参与。该系统涵盖个人中心、用户管理等多个关键模块,通过前台展示与后台录入的协同运作,满…

LabVIEW输血袋字符智能检测系统

针对医疗行业输血袋字符检测需求,基于 LabVIEW 图形化开发平台与基恩士(KEYENCE)机器视觉硬件,构建高精度、高可靠性的字符在线识别系统。通过选用基恩士工业相机、光源及 NI 数据采集设备等硬件,结合 LabVIEW 强大的图…

Conditional注解的使用

目录 1.ConditionalOnBean 1.1、作用 1.2、使用场景 2. ConditionalOnMissingBean 2.1、作用 2.2、使用场景 3. 两者结合使用 4. 高级用法: 5. 注意事项 6. 实际应用场景 前言 在 Spring 框架中,ConditionalOnBean 和 ConditionalOnMissingBea…