提取 4 位与 2 位蓝牙 HEX 数据,为什么相同的方法会导致错误 [英] Extract 4 bits vs 2Bit of Bluetooth HEX Data, why same method results in error

查看:24
本文介绍了提取 4 位与 2 位蓝牙 HEX 数据,为什么相同的方法会导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是这个 SO (

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

但是,为什么当我在 SO

正在做

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

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

添加说明

解决方案

你说这段代码有问题……但它似乎意外地"起作用了:

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

这会产生 UInt8,但第一个表中的标志字段是 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 {$0.bindMemory(to: UInt32.self)[0]}

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

This is a follow on question from this SO (Extract 4 bits of Bluetooth HEX Data) 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 (Extract 4 bits of Bluetooth HEX Data) does not.

To decode Cycling Power Data, the first 2 bits are the flags and it's used to determine what capabilities the power meter provides.

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]

This results in the flags bit being concatenate from the first 2 bits. After which I used the flags bit and masked it to get the relevant bit position.

eg: to get power balance, I do (flags & 0x01 > 0)

This method works and I'm a happy camper.

However, Why is it that when I used this same method on SO Extract 4 bits of Bluetooth HEX Data it does not work? This is decoding Bluetooth FTMS Data (different from above)

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}

Based on the specs, the returned data has 2 characteristics, each of them 4 octet long.

doing

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

to join the first 4bytes results in an wrong output to start the decoding.

edit: Added clarification

解决方案

There is a problem with this code that you say works... but it seems to work "accidentally":

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

This results in a UInt8, but the flags field in the first table is 16 bits. Note that byteArray[1] << 8 always evaluates to 0, because you are shifting all of the bits of the byte out of the byte. It appeared to work because the only bit you were interested in was in byteArray[0].

So you need it convert it to 16-bit (or larger) first and then shift it:

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

Now flags is UInt16

Similarly when you do 4 bytes, you need them to be 32-bit values, before you shift. So

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

but since that's just reading a 32-bit value from a sequence of bytes that are in little endian byte order, and all current Apple devices (and the vast majority of all other modern computers) are little endian machines, here is an easier way:

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

In summary, in both cases, you had been only preserving byte 0 in your shift-add, because the other shifts all evaluated to 0 due to shifting the bits completely out of the byte. It just so happened that in the first case byte[0] contained the information you needed. In general, it's necessary to first promote the value to the size you need for the result, and then shift it.

这篇关于提取 4 位与 2 位蓝牙 HEX 数据,为什么相同的方法会导致错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