2. MAVLink 核心概念:消息、命令、微服务与安全
好,我们正式开始接触 MAVLink 的骨架。这一章我会把四个最核心的概念掰开揉碎讲清楚:消息、命令、微服务,还有消息签名与安全。这四个东西你搞明白了,后面写代码、调参、做地面站,心里就有底了。
我个人习惯把 MAVLink 理解成一套「无人机领域的 HTTP 协议」。消息就是请求和响应,命令就是 POST 一个特殊动作,微服务就是后台跑的那些守护进程。嗯,这个类比不一定完全准确,但上手阶段特别好用。
2.1 消息(Message)—— 一切通信的原子单位
MAVLink 里最基础的东西就是消息。说白了,就是一包结构化的二进制数据,从飞控发到地面站,或者反过来。
每条消息都有一个唯一的 ID,比如 HEARTBEAT 的 ID 是 0,GPS_RAW_INT 是 24。我刚开始学的时候老记不住这些数字,后来发现根本不用记——MAVLink 的代码生成器会帮你把 ID 和结构体绑定好,你直接调函数就行。
消息的典型结构:
- STX(起始标志):MAVLink 1 是 0xFE,MAVLink 2 是 0xFD
- Payload Length:有效载荷长度
- Sequence Number:序列号,用来检测丢包
- System ID & Component ID:谁发的、哪个部件发的
- Message ID:这条消息是什么类型
- Payload:真正的数据
- Checksum:CRC 校验
举个例子,HEARTBEAT 消息只有 9 个字节的 payload,但包含了飞控的类型、状态、自定义模式。我在项目里遇到过一个问题:地面站收不到心跳,结果发现是波特率配错了。你想想看,心跳都丢了,后面所有消息肯定都收不到。所以调试的时候,第一件事就是看心跳。
2.1.1 消息的两种版本:MAVLink 1 vs MAVLink 2
| 特性 | MAVLink 1 | MAVLink 2 |
|---|---|---|
| 消息 ID 范围 | 0–255 | 0–16777215 |
| Payload 最大长度 | 255 字节 | 255 字节(可扩展) |
| 签名支持 | 不支持 | 支持 |
| 兼容性标志 | 无 | 有(兼容位 + 不兼容位) |
| 实际使用 | 老设备、低带宽链路 | 新项目、需要安全性的场景 |
我个人建议新项目直接用 MAVLink 2。原因很简单:消息 ID 够多,还能加签名。我曾经在一个老项目里被迫用 MAVLink 1,结果自定义消息 ID 不够用,最后只能复用一些不常用的标准消息 ID,调试起来特别痛苦。
2.2 命令(Command)—— 让无人机执行动作
消息是「告诉地面站我现在怎么样」,命令是「让飞控去做某件事」。命令通过 COMMAND_LONG(ID=76)或 COMMAND_INT(ID=75)消息来传输。
每个命令也有一个 ID,比如 MAV_CMD_NAV_TAKEOFF 是 22,MAV_CMD_DO_SET_MODE 是 176。命令可以带最多 7 个参数(param1 到 param7),具体含义看命令定义。
避坑指南:我曾经在测试时发了一个 MAV_CMD_NAV_LAND,结果无人机直接原地降落——因为我忘了检查当前模式是不是 AUTO。命令的执行结果取决于飞控当前的状态和模式。发命令之前,最好先读一下 HEARTBEAT 里的模式字段。
命令的交互流程一般是这样的:
- 地面站发送
COMMAND_LONG消息 - 飞控收到后,立即回复
COMMAND_ACK消息 COMMAND_ACK里包含一个 result 字段,告诉你命令是成功、被拒绝、还是正在执行
嗯,这里要注意:COMMAND_ACK 只表示飞控收到了并尝试执行,不代表动作已经完成。比如起飞命令,ACK 返回成功只说明飞控开始执行起飞逻辑,真正离地还要等几秒。
2.3 微服务(Microservice)—— 协议之上的业务逻辑
MAVLink 不只是一堆消息和命令,它还定义了一些微服务。微服务是一组消息的交互模式,用来完成某个特定功能。
常见的微服务有:
- Mission Protocol:上传/下载航点任务
- Parameter Protocol:读写飞控参数
- Camera Protocol:控制相机拍照、录像
- GPS Global Origin:设置地理参考点
每个微服务都有自己的一套请求/响应/重试机制。比如 Parameter Protocol,地面站发 PARAM_REQUEST_LIST,飞控就一条一条地回 PARAM_VALUE,直到发完为止。
注意:微服务不是独立进程,而是一组约定好的消息交互流程。你在飞控代码里看到的「微服务」,其实就是几个消息处理函数的组合。别被名字吓到。
我个人觉得,理解微服务最好的方式就是抓包看一次。你打开地面站,点一下「读取参数」,然后看串口日志——你会发现飞控和地面站之间来回发了上百条消息,这就是微服务在干活。
2.4 消息签名与安全—— 别让你的无人机被劫持
MAVLink 2 引入了一个非常重要的特性:消息签名。说白了,就是在每条消息末尾加一个 6 字节的签名,用来验证消息的完整性和来源。
签名是怎么工作的?
- 飞控和地面站共享一个 32 字节的密钥(secret key)
- 发送方用密钥 + 消息内容 + 时间戳,算出一个 SHA-256 哈希,取前 6 字节作为签名
- 接收方用同样的密钥和算法重新计算,比对签名是否一致
时间戳也很关键。它是个 48 位的毫秒级时间戳,接收方会检查时间戳是否在允许的偏差范围内(默认 1 秒)。这样可以防止重放攻击——就算攻击者录下了你的消息,过几秒再发出来,也会因为时间戳过期而被丢弃。
签名带来的额外开销:
- 每条消息增加 6 字节(签名)+ 6 字节(时间戳)
- 发送方和接收方都需要计算 SHA-256
- 密钥管理需要额外代码
对于 115200 bps 的链路,这个开销完全可以接受。但如果你用 9600 bps 的老电台,就要权衡一下了。
我曾经在一个农业无人机项目里吃过亏。当时没开签名,结果有人在农田边上用一台笔记本伪造了 COMMAND_LONG 消息,让无人机在空中切到了 RTL 模式。嗯,从那以后,凡是飞越人群或敏感区域的无人机,我都强制要求开启签名。
2.4.1 如何开启签名
在 PX4 或 ArduPilot 上开启签名,一般需要两步:
- 设置参数
MAV_SIGNING为 1 - 写入密钥(通过
SETUP_SIGNING消息或直接写参数文件)
地面站这边,QGroundControl 在「通信设置」里有个「启用签名」的选项,填上同样的密钥就行。密钥要保密,但也要备份——我见过有人把密钥存在飞控的 SD 卡里,结果 SD 卡坏了,飞控直接变砖,只能重新刷固件。
2.5 本章知识体系总览
下面这张图把四个核心概念的关系画出来了。我建议你多看几遍,理解消息、命令、微服务、签名之间是怎么配合的。
从图里可以看得很清楚:消息在最底层,命令和微服务都建立在消息之上。签名则像一层防护罩,覆盖所有消息。你写代码的时候,也是这个顺序——先搞定消息收发,再实现命令处理,然后封装微服务,最后加上签名。
2.6 本章小结
这一章我们讲了四个核心概念:
- 消息:MAVLink 的原子通信单位,有固定格式和 ID
- 命令:通过
COMMAND_LONG消息让飞控执行动作,需要 ACK 确认 - 微服务:一组消息交互的约定,完成特定功能(任务、参数、相机等)
- 签名与安全:MAVLink 2 的防伪造、防重放机制,用共享密钥 + 时间戳实现