这是我为 ESP32 板编写 BLE FTMS 服务的第一个方法。老实说,我并没有真正的经验,这是我的第一个 C++ 应用程序。我成功创建了 FTMS 服务并将数据发送到培训应用程序,例如KinoMap 或类似的。我的问题是我只能发送不超过 20 字节限制的数据。
我在规范中读到,我必须将其分成 2 个块,并向第一个块添加“更多数据位”,以便能够发送超过 20 个字节,并确保客户端知道第二个数据块可用。这就是我挣扎的地方。
我可能没有足够的经验来了解问题所在,而且我对 BLE FTMS 规范了解得越多,我的困惑就越多;)我没有找到描述如何添加这个“更多数据位”以及它的外观......我尝试使用 0x01 但我不知道这是否是添加它的正确方法。
这样它就可以使用最大 20 字节:
...
byte features[] = {0x07,0x52,0x00,0x00};
void transmitFTMS(double rpm, double avgRpm, double cadence, double avgCadence, double kph, double avgKph, double power, double avgPower,
double runningDistance, double runningCalories, unsigned long elapsedTime)
{
uint16_t transmittedKph = (uint16_t) (kph * 100); //(0.01 resolution)
uint16_t transmittedTime = (uint16_t) (elapsedTime / 1000);//(1.0 resolution)
uint16_t transmittedAvgKph = (uint16_t) (avgKph * 100); //(0.01 resolution)
uint16_t transmittedRpm = (uint16_t) (rpm * 2); //(0.5 resolution)
uint16_t transmittedAvgRpm = (uint16_t) (avgRpm * 2); //(0.1 resolution)
uint16_t transmittedCadence = (uint16_t) (cadence * 2);
uint16_t transmittedAvgCadence = (uint16_t) (avgCadence * 2);
uint16_t transmittedPower = (uint16_t) (power * 2); //(1.0 resolution)
uint16_t transmittedAvgPower = (uint16_t) (avgPower * 2); //(1.0 resolution)
uint32_t transmittedDistance = (uint32_t) (runningDistance * 1000);// runningDistance in km, need m
uint16_t transmittedTotalCal = (uint16_t) (runningCalories * 10); //(1.0 resolution)
uint16_t transmittedCalHr = (uint16_t) (runningCalories * 60 * 60 / elapsedTime);//(1.0 resolution)
uint8_t transmittedCalMin = (uint8_t) (runningCalories * 60 / elapsedTime); //(1.0 resolution)
bool disconnecting = !deviceConnected && oldDeviceConnected;
bool connecting = deviceConnected && !oldDeviceConnected;
byte bikeData[20]={0x56,0x09,
(uint8_t)transmittedKph, (uint8_t)(transmittedKph >> 8),
(uint8_t)transmittedAvgKph, (uint8_t)(transmittedAvgKph >> 8),
(uint8_t)transmittedCadence, (uint8_t)(transmittedCadence >> 8),
(uint8_t)transmittedDistance, (uint8_t)(transmittedDistance >> 8),
(uint8_t)(transmittedDistance >> 16),
(uint8_t)transmittedPower, (uint8_t)(transmittedPower >> 8),
(uint8_t)transmittedTotalCal, (uint8_t)(transmittedTotalCal >> 8),
(uint8_t)transmittedCalHr, (uint8_t)(transmittedCalHr >> 8),
transmittedCalMin,
(uint8_t)transmittedTime, (uint8_t)(transmittedTime >> 8)
};
if (deviceConnected)
{
indoorBikeDataCharacteristic->setValue((uint8_t *)&bikeData, 20);
indoorBikeDataCharacteristic->notify();
}
...
我尝试按如下方式更改此设置以提交超过 20 个字节:
...
byte bikeData1[20]={0x56,0x09,
(uint8_t)transmittedKph, (uint8_t)(transmittedKph >> 8),
(uint8_t)transmittedAvgKph, (uint8_t)(transmittedAvgKph >> 8),
(uint8_t)transmittedCadence, (uint8_t)(transmittedCadence >> 8),
(uint8_t)transmittedRpm, (uint8_t)(transmittedRpm >> 8),
(uint8_t)transmittedAvgRpm, (uint8_t)(transmittedAvgRpm >> 8),
(uint8_t)transmittedAvgCadence, (uint8_t)(transmittedAvgCadence >> 8),
(uint8_t)transmittedDistance, (uint8_t)(transmittedDistance >> 8),
(uint8_t)(transmittedDistance >> 16),
(uint8_t)transmittedPower, (uint8_t)(transmittedPower >> 8),
0x01
};
byte bikeData2[9]={
(uint8_t)transmittedAvgPower, (uint8_t)(transmittedAvgPower >> 8),
(uint8_t)transmittedTotalCal, (uint8_t)(transmittedTotalCal >> 8),
(uint8_t)transmittedCalHr, (uint8_t)(transmittedCalHr >> 8),
transmittedCalMin,
(uint8_t)transmittedTime, (uint8_t)(transmittedTime >> 8)
};
if (deviceConnected)
{
indoorBikeDataCharacteristic->setValue((uint8_t *)&bikeData1, 20);
indoorBikeDataCharacteristic->notify();
indoorBikeDataCharacteristic->setValue((uint8_t *)&bikeData2, 9);
indoorBikeDataCharacteristic->notify();
}
...
但是客户端应用程序无法处理提供的数据,我不知道失败的原因。
我希望有人能给我指出正确的方向,因为过去三周我一直在研究这个问题,但运气不佳。我还尝试更改提交数据的顺序或每个块中提交的数据,但我所做的所有尝试都无法使其按预期工作。
我不知道如何调试这个。
遵循 FTMS 规范,室内自行车数据在 4.9 中定义。在标志字段中,您传递 0x56、0x09,其小端格式为:
100101010110
根据4.9.1.1标志字段,这表明您正在发送:
您的代码发送:
// Instantaneous Speed (because More Data == 0)
(uint8_t)transmittedKph, (uint8_t)(transmittedKph >> 8),
// Average Speed
(uint8_t)transmittedAvgKph, (uint8_t)(transmittedAvgKph >> 8),
// Instantaneous Cadence
(uint8_t)transmittedCadence, (uint8_t)(transmittedCadence >> 8),
// Total Distance
(uint8_t)transmittedDistance, (uint8_t)(transmittedDistance >> 8), (uint8_t)(transmittedDistance >> 16),
// Instantaneous Power
(uint8_t)transmittedPower, (uint8_t)(transmittedPower >> 8),
// Expended Energy (Total Energy, Energy per Hour, Energy per Minute)
(uint8_t)transmittedTotalCal, (uint8_t)(transmittedTotalCal >> 8),
(uint8_t)transmittedCalHr, (uint8_t)(transmittedCalHr >> 8),
transmittedCalMin,
// Elapsed Time
(uint8_t)transmittedTime, (uint8_t)(transmittedTime >> 8)
到目前为止,一切都很好。你发送你所说的发送。
然后在你的第二批中,你似乎添加了一堆字段,但你没有更新你的标志,所以我不太确定它们的含义。特别是这些
Rpm
字段看起来就像只是节奏。所以我不确定你的意思是什么,但如果你想包括平均节奏,你需要打开它。但经过的时间不适合,所以你需要删除它。
那就是这样的。 (删除 Rpm 字段,因为我不知道它们是什么。)
// 0x150E; adds Avg Cadence, removes elapsed time
// 0001 0101 1110
byte bikeData[]={0x0E,0x15,
(uint8_t)transmittedKph, (uint8_t)(transmittedKph >> 8),
(uint8_t)transmittedAvgKph, (uint8_t)(transmittedAvgKph >> 8),
(uint8_t)transmittedCadence, (uint8_t)(transmittedCadence >> 8),
// Add Average Cadence
(uint8_t)transmittedAvgCadence, (uint8_t)(transmittedAvgCadence >> 8),
(uint8_t)transmittedDistance, (uint8_t)(transmittedDistance >> 8), (uint8_t)(transmittedDistance >> 16),
(uint8_t)transmittedPower, (uint8_t)(transmittedPower >> 8),
(uint8_t)transmittedTotalCal, (uint8_t)(transmittedTotalCal >> 8),
(uint8_t)transmittedCalHr, (uint8_t)(transmittedCalHr >> 8),
transmittedCalMin
};
现在您需要发送“更多数据”。这意味着在标志中设置位 0,并且不发送瞬时速度。
// Flags: 0x4001, 0100 0000 0000 0001
byte bikeData2[]={0x01, 0x40
(uint8_t)transmittedAvgPower, (uint8_t)(transmittedAvgPower >> 8),
(uint8_t)transmittedTime, (uint8_t)(transmittedTime >> 8)
};
这可能很接近。关键点是您的标志必须描述数据包中的内容,数据包不能超过 20 个字节,如果您想发送不包括瞬时速度的第二个数据包,请设置位 0(“更多数据”) .