Web Bluetooth API获取BLE广播厂商与服务数据的问题排查与解决
Web Bluetooth API无法获取BLE广播的厂商数据/服务数据问题排查与解决
问题描述
我尝试通过BLE广播传输数据,发送端用原生APP能正常发送,但接收端需基于Web应用实现。已知Web Bluetooth API在部分浏览器支持,扫描监听BLE广播需手动启用。目前已能监听广播,获取设备名称、信号强度等数据,但无法获取自定义的厂商数据(Manufacturer Data)与服务数据(Service Data)。
使用以下脚本尝试获取数据,但manufacturerData始终为空:
device.addEventListener('advertisementreceived', event => { event.manufacturerData.forEach((dataView, companyId) => { const bytes = new Uint8Array(dataView.buffer); const ascii = new TextDecoder('ascii').decode(bytes); log(`Company ID: 0x${companyId.toString(16)}`); log(`Message: ${ascii}`); }); }); await device.watchAdvertisements();
原生Android APP扫描广播时可正常获取这些属性,请问无法通过浏览器获取的原因是什么?能否提供基于Web应用的解决方案?
无法获取数据的核心原因
- 浏览器隐私过滤机制:为保护用户隐私,Web Bluetooth API默认会过滤广播中的厂商数据和服务数据,除非在请求设备时明确声明需要访问对应的厂商ID或服务UUID。
- 连接状态限制:
watchAdvertisements()在设备未连接时,部分浏览器(如Chrome)仅允许读取基础广播信息,无法获取自定义的厂商/服务数据;只有设备处于连接状态,才能完整读取这类数据。 - 厂商ID规范性问题:若发送端使用的是蓝牙SIG未分配的自定义厂商ID,浏览器可能直接忽略该部分数据。
解决方案
1. 请求设备时明确声明厂商ID或服务UUID
调用navigator.bluetooth.requestDevice()时,必须通过filters字段指定目标厂商ID或服务UUID,让浏览器允许访问对应广播数据。示例代码:
// 替换为你的实际厂商ID(如0x0001)或服务UUID const device = await navigator.bluetooth.requestDevice({ filters: [{ manufacturerData: [{ companyId: 0x0001 }] // 若要获取服务数据,可替换为:serviceData: [{ uuid: '0000ffe0-0000-1000-8000-00805f9b34fb' }] }], acceptAllDevices: false, optionalServices: ['battery_service'] // 必须声明,可填需要的服务UUID或留空 }); device.addEventListener('advertisementreceived', event => { // 处理厂商数据 event.manufacturerData.forEach((dataView, companyId) => { const bytes = new Uint8Array(dataView.buffer); const ascii = new TextDecoder('ascii').decode(bytes); console.log(`Company ID: 0x${companyId.toString(16)}`); console.log(`Message: ${ascii}`); }); // 处理服务数据(若有) event.serviceData.forEach((dataView, serviceUuid) => { const bytes = new Uint8Array(dataView.buffer); const ascii = new TextDecoder('ascii').decode(bytes); console.log(`Service UUID: ${serviceUuid}`); console.log(`Service Data: ${ascii}`); }); }); await device.watchAdvertisements();
2. 先连接设备再监听广播
若上述方法无效,尝试先建立GATT连接,再监听广播数据:
const device = await navigator.bluetooth.requestDevice({ filters: [{ manufacturerData: [{ companyId: 0x0001 }] }], optionalServices: ['0000ffe0-0000-1000-8000-00805f9b34fb'] // 替换为你的服务UUID }); // 先建立GATT连接 const server = await device.gatt.connect(); // 再监听广播事件 device.addEventListener('advertisementreceived', event => { console.log('Manufacturer Data:', event.manufacturerData); console.log('Service Data:', event.serviceData); }); await device.watchAdvertisements();
3. 验证厂商ID的合法性
确保发送端使用的厂商ID是蓝牙SIG分配的合法16位ID,若需使用自定义标识,建议将数据嵌入服务数据,并搭配标准服务UUID传输。
4. 确认浏览器兼容性
目前仅Chrome(桌面/Android)、Edge等主流浏览器支持Web Bluetooth API的广播数据读取功能,Safari(含iOS)暂未完全支持该特性。
内容的提问来源于stack exchange,提问作者LAZARO QUEIROZ DO NASCIMENTO
相关产品推荐
相关产品推荐

