蓝牙BLE中Central发送带响应写请求后无法接收Peripheral回复
蓝牙BLE带响应写请求:Central端无法接收Peripheral回复的问题排查
已正常实现的特征读取功能
当前BLE特征读取功能运行正常,相关代码如下:
Central端发送读请求
func readCharacteristicValue() { if let peripheral = connectedPeripheral, let characteristic = targetCharacteristic { peripheral.readValue(for: characteristic) } }
Peripheral端处理读请求
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) { // 根据服务调用不同逻辑 switch request.characteristic.uuid { case Constants.uuid.AuthService: let authenticationInstance = PAuthentication.pAuthentication authenticationInstance.responseToReadRequest(request: request, peripheralManager: peripheralManager, clearServiceCharacteristic: clearServiceCharacteristic) case Constants.uuid.OtherService: print("Other implementation") default: print("Nothing") } }
Central端接收读响应
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){ // 处理错误 if let error = error { print("Error reading characteristic value: \(error)") } // 根据响应的特征处理不同逻辑 switch characteristic.uuid { case Constants.uuid.AuthService: let authenticationInstance = CAuthentication.cAuthentication authenticationInstance.responceFromReadRequest(characteristic: characteristic, disconnect: disconnect) default: print("Nothing") } }
带响应写请求的问题描述
实现带响应的写请求时出现异常:Central端发送带响应的写请求后,Peripheral端能正常接收并处理请求,但Central端无法收到Peripheral的回复数据。
Central端写请求代码
func writeStringToCharacteristic(_ string: String) { if let data = string.data(using: .utf8), let peripheral = connectedPeripheral, let characteristic = targetCharacteristic { peripheral.writeValue(data, for: characteristic, type: .withResponse) } }
Peripheral端处理写请求代码
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) { for request in requests { if request.characteristic == characteristic { if let value = request.value { // 处理Central发送的数据示例 let receivedString = String(data: value, encoding: .utf8) print("Received data from Central: \(receivedString ?? "")") if (receivedString == "Auth"){ var dataToSend:Data? if let name = SharedData.shared.AuthData["name"], let surname = SharedData.shared.AuthData["surname"], let date = SharedData.shared.AuthData["date"] { dataToSend = "\(name), \(surname), \(date)".data(using: .utf8) // 准备通过蓝牙特征发送数据 } else { print("One or more values are missing") } request.value = dataToSend peripheralManager.respond(to: request, withResult: .success) // 无法将回复送达Central } } } } }
可能的原因及排查方向
- 写请求响应逻辑误解:BLE协议中,带响应的写请求(
.withResponse)的CBATTRequest.value字段仅用于读请求返回数据,写请求的响应仅告知Central写操作成功/失败,不会主动附带数据。若需在处理写请求后返回数据,必须使用**通知(Notify)或指示(Indicate)**机制。 - 特征属性配置不全:检查目标特征的属性,需同时开启
write(或writeWithoutResponse)和notify/indicate属性,否则Peripheral无法主动推送数据给Central。 - Central端未订阅特征通知:若要接收Peripheral主动推送的数据,Central必须先调用
setNotifyValue(true, for: characteristic)订阅目标特征的通知/指示。 - Central端未实现写操作回调:带响应的写请求的结果(成功/失败)需通过
peripheral(_:didWriteValueFor:error:)回调接收,而非didUpdateValueFor(该回调用于接收读响应和通知数据),若未实现此回调会误以为没收到回复。
修正示例
Peripheral端修改:处理写请求后发送通知
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) { for request in requests { if request.characteristic == characteristic { if let value = request.value { let receivedString = String(data: value, encoding: .utf8) print("Received data from Central: \(receivedString ?? "")") if receivedString == "Auth" { var dataToSend: Data? if let name = SharedData.shared.AuthData["name"], let surname = SharedData.shared.AuthData["surname"], let date = SharedData.shared.AuthData["date"] { dataToSend = "\(name), \(surname), \(date)".data(using: .utf8) } else { print("One or more values are missing") } // 先回复写操作成功状态 peripheralManager.respond(to: request, withResult: .success) // 若有数据需要返回,通过通知发送给已订阅的Central if let data = dataToSend, let targetChar = characteristic { peripheralManager.updateValue(data, for: targetChar, onSubscribedCentrals: nil) } } } } } }
Central端配套修改
- 订阅目标特征的通知:
// 连接Peripheral并发现特征后执行 if let peripheral = connectedPeripheral, let characteristic = targetCharacteristic { peripheral.setNotifyValue(true, for: characteristic) }
- 实现写操作结果回调:
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { print("Write operation failed: \(error)") return } print("Write operation succeeded") }
- 保留原
didUpdateValueFor回调接收通知数据(与读响应共用):
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){ if let error = error { print("Error receiving data: \(error)") return } switch characteristic.uuid { case Constants.uuid.AuthService: let authenticationInstance = CAuthentication.cAuthentication authenticationInstance.responceFromReadRequest(characteristic: characteristic, disconnect: disconnect) default: print("Nothing") } }
内容的提问来源于stack exchange,提问作者Emanuele Mele
相关产品推荐
相关产品推荐

