2017-02-09 889 views
0

我有一个TI传感器标签作为外设,以kCBAdvDataManufacturerData的形式广播BLE数据。我想从iOS中的这些数据中提取不同的值。从Swift提取kCBAdvDataManufacturerData的数据

我执行斯威夫特如下:

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){  
    for (index, foundPeripheral) in peripherals.enumerated(){ 
     if foundPeripheral.peripheral?.identifier == peripheral.identifier{ 
      peripherals[index].lastRSSI = RSSI 
      print("AdvertisementData:\(advertisementData)") 
      return 

     } 
    } 

    let isConnectable = advertisementData["kCBAdvDataIsConnectable"] as! Bool 
    let displayPeripheral = DisplayPeripheral(peripheral: peripheral, lastRSSI: RSSI, isConnectable: isConnectable) 
    peripherals.append(displayPeripheral) 
    tableView.reloadData() 
    } 
} 

这是我在控制台中看到:

AdvertisementData: “kCBAdvDataIsConnectable”:0, “kCBAdvDataManufacturerData”:< 0d00fe05 0c6f32> ,“kCBAdvDataLocalName”:CLIMBC]

我感兴趣解码的数据是kCBAdvDataManufacturerData:< 0d00fe05 0c6f32>并在屏幕上显示每个字段。 具体而言,这是个什么数字在我的情况表示:

  1. 0d00 - TI制造商ID
  2. FE - 我已经给
  3. 05节点ID - 节点的东西的(状态保持不变
  4. C6F - 是传感器标签电池电压
  5. 32是BLE分组计数器

在Android中我能。解码如下:

private static String getNodeIdFromRawPacket(byte[] manufSpecField) { 
    if(manufSpecField != null && manufSpecField.length > 1) { 
     return String.format("%02X", manufSpecField[0]); 
    }else{ 
     return null; 
    } 
} 
private static int getNodeBatteryVoltageFromRawPacket(byte[] manufSpecField){ 
    if(manufSpecField != null && manufSpecField.length > 4) { 
     return (((((int) manufSpecField[manufSpecField.length - 3]) << 24) >>> 24) << 8) + ((((int) manufSpecField[manufSpecField.length - 2]) << 24) >>> 24); 
    }else{ 
     return 0; 
    } 
} 

private byte[] extractManufacturerSpecificData(byte[] scanRecord, int manufacturer_id){ 

    if(scanRecord != null) { 
     int ptr = 0; 
     while (ptr < scanRecord.length && scanRecord[ptr] != 0) { 
      int field_length = scanRecord[ptr]; 
      if (scanRecord[ptr + 1] == (byte) (0xFF)) { //this is true when the manufacturer specific data field has been found 
       if (((scanRecord[ptr + 3] << 8) + scanRecord[ptr + 2]) == manufacturer_id) { 
        byte[] manufacturerSpecificData = new byte[field_length - 3]; 
        System.arraycopy(scanRecord, ptr + 4, manufacturerSpecificData, 0, field_length - 3); 
        return manufacturerSpecificData; 
       } 
      } 
      ptr += (field_length + 1); 
     } 
     return null; 
    }else{ 
     return null; 
    } 
    } 
}; 

我到底该如何做到这一点?我对Swift很陌生,这就是为什么我发现一些困难。任何代码片段将是最受欢迎的。

+1

在伪代码'VAR manData = AdvertisementData [“kCBAdvDataManufacturerData”]作为Data'然后就可以调用'子数据(范围:NSRange)'将你的manData分成你想要的每个部分,然后读取它们。 – Larme

回答

1

这里是SWIFT 3数据的方法subdata的实现与转换成数据,然后一个字符串的例子分裂出去,你可以回转换为字符串字节:

let input = "505450578" 
let data = input.data(using: .utf8) 

let manufacturerId:Range<Int> = 0..<2 
let nodeId:Range<Int> = 2..<4 
let nodeState:Range<Int> = 4..<5 
let voltage:Range<Int> = 5..<6 
let packetCounter:Range<Int> = 6..<9 

let subdata1 = data?.subdata(in: manufacturerId) 
let subdata2 = data?.subdata(in: nodeId) 
let subdata3 = data?.subdata(in: nodeState) 
let subdata4 = data?.subdata(in: voltage) 
let subdata5 = data?.subdata(in: packetCounter) 

//Results from original given string 
let str1 = String(data: subdata1!, encoding:.utf8) //50 
let str2 = String(data: subdata2!, encoding:.utf8) //54 
let str3 = String(data: subdata3!, encoding:.utf8) //5 
let str4 = String(data: subdata4!, encoding:.utf8) //0 
let str5 = String(data: subdata5!, encoding:.utf8) //578 
+0

@ Prientus。这非常有帮助。欢呼声:) – user3315702

2

看到您的控制台的输出,advertisementData["kCBAdvDataManufacturerData"]似乎是一个包含7个字节的NSData。您可以轻松地访问它作为一个斯威夫特Data,并在Data每个字节都可以通过下标来访问:

if let manufacturerData = advertisementData["kCBAdvDataManufacturerData"] as? Data { 
    assert(manufacturerData.count >= 7) 
    //0d00 - TI manufacturer ID 
    //Constructing 2-byte data as little endian (as TI's manufacturer ID is 000D) 
    let manufactureID = UInt16(manufacturerData[0]) + UInt16(manufacturerData[1]) << 8 
    print(String(format: "%04X", manufactureID)) //->000D 
    //fe - the node ID that I have given 
    let nodeID = manufacturerData[2] 
    print(String(format: "%02X", nodeID)) //->FE 
    //05 - state of the node (something that remains constant 
    let state = manufacturerData[3] 
    print(String(format: "%02X", state)) //->05 
    //c6f - is the sensor tag battery voltage 
    //Constructing 2-byte data as big endian (as shown in the Java code) 
    let batteryVoltage = UInt16(manufacturerData[4]) << 8 + UInt16(manufacturerData[5]) 
    print(String(format: "%04X", batteryVoltage)) //->0C6F 
    //32- is the BLE packet counter. 
    let packetCounter = manufacturerData[6] 
    print(String(format: "%02X", packetCounter)) //->32 
} 
+0

已编码且已经过测试。有用。伟大的:) – user3315702