3. MAVLink v2.0 新特性:签名、兼容模式与扩展负载

好,咱们进入第三章。说实话,MAVLink v1.0 在很长一段时间里都够用。但无人机系统越来越复杂,飞控、相机、机械臂、地面站……设备一多,v1.0 那 256 字节的负载就显得捉襟见肘了。更关键的是,v1.0 没有消息认证,谁都能伪造一个心跳包,这在工业场景下简直是灾难。

所以 v2.0 来了。它不是一个全新的协议,而是在 v1.0 基础上做了几个关键升级。我个人觉得,最核心的变化就四个:签名机制、兼容模式、扩展负载、以及更灵活的 ID 使用。咱们一个一个说。

核心要点:MAVLink v2.0 向下兼容 v1.0,但引入了可选的签名机制来保证消息的完整性和真实性。扩展负载长度让单帧能传输更多数据,而目标系统/组件 ID 的灵活使用则让多设备协同更加方便。

3.1 签名机制:消息认证与防篡改

先聊聊签名。这是 v2.0 最重要的安全增强。为什么需要它?

你想想看,如果地面站收到一个“解锁电机”的指令,但这个指令是黑客伪造的,那后果不堪设想。v1.0 的报文是明文传输,没有任何防伪手段。v2.0 的签名机制就是为了解决这个问题。

签名的原理其实不复杂。发送方在报文的末尾附加一个 13 字节的签名。这个签名是基于整个报文内容、一个时间戳、以及一个只有通信双方知道的密钥计算出来的。接收方用同样的密钥和算法重新计算签名,如果匹配,就说明报文没有被篡改,而且确实是来自持有密钥的合法发送方。

具体来说,v2.0 的签名结构是这样的:

MAVLink v2.0 报文结构(带签名):
+--------+--------+--------+--------+--------+--------+--------+--------+
| 起始符 | 负载长度| 序列号 | 系统ID | 组件ID | 消息ID |  负载  | 校验和 |
|  (1B)  |  (1B)  |  (1B)  |  (1B)  |  (1B)  |  (3B)  | (0-255B)|  (2B)  |
+--------+--------+--------+--------+--------+--------+--------+--------+
|  签名 (13B)                                                             |
+--------+--------+--------+--------+--------+--------+--------+--------+
| 签名结构:                                                              |
| 链路ID (1B) | 时间戳 (6B) | 签名数据 (6B)                              |
+--------+--------+--------+--------+--------+--------+--------+--------+

这里有几个关键点:

  • 链路 ID (1 字节):用于区分不同的通信链路。比如飞控和地面站是一条链路,飞控和机载计算机是另一条。每条链路可以使用不同的密钥。
  • 时间戳 (6 字节):这是防重放攻击的关键。接收方会记录最近收到的时间戳,如果收到一个时间戳比之前还旧的报文,就丢弃。时间戳通常以微秒为单位,精度很高。
  • 签名数据 (6 字节):这是真正的消息认证码,基于 SHA-256 哈希算法截取前 6 字节生成。

注意:签名是可选的,不是强制的。你可以在系统启动时通过 MAV_CMD_SET_MESSAGE_INTERVAL 或 MAV_CMD_COMPONENT_ARM_DISARM 等命令来启用或禁用签名。但一旦启用,通信双方都必须支持签名,否则无法通信。

我曾经在一个农业无人机项目中吃过亏。当时我们用的是 v1.0,地面站和飞控之间通过 4G 网络通信。结果有一次,地面站收到了一个错误的“返航”指令,无人机直接飞回了错误的坐标。后来排查发现,是网络中间人篡改了报文。从那以后,凡是涉及关键指令的链路,我必开签名。

3.2 兼容模式与不兼容模式

v2.0 的设计者很聪明。他们知道,不可能一夜之间让所有设备都升级到 v2.0。所以,他们设计了两种模式:兼容模式和不兼容模式。

说白了,兼容模式就是让 v2.0 的报文看起来像 v1.0 的报文,这样老设备也能解析。不兼容模式则完全使用 v2.0 的特性,老设备无法识别。

这两种模式的区别体现在报文头部的第 2 个字节——负载长度字段的最高位(bit 7)。

模式 负载长度最高位 (bit 7) 含义 适用场景
兼容模式 0 报文格式与 v1.0 完全兼容,v1.0 设备可以正常解析 混合网络(v1.0 和 v2.0 设备共存)
不兼容模式 1 报文使用了 v2.0 新特性(如扩展负载、签名),v1.0 设备无法解析 纯 v2.0 网络,或需要新特性的场景

举个例子。假设你的地面站是 v2.0,但飞控还是 v1.0。那么地面站在发送心跳包时,就应该使用兼容模式。这样飞控收到后,会把它当成一个普通的 v1.0 报文来处理,完全没问题。

