iOS10上的蓝牙LE奇怪行为

时间:2016-09-25 08:54:56

标签: ios swift bluetooth bluetooth-lowenergy

我发现当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)
         }
    }

1 个答案:

答案 0 :(得分:2)

经过一天的调查,硬件芯片和iOS,我意识到通知更新 - 会在有新值时通知您。

那么,有什么新价值?

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

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

因此,当您注册通知时,iOS会检查初始值,如果它包含其他零/零的内容,则会调用委托。

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

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

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