80 00 00 00 FF FF FF FF FF FF 60 60 1F B0 13 D0 60 60 1F B0 13 D0 00 00 10 4F F1 1A 00 00 00 00 A0 00 20 04 00 18 52 49 44 2D 31 35 38 31 46 35 59 48 58 32 33 39 48 30 30 32 34 35 30 41 DD 53 FA 0B BC 0D B0 F1 19 03 01 12 31 35 38 31 46 35 59 48 58 32 33 39 48 30 30 32 34 35 30 41 00 00 00 11 16 B5 00 00 AA 10 8D 12 5E 64 77 3D 3E 08 35 08 D0 07 4B 04 DB 01 0A 00 41 09 98 0F 8D 12 A5 64 77 3D 01 00 00 00 00 00 00 01 1A 08 0F 45 BF 0C 00 00 78 56 AD
以上为抓取到的无人机 Remote ID 原始 16 进制数据(部分位置已做脱敏处理)。这份数据包总长 151 字节,完整承载了 OpenDroneID 协议信息。咱们直接切入正题,拆解这个 Beacon 帧的每一个关键字段。
802.11 Beacon 帧 + OpenDroneID 协议完整解析
1. 帧类型与整体结构
这串十六进制数据对应的是 802.11 管理帧(Beacon 帧),里面嵌入了 OpenDroneID 协议数据(Remote ID)。整个帧符合 IEEE 802.11-2020 规范,通过**供应商特定信息元素(VSIE,类型 0xDD)**把无人机的标识、位置和操作者信息打包进去。总长度 151 字节(索引 0-150),没有缺失片段。
2. 帧头部解析(0-35 字节)
帧头占了前 36 个字节,这是标准的 802.11 管理帧结构。我们可以对照下表看具体含义:
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 0-1 | 2 | 帧控制字段 | 80 00 | 管理帧(类型=0),子类型=Beacon 帧(0x8000),无加密、无分片,符合信标帧标准。 |
| 2-3 | 2 | 持续时间 | 00 00 | 标准填充值,用于避免帧冲突,业务上无特殊含义。 |
| 4-9 | 6 | 目的地址 | FF FF FF FF FF FF | 广播地址,Beacon 帧需向所有设备发送,确保周边接收端能捕获。 |
| 10-15 | 6 | 源地址 | 60 60 1F B0 13 D0 | 发送设备的 MAC 地址,推测是无人机无线模块或关联 AP 的 MAC。 |
| 16-21 | 6 | BSSID | 60 60 1F B0 13 D0 | 基本服务集标识,与源地址相同,说明处于基础设施模式(AP 发送,非自组织)。 |
| 22-23 | 2 | 序列控制 | 00 00 | 帧序列号(0)+ 分片号(0),初始帧,无分片。 |
| 24-31 | 8 | 时间戳 | 10 4F F1 1A 00 00 00 00 | 设备内部计时戳(微秒级),用于同步接收端时钟,不直接映射 UTC。 |
| 32-33 | 2 | 信标间隔 | A0 00 | 小端序转换为 0x00A0=160,单位'1024 微秒',计算得 160×1024=163840 微秒≈0.164 秒。 |
| 34-35 | 2 | 能力信息 | 20 04 | 二进制 00100000 00000100→支持 ESS(基础设施网络)、支持隐私保护(WEP 加密),无其他扩展。 |
3. 信息元素(IE)解析(36-146 字节)
帧头之后就是 IE 字段,包含 SSID 和 OpenDroneID 核心数据。IE 遵循'类型(1 字节)+ 长度(1 字节)+ 数据'的规范。
3.1 SSID 信息元素(36-61 字节)
这部分定义了无人机的网络名称,通常作为远程标识的关联 ID。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 36 | 1 | IE 类型 | 00 | 标准 IE 类型,标识后续为 SSID 字段。 |
| 37 | 1 | IE 长度 | 18 | 十六进制 0x18=24 字节,对应 SSID 数据长度。 |
| 38-61 | 24 | SSID | 52 49 44 2D 31 35 38 31 46 35 59 48 58 32 33 39 48 30 30 32 34 35 30 41 | ASCII 转换后为 RID-1581F5YHX239H002450A,这是无人机的'远程标识关联 ID'。注意,真正的序列号在 Basic ID 消息里,这里只是关联名。 |
3.2 OpenDroneID 供应商特定 IE(62-146 字节)
这里是重头戏,OpenDroneID 的数据就藏在这个 VSIE 里。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 62 | 1 | IE 类型 | DD | 供应商特定 IE(VSIE),标识厂商自定义数据。 |
| 63 | 1 | IE 长度 | 53 | 十六进制 0x53=83 字节,对应后续数据长度(64-146 字节共 83 字节)。 |
| 64-66 | 3 | OUI | FA 0B BC | 供应商标识,ASD-STAN(无人机行业标准组织)。 |
| 67 | 1 | App Code | 0D | OpenDroneID 应用代码(0x0D)。 |
4. OpenDroneID 消息包解析(68-146 字节)
64-67 字节是 OUI 和 App Code,从 68 字节开始才是真正的 OpenDroneID 消息包,总长 79 字节。
4.1 消息包头部(68-71 字节)
这一小块决定了后面怎么解析。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 68 | 1 | 消息计数器 | B0 | 递增计数器(176),用于接收端去重或排序。 |
| 69 | 1 | 消息类型 + 版本 | F1 | 高 4 位 0xF=Message Pack(消息包);低 4 位 0x1=F3411-20 (1.1) 协议版本。 |
| 70 | 1 | 子消息大小 | 19 | 单个子消息固定长度 25 字节(符合 OpenDroneID 标准)。 |
| 71 | 1 | 子消息数量 | 03 | 共 3 个子消息(类型 0、1、4),没发可选的类型 2/3。 |
4.2 子消息 1:Basic ID 消息(72-96 字节)
这是无人机的身份证,告诉别人'我是谁'。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 72 | 1 | 消息类型 + 版本 | 01 | 高 4 位 0x0=Basic ID;低 4 位 0x1=F3411-20 (1.1)。 |
| 73 | 1 | ID 类型 + 无人机类型 | 12 | 高 4 位 0x1=Serial Number(序列号);低 4 位 0x2=Helicopter/Multirotor(多旋翼)。 |
| 74-93 | 20 | 无人机序列号 | 31 35 38 31 46 35 59 48 58 32 33 39 48 30 30 32 34 35 30 41 | ASCII 转换后为 1581F5YHX239H002450A,与 SSID 前缀一致,唯一标识。 |
| 94-96 | 3 | 保留字段 | 00 00 00 | 协议预留,填充 0。 |
4.3 子消息 2:Location/Vector 消息(97-121 字节)
这部分包含了位置、速度和高度,是监管最关心的数据。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 97 | 1 | 消息类型 + 版本 | 11 | 高 4 位 0x1=Location/Vector;低 4 位 0x1=F3411-20 (1.1)。 |
| 98 | 1 | 状态 + 标志 | 16 | 高 4 位 0x1=On Ground(地面状态);低 4 位 0x6→bit2=AGL(离地高度),bit1=West(西向),bit0=速度乘数 0.25。 |
| 99 | 1 | 方向 | B5 | 原始值 181°,结合西向标志→361°(Unknown)。 |
| 100 | 1 | 水平速度 | 00 | 原始值 0 × 0.25 = 0 m/s(静止)。 |
| 101 | 1 | 垂直速度 | 00 | 0 × 0.5 m/s = 0 m/s(无升降)。 |
| 102-105 | 4 | 无人机纬度 | AA 10 8D 12 | 小端序重组为 0x128D10AA=311230730,单位 1e-7° → 北纬 31.123073°。 |
| 106-109 | 4 | 无人机经度 | 5E 64 77 3D | 小端序重组为 0x3D77645E=1031234654 → 东经 103.1234654°。 |
| 110-111 | 2 | 气压高度 | 3E 08 | 小端序 0x083E=2110,公式 (值×0.5)-1000 → 55 米。 |
| 112-113 | 2 | 大地高度 | 35 08 | 小端序 0x0835=2101 → 50.5 米。 |
| 114-115 | 2 | AGL 高度 | D0 07 | 小端序 0x07D0=2000 → 0 米(确认地面状态)。 |
| 116 | 1 | 精度组合 | 4B | 高 4 位 <10 m(垂直精度);低 4 位 <3 m(水平精度)。 |
| 117 | 1 | 气压 / 速度精度 | 04 | 高 4 位 >=150 m(气压高度精度);低 4 位 <0.3 m/s(速度精度)。 |
| 118-119 | 2 | 小时内时间戳 | DB 01 | 小端序 0x01DB=475,单位 0.1 秒 → 47.5 秒。 |
| 120 | 1 | 时间戳精度 | 0A | 低 4 位 0xA → 1.0 秒精度。 |
| 121 | 1 | 保留字段 | 00 | 协议预留。 |
4.4 子消息 3:System 消息(122-146 字节)
最后这部分描述系统状态和操作者信息。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 122 | 1 | 消息类型 + 版本 | 41 | 高 4 位 0x4=System;低 4 位 0x1=F3411-20 (1.1)。 |
| 123 | 1 | 系统标志 | 09 | 二进制 00001001→高 4 位 0(正常运行);低 4 位保留。 |
| 124-127 | 4 | 操作者纬度 | 98 0F 8D 12 | 小端序重组为 0x128D0F98=311234456 → 北纬 31.1234456°。 |
| 128-131 | 4 | 操作者经度 | A5 64 77 3D | 小端序重组为 0x3D7764A5=1031234725 → 东经 103.1234725°。 |
| 132 | 1 | 操作者高度类型 | 01 | Dynamic(动态位置)。 |
| 133-134 | 2 | 操作者高度 | 00 00 | 0 × 0.5 = 0 米(相对大地水准面)。 |
| 135-138 | 4 | 系统时间戳 | 00 01 1A 08 | 小端序 0x081A0100=135921920。Epoch 为 2019-01-01,Unix 时间戳约为 1,682,193,920。 |
| 139 | 1 | 无人机分类 | 0F | 此处为分类字段。 |
| 140-145 | 6 | 保留字段 | 45 0F 8D 12 A5 64 | 协议预留,含厂商自定义数据。 |
| 146 | 1 | 保留字段 | 45 | 协议预留。 |
5. 帧尾部:填充位与 FCS(147-150 字节)
最后是 802.11 帧强制要求的尾部字段。
| 偏移(字节) | 长度(字节) | 字段 | 十六进制值 | 说明 |
|---|---|---|---|---|
| 147-148 | 2 | 填充位 | 00 00 | 凑足最小帧长,无业务含义。 |
| 149-150 | 2 | FCS(帧校验序列) | 56 AD | CRC-16 校验,确保数据完整性。 |
解析完这些字段,基本上就能还原出无人机的身份、实时位置和飞手坐标了。实际开发中,建议用 Python 脚本批量处理这类 Hex 数据,效率会高很多。
