iPhone与ESP32 BLE通信异常:发送成功但ESP32无接收反馈
iPhone通过BLE向ESP32发送文本数据无响应问题排查
问题描述
iPhone应用已与ESP32成功建立并保持BLE连接,点击发送按钮后应用控制台提示发送成功,但ESP32的串口监视器无任何数据输出。使用第三方BLE扫描类应用测试时,ESP32能正常接收数据。
ESP32端代码
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #define SERVICE_UUID "8c2a81f7-f8b8-4b31-89b4-6b5d98a822db" #define CHARACTERISTIC_UUID "e8bd8c82-2506-4fae-b5f2-9bbbf4ab5b0e" BLECharacteristic *characteristic; class MyServerCallbacks : public BLEServerCallbacks { void onConnect(BLEServer *pServer) { // Verbindung hergestellt } void onDisconnect(BLEServer *pServer) { // Verbindung getrennt } }; class MyCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string value = pCharacteristic->getValue(); if (value.length() > 0) { Serial.println("Empfangene Daten:"); Serial.println(value.c_str()); } } }; void setup() { Serial.begin(115200); BLEDevice::init("ESP32"); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); characteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE ); characteristic->setCallbacks(new MyCallbacks()); pService->start(); BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(false); pAdvertising->setMinPreferred(0x06); pAdvertising->setMinPreferred(0x12); BLEDevice::startAdvertising(); } void loop() { // Hier können weitere Aktionen im Hintergrund durchgeführt werden }
iPhone端Swift代码
import SwiftUI import CoreBluetooth class BluetoothManager: NSObject, CBCentralManagerDelegate, ObservableObject { let esp32ServiceUUID = CBUUID(string: "8c2a81f7-f8b8-4b31-89b4-6b5d98a822db") let esp32CharacteristicUUID = CBUUID(string: "e8bd8c82-2506-4fae-b5f2-9bbbf4ab5b0e") let centralManager: CBCentralManager var peripheral: CBPeripheral? var characteristic: CBCharacteristic? @Published var isConnected = false override init() { centralManager = CBCentralManager(delegate: nil, queue: nil) super.init() centralManager.delegate = self } func startScanning() { centralManager.scanForPeripherals(withServices: [esp32ServiceUUID]) print("Started scanning for peripherals") } func sendNumberToESP32(text: String) { guard let peripheral = peripheral, let characteristic = characteristic else { return } guard let data = text.data(using: .utf8) else { return } peripheral.writeValue(data, for: characteristic, type: .withoutResponse) print("Sent data to ESP32: \(text)") } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { startScanning() } else { // Bluetooth ist nicht aktiviert oder nicht verfügbar print("Bluetooth not powered on or unavailable") } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if peripheral.name == "ESP32" { centralManager.stopScan() self.peripheral = peripheral self.peripheral?.delegate = self centralManager.connect(peripheral) print("Discovered ESP32 peripheral") } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { isConnected = true print("Connected to peripheral") peripheral.discoverServices([esp32ServiceUUID]) } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { isConnected = false print("Disconnected from peripheral") centralManager.scanForPeripherals(withServices: [esp32ServiceUUID]) print("Started scanning for peripherals again") } } extension BluetoothManager: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let service = peripheral.services?.first(where: { $0.uuid == esp32ServiceUUID }) { peripheral.discoverCharacteristics([esp32CharacteristicUUID], for: service) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let characteristic = service.characteristics?.first(where: { $0.uuid == esp32CharacteristicUUID }) { self.characteristic = characteristic } } } struct ContentView: View { @State private var text: String = "" @StateObject private var bluetoothManager = BluetoothManager() var body: some View { VStack { Text(bluetoothManager.isConnected ? "Verbunden" : "Getrennt") .padding() TextField("Zahl eingeben",text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() Button(action: { bluetoothManager.sendNumberToESP32(text: text) }) { Text("Senden") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } } .onAppear { bluetoothManager.startScanning() } .onChange(of: bluetoothManager.isConnected) { isConnected in print("Verbindungsstatus geändert: \(isConnected)") } } }
排查解决方案
匹配BLE写入属性
iPhone端使用.withoutResponse类型写入,ESP32端必须开启对应的PROPERTY_WRITE_NR属性。修改ESP32创建Characteristic的代码:characteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR );验证Characteristic权限
在iPhone端的didDiscoverCharacteristicsFor方法中,添加权限检查,确保获取的Characteristic支持无响应写入:func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let characteristic = service.characteristics?.first(where: { $0.uuid == esp32CharacteristicUUID }) { guard characteristic.properties.contains(.writeWithoutResponse) else { print("Characteristic不支持无响应写入") return } self.characteristic = characteristic print("成功获取可写入Characteristic") } }添加连接状态日志
在ESP32的onConnect回调中添加串口打印,确认设备连接状态:void onConnect(BLEServer *pServer) { Serial.println("ESP32已与设备建立连接"); }检查串口配置
确保ESP32串口监视器的波特率设置为115200,与代码中Serial.begin(115200)一致。测试带响应写入
暂时将iPhone端写入类型改为.withResponse,测试是否能触发ESP32的onWrite回调:peripheral.writeValue(data, for: characteristic, type: .withResponse)如果此方式能收到数据,说明无响应写入的属性配置存在不匹配。
内容的提问来源于stack exchange,提问作者Jufeus
相关产品推荐
相关产品推荐

