You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:02:56