我正在尝试从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中提取二进制数据为快速数据类型
  • 如何从二进制字符串
  • 中提取有用的数据

    从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
    

    请注意,我做了以下假设:
  • 您的二进制字符串是LSB
  • 您的二进制字符串只有16位长。如果不是这种情况,则应该使用&运算符而不是>>来提取符号。

  • 更新-包括游乐场内容
    // 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)")
    

    10-07 19:23
    查看更多