提取 4 位与 2 位蓝牙 HEX 数据,为什么相同的方法会导致错误

Extract 4 bits vs 2Bit of Bluetooth HEX Data, why same method results in error

这是来自这个 SO () which an answer has been accepted. I wanna understand more why the difference between what I was using; example below; (which works) when applied to the SO () 的后续问题。

要解码骑行功率数据,前 2 位是标志,用于确定功率计提供的功能。

guard let characteristicData = characteristic.value else { return -1 }
var byteArray = [UInt8](characteristicData)
// This is the output from the Sensor (In Decimal and Hex)
// DEC [35,  0, 25,  0, 96, 44, 0, 33, 229] Hex:{length = 9, bytes = 0x23001900602c0021e5} FirstByte:100011    

/// First 2 Bits is Flags
let flags = byteArray[1]<<8 + byteArray[0]

这导致 flags 位与前 2 位连接。之后我使用 flags 位并将其屏蔽以获得相关位位置。

例如:为了获得权力平衡,我 (flags & 0x01 > 0)

这个方法有效,我是一个快乐的露营者。

但是,为什么当我在 SO 上使用同样的方法时它不起作用?这是解码蓝牙 FTMS 数据(与上面不同)

guard let characteristicData = characteristic.value else { return -1 }
let byteArray = [UInt8](characteristicData)
let nsdataStr = NSData.init(data: (characteristic.value)!)

print("pwrFTMS 2ACC Feature  Array:[\(byteArray.count)]\(byteArray) Hex:\(nsdataStr)")

PwrFTMS 2ACC Feature Array:[8][2, 64, 0, 0, 8, 32, 0, 0] Hex:{length = 8, bytes = 0x0240000008200000}

根据规范,返回的数据有 2 个特征,每个特征长 4 个八位字节。

正在做

byteArray[3]<<24 + byteArray[2]<<16 + byteArray[1]<<8 + byteArray[0]

加入前 4 个字节会导致错误输出以开始解码。

编辑:添加了说明

您说有效的代码有问题...但它似乎“意外”有效:

let flags = byteArray[1]<<8 + byteArray[0]

这导致 UInt8,但第一个 table 中的标志字段是 16 位。请注意,byteArray[1] << 8 始终计算为 0,因为您正在将字节的所有位移出字节。它似乎有效,因为您唯一感兴趣的是 byteArray[0].

所以你需要先把它转换成16位(或更大),然后再移位:

let flags = (UInt16(byteArray[1]) << 8) + UInt16(byteArray[0])

现在 flagsUInt16

类似地,当你做 4 个字节时,你需要它们是 32 位值,然后再移位。所以

let flags = UInt32(byteArray[3]) << 24 
    + UInt32(byteArray[2]) << 16
    + UInt32(byteArray[1]) << 8
    + UInt32(byteArray[0])

但由于这只是从小端字节顺序的字节序列中读取 32 位值,并且所有当前的 Apple 设备(以及绝大多数其他现代计算机)都是小端机器,这里是一种更简单的方法:

let flags = byteArray.withUnsafeBytes {
    [=13=].bindMemory(to: UInt32.self)[0]
}

总而言之,在这两种情况下,您只在移位加法中保留了字节 0,因为由于将位完全移出字节,其他移位全部评估为 0。碰巧在第一种情况下 byte[0] 包含了你需要的信息。一般来说,需要先将值提升到结果需要的大小,然后再平移。