You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)")
        }
    }
}

排查解决方案

  1. 匹配BLE写入属性
    iPhone端使用.withoutResponse类型写入,ESP32端必须开启对应的PROPERTY_WRITE_NR属性。修改ESP32创建Characteristic的代码:

    characteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR
    );
    
  2. 验证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")
        }
    }
    
  3. 添加连接状态日志
    在ESP32的onConnect回调中添加串口打印,确认设备连接状态:

    void onConnect(BLEServer *pServer) {
        Serial.println("ESP32已与设备建立连接");
    }
    
  4. 检查串口配置
    确保ESP32串口监视器的波特率设置为115200,与代码中Serial.begin(115200)一致。

  5. 测试带响应写入
    暂时将iPhone端写入类型改为.withResponse,测试是否能触发ESP32的onWrite回调:

    peripheral.writeValue(data, for: characteristic, type: .withResponse)
    

    如果此方式能收到数据,说明无响应写入的属性配置存在不匹配。

内容的提问来源于stack exchange,提问作者Jufeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:53:12