iOS10 上的蓝牙 LE 奇怪行为

Bluetooth LE on iOS10 strange behavior

我发现当 iPhone 正在更新本地特征值时,并且还听取了该特征的通知,即使 他就是那个人,他也会收到通知 更新了值,所以委托 :

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

将被调用,即使我是更改值的人,而不是远程服务器(ble 设备)。当远端发送数据时,我也会得到这个委托。 这是应该的方式吗?我不记得了。

我在 其他 扫描蓝牙 LE 的第三个应用程序上发现了相同的行为。

我还发现由于某种原因我的代码并不总是得到委托,也许我在这里做错了:

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {


        let foundName=peripheral.name
        let deviceName = "Name"

       if foundName?.range(of: deviceName) != nil
        {
                        self.centralManager.stopScan()
                        self.peripheral = peripheral
                        self.peripheral.delegate = self
                        self.centralManager.connect(peripheral, options: nil)
                        NotificationCenter.default.post(name: Notification.Name(rawValue: "Bluetooth"), object: "Detected")

        }
}


    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

         peripheral.discoverServices( nil)
    }



     func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

          for service in peripheral.services!
         {

            let thisService = service as CBService
            print(thisService.uuid.uuidString)

            if thisService.uuid.uuidString == serviceUUID {
                 peripheral.discoverCharacteristics(nil, for: thisService)
            }

        }
    }


    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

        for charateristic in service.characteristics!
        {
            let thisCharacteristic = charateristic as CBCharacteristic



            // check for data characteristic
            if thisCharacteristic.uuid.uuidString == characteristicUUID {

                print("REGISTERED CHARACTERISTIC:",thisCharacteristic)
                 self.peripheral.setNotifyValue(true, for: thisCharacteristic)
                self.characteristic=thisCharacteristic
                 isConnected=true
                NotificationCenter.default.post(name: Notification.Name(rawValue: "Bluetooth"), object: "Connected")

            }
        }            
    }


    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {


           if characteristic.uuid.uuidString == characteristicUUID {
             if let str = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue)
             {                   
                print("BLE:DATAIN:",str )
                 NotificationCenter.default.post(name: Notification.Name(rawValue: "Bluetooth"), object: str)

             }

          }                 
    }



    func sendData(data:String)
    {
        if(peripheral != nil)
        {
            print("BLE:SENT")  
            var bytesData = [UInt8](data.utf8)
            let writeData = NSData (bytes: &bytesData, length: bytesData.count)
             peripheral.writeValue(writeData as Data, for: characteristic, type: CBCharacteristicWriteType.withoutResponse)
         }
    }

查了一天硬件芯片和iOS,发现notify update-有新值的时候会通知你

那么,什么是新值?

当上一个值与当前值不同时。

对于某些硬件配置,以前的值即使在重置后也会保留在缓存中,并且 iOS 会将其视为新值,即使硬件根本没有更新它 (!)

因此,当您注册通知时,iOS 将检查初始值 ,如果它包含 zero/nil 以外的其他内容,则委托将是打电话。

你的工作就是以某种方式清除芯片中以前缓存的值。

总的来说,我发现(也许为时已晚)最佳做法是连接并保持连接,只要应用程序处于 运行。这将消除每次需要发送数据时 connect/disconnect 发生的各种问题。

结论: 连接一次,当因任何原因断开连接时 - 自动重置您的硬件(使用主机控制器软件)