# 蓝牙广播包改造需求 ## 背景 当前设备二维码中存储的是设备 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,与扫码结果比对: ```typescript // 解析 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` 去掉冒号转大写后与上述结果直接比较。 ## 验证方法 修改固件后,可使用以下工具验证广播包内容: - **iOS**:[nRF Connect for Mobile](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-mobile) - **Android**:nRF Connect 或 BLE Scanner 在 nRF Connect 中找到目标设备,展开 **Raw Advertising Data**,确认 Manufacturer Specific Data 字段中包含正确的 MAC 字节。 ## 联系人 如有疑问请联系 App 开发团队。