但如果地面站要发送一个带有签名的解锁指令,就必须使用不兼容模式。因为 v1.0 的飞控根本不认识签名,收到后校验和会失败,直接丢弃。所以,不兼容模式其实是一种“声明”:我这个报文用了新特性,老家伙们别碰。

我的建议:在系统设计初期,尽量让所有设备都支持 v2.0。如果实在有老设备,那就只在关键链路上使用不兼容模式,其他链路保持兼容模式。这样可以平衡安全性和兼容性。

3.3 扩展负载(Payload)长度

v1.0 的负载长度是 0-255 字节,但实际受限于 256 字节的 MTU(最大传输单元),有效负载通常只有 250 字节左右。对于大多数消息来说,这足够了。但有些场景,比如传输高分辨率图像、日志文件、或者复杂的参数列表,250 字节就显得太小了。

v2.0 引入了扩展负载的概念。它通过一个特殊的消息 ID——MAVLINK_MSG_ID_EXTENDED(消息 ID 为 0x100)来实现。这个消息的负载可以长达 65535 字节!

具体怎么用呢?看代码:

// 发送扩展负载消息
mavlink_message_t msg;
uint8_t buf[1024]; // 假设我们要发送 1024 字节的数据
uint16_t len = 1024;

// 填充 buf 数据...

// 使用 mavlink_msg_extended_send_struct() 或手动构建
mavlink_msg_extended_pack(
    system_id,      // 系统 ID
    component_id,   // 组件 ID
    &msg,           // 输出消息
    target_system,  // 目标系统 ID
    target_component, // 目标组件 ID
    len,            // 数据长度
    buf             // 数据指针
);

// 发送 msg

这里要注意,扩展负载消息在网络上传输时,会被自动分片成多个标准 v2.0 报文。接收方再把这些分片重组起来。这个过程对应用层是透明的,你只需要调用 API 发送和接收即可。

我记得有一次,我们需要在无人机起飞前,把一整块区域的航点文件(大约 50KB)上传到飞控。如果用 v1.0,得拆成 200 多个小包,还要自己处理丢包重传,非常麻烦。换成 v2.0 的扩展负载后,一个消息就搞定了,省心不少。

3.4 目标系统/组件 ID 的灵活使用

v1.0 中,每个报文都包含源系统 ID 和源组件 ID,但没有目标系统/组件 ID。这意味着,所有设备都在同一个广播域里,每个设备收到报文后,需要自己判断这个报文是不是发给自己的。这在设备少的时候没问题,但设备一多,效率就低了。

v2.0 在报文中增加了目标系统 ID 和目标组件 ID 字段。这样,发送方可以明确指定这个报文是发给谁的。接收方收到后,先检查目标系统 ID 和组件 ID 是否匹配自己,如果不匹配,直接丢弃,不用再解析负载内容。

这个改进带来的好处很明显:

  • 减少 CPU 开销:设备不需要解析所有报文,只处理发给自己的。
  • 支持多目标通信:你可以发送一个报文给特定系统下的特定组件,或者广播给所有系统。
  • 简化路由:在复杂的网络拓扑中(比如多个地面站、多个无人机),目标 ID 可以帮助中间节点快速转发报文。

目标系统/组件 ID 的使用规则也很简单:

  • 如果目标系统 ID 为 0,表示广播给所有系统。
  • 如果目标组件 ID 为 0,表示广播给目标系统下的所有组件。
  • 如果两者都非零,表示发送给特定系统下的特定组件。

嗯,这里要注意一点:v2.0 的报文头部并没有直接增加目标 ID 字段,而是复用了 v1.0 中保留的位。具体来说,v2.0 的报文头部第 3 字节(序列号)的低 6 位仍然用作序列号,但高 2 位被用来编码目标系统 ID 和目标组件 ID 的存在性。这算是一种巧妙的兼容性设计。

3.5 知识体系总览

为了让你更直观地理解 v2.0 的四大新特性及其关系,我画了一张图:

MAVLink v2.0 新特性总览 MAVLink v2.0 签名机制 兼容/不兼容模式 扩展负载长度 目标系统/组件ID 消息认证 + 防篡改 13字节签名 SHA-256 + 时间戳 向下兼容 v1.0 负载长度最高位标识 混合网络必备 负载可达 65535 字节 自动分片重组 适合大文件传输 精准寻址 减少CPU开销 支持多目标通信

从这张图可以看出来,v2.0 的四个新特性是相互独立的,但组合起来能解决很多实际问题。签名机制解决安全问题,兼容模式解决升级过渡问题,扩展负载解决大数据传输问题,目标 ID 解决多设备协同问题。