蓝牙广播包需求文档.md 3.1 KB

蓝牙广播包改造需求

背景

当前设备二维码中存储的是设备 MAC 地址(格式:98:A3:16:35:D2:52)。

Android 平台,系统 BLE API 的 deviceId 直接就是 MAC 地址,可以通过扫码结果直接发起连接。

iOS 平台,系统出于隐私保护,不暴露设备的真实 MAC 地址,deviceId 是系统随机分配的 UUID,且每次重置蓝牙后会变化。因此 iOS 无法通过 MAC 地址直接连接设备,必须先扫描周边设备,再通过某种标识从广播包中识别出目标设备

当前问题

当前设备广播包内容(十六进制):

06000109210AD04EB83117A450432D323032333032313531333539

其中不包含设备 MAC 地址,导致 iOS 端扫码后无法定位到目标设备。

需求

请在 BLE 广播包的 Manufacturer Specific Data(厂商自定义数据,AD Type = 0xFF) 字段中,加入设备的 MAC 地址(6字节,大端序)

广播包格式要求

[Length] [Type=0xFF] [Company ID Low] [Company ID High] [MAC 6字节, 大端序] [其他自定义数据...]

示例

设备 MAC 为 98:A3:16:35:D2:52,对应字节为:

98 A3 16 35 D2 52

厂商数据段示例(Company ID 使用 0x0000 占位,可替换为实际注册 ID):

[Length] FF 00 00 98 A3 16 35 D2 52 [其他数据...]

完整广播包示例(在现有数据基础上增加该字段):

原有数据段保持不变
新增字段: 0A FF 00 00 98 A3 16 35 D2 52

0A = 后续字节长度(10字节:Type 1字节 + Company ID 2字节 + MAC 6字节 + 预留1字节)

字节序说明

MAC 地址按大端序写入,即 98:A3:16:35:D2:52 写为:

98 A3 16 35 D2 52

不要使用小端序(52 D2 35 16 A3 98),以便 App 端直接比对。

App 端解析逻辑

App 收到广播包后,会遍历所有 AD Structure,找到 Type = 0xFF 的字段,从第 3 字节(跳过 Company ID)开始读取 6 字节作为 MAC,与扫码结果比对:

// 解析 Manufacturer Specific Data 中的 MAC
function extractMacFromAdvertData(advertisData: ArrayBuffer): string {
  const bytes = new Uint8Array(advertisData)
  let i = 0
  while (i < bytes.length) {
    const len = bytes[i]
    const type = bytes[i + 1]
    if (type === 0xFF && len >= 8) {
      // 跳过 length(1) + type(1) + companyId(2),取后6字节为MAC
      const mac = Array.from(bytes.slice(i + 4, i + 10))
        .map(b => b.toString(16).padStart(2, '0').toUpperCase())
        .join('')
      return mac  // 返回格式如 "98A31635D252"
    }
    i += len + 1
  }
  return ''
}

比对时将扫码 MAC 98:A3:16:35:D2:52 去掉冒号转大写后与上述结果直接比较。

验证方法

修改固件后,可使用以下工具验证广播包内容:

在 nRF Connect 中找到目标设备,展开 Raw Advertising Data,确认 Manufacturer Specific Data 字段中包含正确的 MAC 字节。

联系人

如有疑问请联系 App 开发团队。