我正在尝试从iOS上的Bluetooth 4.0 LE刻度读取值。如何将以NSData形式接收的Bluetooth特性测量值转换为专用的Swift对象?
作为规范,我知道……
0至12位→重量(0至5000 g)
位15 →正负重量值
func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
let value:NSData = characteristic.value
let weight:Double = … ?
let negative:Bool = … ?
另一则信息–查看
value.length
看来我总是从设备中获取1或2个字节(?)的数据。但是我仍然不确定如何提取所需的数据/值。我将不胜感激任何建议。
到目前为止,这是可行的……
var bin16:UInt16 = 0
characteristic.value.getBytes(&bin16, range: NSRange(location: 0,length: 1))
println("Bytes \(characteristic.value.bytes) Length \(characteristic.value.length)")
println("Value \(bin16)")
–这样,我设法获得一些体重读数。除非该值大于255或负数,否则它似乎起作用。这里有些例子:
75克
字节0x1655e458长度1
值(value)75
367克
字节0x1765cbc8长度2
值(value)161
-6克
字节0x17670f18长度2
值(value)32
同样,这在两次之间会更频繁地传输-在这种情况下,它代表不了160克。也许某种错误代码?
字节0x146528b8长度2
值(value)160
最佳答案
看起来有两个问题。
从NSData提取Swift数据类型
看上面的问题,您的数据在16位二进制字符串中。因此,我们的首要任务是将16位二进制字符串提取为数据类型。我认为
UInt16
对此最合适。func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
var bin16:UInt16 = 0
var wrapin: NSNumber = NSNumber(unsignedShort: 0)
characteristic.value.getBytes(&wrapin, range: NSRange(location: 0,length: 2))
bin16 = wrapin.unsignedShortValue
从二进制字符串中提取数据
此时,
bin16
具有一个16位二进制字符串。根据您的描述,重量数据存储在第0至12位,符号位为第16位。以下是如何使用按位运算符&和>>提取此数据的示例。在Swift中查看快速语言guid以获得更多有关二进制运算符的信息。// The actual data
let value : UInt16 = 0b0010_1010_0000_0000 // 2560g & positive sign
let weight : uint16 = value & 0b0001_1111_1111_1111 // Extract weight
let sign : UInt16 = value >> 15 // Posative or negative
请注意,我做了以下假设:
更新-包括游乐场内容
// Important Note: Reading & Writing to NSData using the native UInt16 does
// not work correctly. Something happens and it mangles the data. To get
// around this in xcode beta 5 you must wrap your data in an NSNumber.
import UIKit
// Build an NSData type
// Bit 0 through 12 --> Weight in g
// Bit 13 & 14 --> not read or used in example (discarded)
// Bit 15 --> Sign-bit
// The value below:
// Weight: (bit 0-12) : 2560G
// Sign: Positive
let rawvalue : UInt16 = 0b0010_1010_0000_0000
// Build NSData payload
var wrapout : NSNumber = NSNumber(unsignedShort: rawvalue)
var payload : NSData = NSData(bytes: &wrapout, length: 2)
// Extracting data
var finalWeight = 0
if payload.length >= 2 {
var wrapin : NSNumber = NSNumber(unsignedShort: 0)
var bstring : UInt16 = 0
payload.getBytes(&wrapin, range: NSRange(location: 0, length: 2))
bstring = wrapin.unsignedShortValue
let weight : UInt16 = bstring & 0b0001_1111_1111_1111
let valsign: UInt16 = (bstring & 0b1000_0000_0000_0000) >> 15
if valsign == 0 {
finalWeight = Int(weight)
} else {
finalWeight = -1 * Int(weight)
}
}
println("\(finalWeight)")