了解用于循环功率测量的BLE特性值0x2A63

时间:2019-01-29 18:33:50

标签: bluetooth dart flutter bluetooth-lowenergy

我目前正在使用Dart / Flutter BLE插件来更好地了解BLE设备。

插件:

https://pub.dartlang.org/packages/flutter_blue

当我连接到虚拟自行车训练器时,我选择了0x1818服务,然后订阅了0x2A63特性来进行自行车功率测量。

我正在努力使获得的回复列表与以下有关此服务/功能的GATT文档保持一致。此列表中有18个值,但是GATTS列表中只有17个值。而且这些值似乎没有任何意义。

我还尝试将前两个值'52','24'转换为16位二进制数,以查看该值是否与第一个字段的标志对齐,但是结果是下面的值又没有意义。 / p>

0x3418 = 11010000011000

https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.cycling_power_measurement.xml

此屏幕截图是我第一次连接到培训师时。

enter image description here

此屏幕截图是当我在自行车上轻轻骑行时

enter image description here

此屏幕截图是当我停止骑自行车但踏板和车轮仍在转动时。

enter image description here

自行车训练器是Cycleops Magnus,它没有Cycle Speed Cadence服务1816,但可以基于功率提供虚拟速度。

  

我的问题是这个

     

列表中与GATTS对应的值   特征和奖金问题是,我如何推断速度或   从这项服务中的价值观中选择节奏?

1 个答案:

答案 0 :(得分:2)

基于Bluetooth GATT规范的第3.55节:

DEC - [52,24,40,0,58,29,59,0,0,0,107,136,23, 0,214, 81, 1,0]
BIT -   0  1  2 3  4  5  6 7 8 9  10  11 12 13  14  15 16 17 
Flag field = 24,52 (bit0 and bit1)

2452 = 00001001 10010100

第3.55.2.1节 对应的(1)等于

- bit2  = Accumulated Torque Present 
- bit4  = Wheel Revolution Data Present
- bit7  = Extreme Torque Magnitudes Present
- bit8  = Extreme Angles Present
- bit11 = Accumulated Energy Present

然后从3.55.2节开始,根据标志向下浏览位列表: 瞬时功率为bit2(40)和bit3(0)

(Dec) 0040 == 00000000 00101000 == 40w

要解密其余的位,我们必须参考flags字段,因为flags字段和即时功率之后的其余位必须取决于flags字段说明训练员支持的内容。

基于flags字段的bit2,其中指出“存在累计扭矩”( 如果“标志”字段的位2设置为1,则显示)。因此,接下来的2位表示累积扭矩

Dec (2958)

然后,下一个数据将基于标志字段的第4位-车轮转速数据存在(如果标志字段的第4位设置为1,则存在)。这是车轮速度,一旦您考虑了车轮周长,它将转化为速度。对于Wheel Rev Data,它由接下来的6位表示。

Cumulative Wheel Revolutions - 4 bits
Last Wheel Event Time - 2 bits

就像您提到的那样,该培训师不提供脚踏圈速服务,因此这就是为什么您看不到flags字段(第5位)为1的原因。因此,您无法从此数据集推断脚踏圈速。

对于“车轮速度”,您将根据“累计车轮转速”和“最后一个车轮事件时间”从6位中解码数据。当您使用flutter时,我无法为您提供有关如何解码6位代码的代码,并且我对flutter语言没有任何经验。 (我使用的是Swift),但可以从GoldenCheetah看一下这段代码并进行相应的转换。

BT40Device::getWheelRpm(QDataStream& ds)
{
    quint32 wheelrevs;
    quint16 wheeltime;
    ds >> wheelrevs;
    ds >> wheeltime;

    double rpm = 0.0;

    if(!prevWheelStaleness) {
        quint16 time = wheeltime - prevWheelTime;
        quint32 revs = wheelrevs - prevWheelRevs;
        // Power sensor uses 1/2048 second time base and CSC sensor 1/1024
        if (time) rpm = (has_power ? 2048 : 1024)*60*revs / double(time);
    }
    else prevWheelStaleness = false;

    prevWheelRevs = wheelrevs;
    prevWheelTime = wheeltime;
    dynamic_cast<BT40Controller*>(parent)->setWheelRpm(rpm);
}