ios - 提取 4 位与 2 位蓝牙 HEX 数据,为什么相同的方法会导致错误
问题描述
这是来自此 SO(提取 4 位蓝牙 HEX 数据)的后续问题,答案已被接受。我想更多地了解为什么我使用的是什么;下面的例子;(有效)当应用于 SO(提取 4 位蓝牙 HEX 数据)时无效。
要解码循环功率数据,前 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 Extract 4 bits of Bluetooth HEX Data上使用相同的方法时它不起作用?这是解码蓝牙 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]
这导致 a UInt8
,但第一个表中的标志字段是 16 位。请注意,byteArray[1] << 8
始终计算为0
,因为您将字节的所有位移出字节。它似乎有效,因为您唯一感兴趣的部分是byteArray[0]
.
因此,您需要先将其转换为 16 位(或更大),然后再对其进行转换:
let flags = (UInt16(byteArray[1]) << 8) + UInt16(byteArray[0])
现在flags
是UInt16
同样,当您执行 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] 包含您需要的信息。一般来说,有必要首先将值提升到结果所需的大小,然后再对其进行移位。
推荐阅读
- c++ - 为什么我的有线球体在平移和改变摄像机角度时会变成椭球体?
- python - 用于 WHMCS 的 base64 编码和序列化数组的 Python 数组
- vue.js - 单击一个缺席按钮后,将选择所有其他缺席按钮。我只想一次只选择一个不存在的按钮
- django - 为什么我在 djangorestframework-jwt 中得到这个输出
- angular-material - 在菜单中选择
- react-native - 如何在本机反应中进行反向地理编码
- json - 在使用 swift encodable 编码数据时,我们如何不将 json 字符串化?
- r - 如何将第一行的字符串与数据框中的每一行进行比较并计算 R 中不匹配的数量?
- python - 如何让您的 Discord 机器人说出具体内容,然后删除上一条消息
- xamarin - Xamarin 表单应用无法部署到 Android 10 真机