提问人:3366784 提问时间:8/1/2023 最后编辑:3366784 更新时间:8/2/2023 访问量:56
为什么记录的蓝牙 Unit8 值被读取为 Int16?
Why is documented Bluetooth Unit8 value being read as a Int16?
问:
我试过什么?
我通读了上述文档的先前公开版本。GATT_Specification_Supplement_v10.pdf
我查看了堆栈溢出问题和第三方蓝牙库。
对于GATT_Specification_Supplement_v10.pdf阻力水平的特征是 a,但在实践中它是 .
这意味着它需要两个八位字节或两个类型的数组值来表示阻力水平。3.125 Indoor Bike Data
UInt8
Int16
UInt8
此外,在浏览堆栈溢出时,我发现此第三方文档将值记录为 .SInt16
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/ibd-0000001051005923
我还查看了一个第三方库,该库将此值解析为 .https://github.com/FitnessKit/BluetoothMessageProtocolInt16
// File: CharacteristicIndoorBikeData.swift
// Line: 172
var resistanceLevel: Int16?
if flags.contains(.resistanceLevelPresent) {
resistanceLevel = decoder.decodeInt16(data)
}
你以为我误会了什么吗? 是文档的问题吗?我怀疑情况会是这样。
原始数据
以下是要求的原始数据。
// Raw Byte Array Data - represented as decimal integers
▿ 19 elements
- 0 : 116
- 1 : 3
- 2 : 0
- 3 : 0
- 4 : 62
- 5 : 0
- 6 : 0
- 7 : 0
- 8 : 0
- 9 : 16
- 10 : 0
- 11 : 0
- 12 : 0
- 13 : 0
- 14 : 0
- 15 : 0
- 16 : 0
- 17 : 0
- 18 : 0
// Here is data I generated while actually riding the bike for a few seconds.
// resistance level in bike was updated during the ride, from 17 to 22.
[116, 3, 0, 0, 96, 0, 163, 0, 0, 19, 0, 0, 0, 2, 0, 0, 0, 0, 0]
[116, 3, 178, 12, 176, 0, 171, 0, 0, 17, 0, 162, 0, 3, 0, 0, 0, 0, 0]
[116, 3, 66, 14, 206, 0, 181, 0, 0, 17, 0, 219, 0, 3, 0, 0, 0, 0, 0]
[116, 3, 126, 14, 226, 0, 192, 0, 0, 16, 0, 229, 0, 3, 0, 0, 0, 0, 0]
[116, 3, 146, 14, 224, 0, 202, 0, 0, 16, 0, 233, 0, 3, 0, 0, 0, 0, 0]
[116, 3, 142, 13, 184, 0, 212, 0, 0, 16, 0, 192, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 78, 12, 154, 0, 221, 0, 0, 18, 0, 150, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 170, 10, 120, 0, 229, 0, 0, 18, 0, 103, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 126, 9, 100, 0, 236, 0, 0, 18, 0, 77, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 152, 8, 84, 0, 236, 0, 0, 19, 0, 57, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 98, 7, 60, 0, 242, 0, 0, 21, 0, 42, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 234, 6, 50, 0, 247, 0, 0, 21, 0, 31, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 114, 6, 40, 0, 252, 0, 0, 21, 0, 22, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 114, 6, 40, 0, 0, 1, 0, 21, 0, 22, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 100, 5, 28, 0, 4, 1, 0, 22, 0, 12, 0, 4, 0, 0, 0, 0, 0]
[116, 3, 100, 5, 28, 0, 8, 1, 0, 22, 0, 12, 0, 4, 0, 0, 0, 0, 0]
// For convenience here is the flags field represented as a 16bit binary number
1101110100
答:
你测试过实际设备吗?我绝对希望文档中出现错误。这些年来,我发现了几个。我越深入研究这个特征,它似乎就越混乱。
他们列出了 d=1,这意味着电阻的分辨率为 10 个单位,这毫无意义(这将表示 0、10、20、30 的值,...高达 2550)。我敢肯定他们的意思是 d=-1(十分之一单位)。请参阅关贸总协定补充部分 2.3.2 “标量值”,了解我所说的内容。
测试计划将“目标阻力水平已更改”通知描述为有效载荷为“新目标值(UINT8,无单位,分辨率为 0.1),例如 5.0”,这与我的 d=-1 信念相符。
但测试计划还说,支持的阻力位范围应该是 6 个八位字节(那里有 3 个值,所以这将是 int16)。而“设定目标阻力位程序”也需要 sint16。
但是,如果您阅读 FTMS 规范,“设置目标阻力水平”声称采用“UINT8,无单位,分辨率为 0.1”。
但是旧的(不再受支持的)xml 文档将其列为未缩放的 sint16:
<Field name="Resistance Level">
<InformativeText>Unitless with a resolution of
1</InformativeText>
<Requirement>C6</Requirement>
<Format>sint16</Format>
<Unit>org.bluetooth.unit.unitless</Unit>
</Field>
真是一团糟。
IMO(即按 0.1 缩放)是唯一对该值真正有意义的缩放。sint16 浪费了宝贵的字节(规范在第 4.19 节中讨论了这个问题),甚至不处理常见的小数级别。并签了名?有负阻力吗?我不知道为什么 sint16 偷偷溜进去。我的猜测是,这在某个时候是一个剪切和粘贴错误,因为附近的几个值是 sint16。但也许在某个时候是故意的。uint8,M=1,d=-1,b=0
也就是说,鉴于规范和测试用例之间的模糊性,我的期望是真实世界的设备可以同时做这两件事,如果你的代码需要与许多设备一起工作,你需要查看长度并决定该怎么做。我还敢打赌,有些人发送分辨率为 1 的 uint8,而另一些人发送分辨率为 0.1 的 uint8,因此您可能需要查看值的大小才能确定它可能意味着什么。人们总是忘记比例因子......
(另一方面,华为的库只支持 sint16 这一事实可能意味着 sint16 在市场上非常普遍。或者这可能意味着华为的库不适用于所有产品。那是一回事。
欢迎来到蓝牙开发。不要以为这些文档代表了所有真实产品所做的事情,甚至不是 100% 自洽的。老实说,文档并不可怕,但肯定有错误,我认为这个规范的这一部分是一个错误。唯一的问题是,您需要使用哪些产品对此做了哪些工作。
评论
"Have you tested actual devices?"
是的,我在 Schwinn IC 4 室内自行车上测试了这一点。我还使用第三方库进行了测试,看看这是否是我这边的问题,他们实际上将该有问题的值解析为有符号的 16 位整数。 嗯,这实际上非常有用,因为我认为蓝牙文档是完美的。但这是我的一个假设。"I would absolutely expect errors in the documentation. I've found several over the years. The more I dig into this characteristic, the more of a mess it seems to be."
评论