如何用Web Bluetooth解析室内单车数据?解析原理求教
室内单车BLE数据解析疑问
问题背景
我通过nRF Connect for Mobile能获取室内单车的有效数据:
- 瞬时速度(单位:km/h)
- 瞬时踏频(单位:/min)
- 阻力等级(无单位)
- 瞬时功率(单位:W)
但用Web Bluetooth获取数据时得到的是DataView格式,不知道怎么解析成可读数值。之前参考Stack Overflow回答加随机尝试,用这段代码拿到了阻力等级:
dataView.getInt16(6, true)
但不清楚为什么用偏移量6和小端序(true)能得到正确结果。
随机试偏移量也拿不到瞬时速度、踏频、功率的有效数值,求这三个数值的解析方法。
下面是获取DataView的代码:
const FITNESS_MACHINE_SERVICE_UUID = "00001826-0000-1000-8000-00805f9b34fb"; const INDOOR_BIKE_DATA_UUID = "00002ad2-0000-1000-8000-00805f9b34fb"; const handleClick = async () => { const indoorBikeDevice = await navigator.bluetooth.requestDevice({ filters: [{ name: "MG03" }], optionalServices: [FITNESS_MACHINE_SERVICE_UUID], }); if (!indoorBikeDevice.gatt) return; const server = await indoorBikeDevice.gatt.connect(); const service = await server.getPrimaryService(FITNESS_MACHINE_SERVICE_UUID); const characteristic = await service.getCharacteristic(INDOOR_BIKE_DATA_UUID); characteristic.addEventListener( "characteristicvaluechanged", async (event) => { const dataView = (event.target as any).value as DataView; console.log("dataView: ", dataView); const resistanceLevel = dataView.getInt16(6, true); console.log("resistanceLevel: ", resistanceLevel); } ); characteristic.startNotifications(); };
后续进展及新疑问
查看回复后,我通过这段代码获取到了flags:
// GATT_Specification_Supplement_v8.pdf // 3.124.1 Flags field: The bits of this field are defined below. for (let i = 0; i < 16; i++) { console.log("flags[" + i + "] = " + !!((flags >>> i) & 1)); }
控制台输出:
// flags[0] = false // flags[1] = false // flags[2] = true (Instantaneous Cadence present) // flags[3] = false // flags[4] = false // flags[5] = true (Resistance Level present) // flags[6] = true (Instantaneous Power present) // flags[7] = false // flags[8] = false // flags[9] = false // flags[10] = false // flags[11] = false // flags[12] = false // ...
从flags可知设备支持瞬时踏频、阻力等级、瞬时功率。我盲试出了匹配nRF Connect输出的解析代码:
characteristic.addEventListener( "characteristicvaluechanged", async (event) => { const dataView = (event.target as any).value as DataView; const instantaneousCadence = dataView.getUint16(3, true) / 512; const resistanceLevel = dataView.getUint8(6); const instantaneousPower = dataView.getInt16(8, true); console.log( [instantaneousCadence, resistanceLevel, instantaneousPower].join("|") ); } );
但还是不懂这段代码的原理:
- 瞬时踏频为什么用偏移量3,还要除以512才能得到转/分钟?
- 阻力等级和功率的偏移量6、8是怎么确定的?
求这些问题的解答。
内容的提问来源于stack exchange,提问作者sean0923
相关产品推荐
相关产品推荐

