未调用 BLE 外设委托

Posted

技术标签:

【中文标题】未调用 BLE 外设委托【英文标题】:BLE Peripheral delegate not called 【发布时间】:2017-11-17 01:18:06 【问题描述】:

我最近从 Swift 3 升级到了 Swift 4,从 ios 10.3.3 升级到了 iOS 11.1。

我正在开发一个使用 BLE 进行双向通信的应用程序。工作流程如下:

    外围设备 - 广告身份 CENTRAL - 接收身份(处理它...) CENTRAL - 响应外围设备 外围设备 - 从中​​央接收响应 完成

我的代码在更新之前运行良好,但现在不行了。在第 4 步结束时,我执行以下行:

peripheral.writeValue(encryptedData!, for: characteristic, type: .withResponse)

这应该调用以下委托方法,但它没有:

public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) 
        print("Did Write")
        print("Error=\(error?.localizedDescription)")
    

它还应该(并且正在调用)外围设备上的以下委托方法,但它没有:

public func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) 
        print("did receive write request")

服务和特性设置如下:

let prefs = Preferences()
            let strServiceUUID = prefs.GetString(key: Preferences.PREF_IDENTITY_SERVICE_UUID, defaultVal: "")!
            let strCharacteristicUUID = prefs.GetString(key: Preferences.PREF_IDENTITY_CHARACTERISTIC_UUID, defaultVal: "")!
            print("ServiceUUID=\(strServiceUUID)")
            print("CharacteristicUUID=\(strCharacteristicUUID)")
            mServiceUUID = CBUUID(string: strServiceUUID)
            mCharacterUUID = CBUUID(string: strCharacteristicUUID)
            mCBBluetoothServices = CBMutableService(type: mServiceUUID, primary: true)
            
            //lets configure the data we want to advertise for
            var characteristics : [CBCharacteristic] = []
            
            //let strData : String = "933911"
            //let data = strData.data(using: .utf8)
            let cbProperties: CBCharacteristicProperties = [.read, .write, .notify]
            let cbPermissions: CBAttributePermissions = [.readable, .writeable]
            mIdentityObjectCharacteristic = CBMutableCharacteristic(type: mCharacterUUID,
                                                                    properties: cbProperties,
                                                                    value: nil,
                                                                    permissions: cbPermissions)
            
            
            characteristics.append(mIdentityObjectCharacteristic)
            mCBBluetoothServices.characteristics = characteristics
            mCBPeripheralManager.add(mCBBluetoothServices)

【问题讨论】:

【参考方案1】:

我不确定为什么升级 OS 和 Swift 版本会破坏您的代码,但是在我看来您可能使用了错误的委托方法?

试试这个

func peripheral(CBPeripheral, didWriteValueFor: CBCharacteristic, error: Error?)

而不是这个

func peripheral(CBPeripheral, didWriteValueFor: CBDescriptor, error: Error?)

【讨论】:

我把它改成了正确的委托方法,但是当我调用 peripheral.writeValue(encryptedData!, for: characteristic, type: .withResponse) 时它仍然没有陷入陷阱。 这很不幸。您是否确保您确实已连接、拥有所有权限、启用了 BLE 等?我自己升级到 iOS 后遇到了一些 BLE 连接问题,特别是对于 iPhone 5s 等旧手机。如果您发布更多代码,我可以进行比较,看看我们是否看到了相同的问题。【参考方案2】:

斯威夫特 4

对于任何类型的更新特性(例如读/写特性),将调用 didUpdateValueFor 委托。

所以,首先检查以下委托方法。

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) 
    
    print("didUpdateValueForChar", characteristic)
    
    if let error1 = error
        
        alertMSG(titleString: "Error", subTitleString: "Found error while read characteristic data, Plase try again", buttonTitle: "OK")
        
        print(error1)
    
    else
        
        print("Update Characteristic: ", characteristic)
    


func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) 
    
    print("Write Characteristic :", characteristic)

【讨论】:

【参考方案3】:

斯威夫特 5 iOS 13

需要检查的一些事项:

    确保将外设的delegate 设置为符合CBPeripheralDelegate 协议的任何控制器(这也应该是需要实现peripheral(_:didWriteValueFor:error:) 方法的同一控制器)。 确保您没有指定 .withoutResponse 写入类型。 正如this other answer 所提到的,有两个非常相似的委托方法具有签名peripheral(_:didWriteValueFor:error:)。确保你正在实施正确的。 写入特征时: writeValue(_:for:type:):
    func writeValue(_ data: Data, 
                    for characteristic: CBCharacteristic, 
                    type: CBCharacteristicWriteType)
    
    peripheral(_:didWriteValueFor:error:)
    func peripheral(_ peripheral: CBPeripheral, 
                    didWriteValueFor characteristic: CBCharacteristic, 
                    error: Error?)
    
    写入描述符时: writeValue(_:for:)
    func writeValue(_ data: Data, 
                    for descriptor: CBDescriptor)
    
    peripheral(_:didWriteValueFor:error:)
    func peripheral(_ peripheral: CBPeripheral, 
                    didWriteValueFor descriptor: CBDescriptor, 
                    error: Error?)
    

容易混淆2组write和delegate方法。

由于您正在使用:

peripheral.writeValue(encryptedData!, for: characteristic, type: .withResponse) 

write 和 delegate 对的代码应该是这样的:

class BluetoothController: CBCentralManagerDelegate, CBPeripheralDelegate 

    ...
   
    func writeSomething(to characteristic: CBCharacteristic, of peripheral: CBPeripheral) 
        let something = "1234"
        
        NSLog("Writing \(something) to \(characteristic.uuid.uuidString)")
        
        peripheral.delegate = self  // <===== You may have forgotten this?
        peripheral.writeValue(something.data(using: .utf8)!,
                              for: characteristic,
                              type: .withResponse)
    

    ...

    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) 
        if error != nil 
            NSLog("Write error: \(String(describing: error))")
         else 
            NSLog("Wrote value to \(characteristic.uuid.uuidString)")
        
    

【讨论】:

以上是关于未调用 BLE 外设委托的主要内容,如果未能解决你的问题,请参考以下文章

BLE 外设无广告

Android外设BluetoothGattServerCallback onServiceAdded()没有被调用

未调用 Android BLE onCharacteristicChanged

未调用 Android BLE onCharacteristicChanged()

iOS iPad 应用程序:未调用具有两个 UIScrollViews 和一个 UIPageControl 的 ViewController 的委托(未调用分页的委托函数)

NSURLSession 委托未调用