我目前正在使用Dart / Flutter BLE插件来更好地了解BLE设备。
插件:
https://pub.dartlang.org/packages/flutter_blue
当我连接到虚拟自行车训练器时,我选择了0x1818服务,然后订阅了0x2A63特性来进行自行车功率测量。
我正在努力使获得的回复列表与以下有关此服务/功能的GATT文档保持一致。此列表中有18个值,但是GATTS列表中只有17个值。而且这些值似乎没有任何意义。
我还尝试将前两个值'52','24'转换为16位二进制数,以查看该值是否与第一个字段的标志对齐,但是结果是下面的值又没有意义。 / p>
0x3418 = 11010000011000
此屏幕截图是我第一次连接到培训师时。
此屏幕截图是当我在自行车上轻轻骑行时
此屏幕截图是当我停止骑自行车但踏板和车轮仍在转动时。
自行车训练器是Cycleops Magnus,它没有Cycle Speed Cadence服务1816,但可以基于功率提供虚拟速度。
我的问题是这个
列表中与GATTS对应的值 特征和奖金问题是,我如何推断速度或 从这项服务中的价值观中选择节奏?
答案 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);
}