在OSX与iOS(GAP / GATT)上发现外围设备时,CBPeripheral advertisementData有所不同

时间:2017-01-13 05:46:22

标签: bluetooth bluetooth-lowenergy core-bluetooth cbperipheral cbcentralmanager

我希望将我的一些CoreBluetooth代码从iOS移植到OS X.我已经设置了一组共享的CoreBluetooth包装器,这些包装器被iOS应用程序和OS X应用程序以完全相同的方式使用使用相同的BLE设备。

扫描外围设备:

override init() {
    super.init()
    let queue = DispatchQueue.global(qos: .background)
    centralManager = CBCentralManager(delegate: self, queue: queue)
}

func startScanning() {
    let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
    let deviceUUID = CBUUID(string: Project.Service.Device)
    let recoveryUUID = CBUUID(string: Project.Service.DFURecovery)
    centralManager?.scanForPeripherals(withServices: [deviceUUID, recoveryUUID], options: options)
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
    // Inspect advertisementData here to decipher what kind of device
}

在我的iOS应用中,didDiscoverPeripheral被解雇了。然后当我检查广告数据时,我得到了我期望的所有键/值:

{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = "My Device";
    kCBAdvDataManufacturerData = <34045254 5877f283 43fdd12d ff530978 45000000 000050c2 6500>;
    kCBAdvDataServiceData =     {
        Battery = <64>;
    };
    kCBAdvDataServiceUUIDs =     (
        "My Inforamtion"
    );
}

但是,当从OS X应用程序运行相同的代码(扫描相同的设备)时,广告数据缺少某些字段。

{
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataManufacturerData = <34045254 5877f36e 43fdd12d ff530978 45000000 000050c2 6500>;
}

advertisedData缺少以下键/值对。

kCBAdvDataLocalName
kCBAdvDataServiceData
kCBAdvDataServiceUUIDs

我已尝试将这些密钥添加到scanForPeripherals调用中,如下所示:

    let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: true,
                                  CBAdvertisementDataLocalNameKey: true,
                                  CBAdvertisementDataServiceDataKey: true,
                                  CBAdvertisementDataServiceUUIDsKey: true]
    let deviceUUID = CBUUID(string: Nightlight.Service.Device)
    let recoveryUUID = CBUUID(string: Nightlight.Service.DFURecovery)
    centralManager?.scanForPeripherals(withServices: [deviceUUID, recoveryUUID], options: options)

没有效果。

2 个答案:

答案 0 :(得分:2)

OSX可能会为每个设备多次调用didDiscoverPeripheral,每次调用不同的advertisementData。我想出的解决方案是编写缓存。

导入基金会     导入CoreBluetooth

class AdvertisementDataCache {

    fileprivate var map = [UUID: [String: Any]]()

    func append(peripheral: CBPeripheral, advertisementData: [String: Any]) -> [String: Any] {
        var ad = (map[peripheral.identifier]) ?? [String: Any]()
        for (key, value) in advertisementData {
            ad[key] = value
        }
        map[peripheral.identifier] = ad
        return ad
    }

    func clear() {
        map.removeAll()
    }
}

然后在didDiscoverPeripheral:

var advertisementDataCache = AdvertisementDataCache()

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
    let advertisementDataCache = self.advertisementDataCache.append(peripheral: peripheral, advertisementData: advertisementDataCache)
    // cache may contain all 5 of the advertisements, depending on how may have been delivered
    if let device = AdvertisementData.isTheDeviceIAmLookingFor(peripheral: peripheral, advertisementData: cache) {
        // Do stuff with device
    }
}

答案 1 :(得分:0)

更新。我正在使用UIKitForMac(测试版2),并且遇到了相同的问题。缓存/汇总广告数据的解决方案也适用于这种情况。