使用Web Bluetooth API读取BGM220-EK4314A温度数据异常求助
核心错误点
- 未开启GATT特征通知:现有代码仅读取了客户端特征配置描述符(CCC)的默认值,未写入开启通知的指令,也没有调用特征的
startNotifications()方法,外设不会主动推送温度更新,绑定的characteristicvaluechanged监听永远不会触发。 - 温度值解析不符合蓝牙规范:根据蓝牙SIG官方定义,Health Thermometer服务的
temperature_measurement特征结构为:首字节(偏移0)是标志位,从偏移1位置开始存储32位IEEE 11073格式的温度值。现有代码直接读取偏移0的8位无符号整数,拿到的只是标志位数值,和实际温度完全无关。 - 服务声明缺失:
optionalServices配置中没有加入健康温度计服务对应的UUID0x1809,部分浏览器环境下会拦截未声明服务的访问请求,导致服务获取失败。
修正步骤
- 在
optionalServices数组中补充健康温度计服务UUID0x1809 - 删除冗余的CCC描述符读取逻辑,在绑定值变化监听后调用
startNotifications()开启特征订阅,该API会自动完成CCC描述符的写入操作,无需手动处理 - 重写温度值解析逻辑,跳过首字节标志位,从偏移1位置读取32位小端序浮点数,即为摄氏度温度值
- 可选:开启通知后主动调用
readValue()获取一次初始温度,无需等第一次通知推送
修正后完整代码
const deviceName = "Thermometer Example"; function isWebBLEAvailable() { if (!navigator.bluetooth) { console.log("Web BLE unavailable"); return false; } console.log("Web BLE available"); return true; } function handleTempChanged(event) { const dataView = event.target.value; // 偏移0为标志位,偏移1开始读32位小端序浮点温度值 const temperature = dataView.getFloat32(1, true); const tempText = `${temperature.toFixed(1)} ℃`; console.log("收到温度更新:", tempText); document.getElementById("target").textContent = `当前温度:${tempText}`; } async function getDeviceInfo() { const $target = document.getElementById("target"); try { console.log("请求蓝牙设备..."); const device = await navigator.bluetooth.requestDevice({ // 补充健康温度计服务UUID到可选服务列表 optionalServices: [0x1800, 0x1801, 0x1809, 0x180a], filters: [{ name: deviceName }, { services: ["health_thermometer"] }], }); console.log("已连接设备:", device.name); const server = await device.gatt.connect(); console.log("GATT连接成功"); const healthThermService = await server.getPrimaryService("health_thermometer"); console.log("获取健康温度计服务成功"); const tempChar = await healthThermService.getCharacteristic("temperature_measurement"); console.log("获取温度测量特征成功"); // 绑定值变化监听 tempChar.addEventListener("characteristicvaluechanged", handleTempChanged); // 开启通知订阅 await tempChar.startNotifications(); console.log("温度通知已开启"); // 读取初始温度值 const initialValue = await tempChar.readValue(); const initialTemp = initialValue.getFloat32(1, true); $target.textContent = `当前温度:${initialTemp.toFixed(1)} ℃`; } catch (error) { console.log("操作出错:", error); $target.textContent = `连接出错:${error.message}`; } } document.querySelector("form").addEventListener("submit", function (event) { event.stopPropagation(); event.preventDefault(); if (isWebBLEAvailable()) { getDeviceInfo(); } });
补充说明
- Web Bluetooth API仅在HTTPS站点或localhost本地调试环境下可用,普通HTTP环境下接口会被浏览器拦截。
- 如果你使用的固件是将温度数据放在BLE广播包中(无需连接即可收到数据),则不需要走上述GATT连接流程,直接调用
navigator.bluetooth.requestLEScan()开启广播扫描,解析广播包中0x1809服务对应的字段即可拿到温度。你所用的Simplicity Studio官方Health Thermometer例程默认采用GATT通知模式推送数据,上述修正代码可以直接使用。
内容的提问来源于stack exchange,提问作者Amal K O
相关产品推荐
相关产品推荐

