我需要通过BLE将文本从iPhone发送到ESP32. 手机应用程序连接到ESP32并保持成功连接.但当我按下发送时,控制台显示发送成功.但在ESP32的DER串口显示器上什么也没有出现. 有了BLE scanner ,App就可以正常工作了.

以下是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
}

下面是这款应用程序的内容:

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


谢谢你的帮助

我问过ChatGPT,但它不知道,我在互联网上搜索了

推荐答案

您并没有在这里判断错误,所以很难确定发生了什么.通常,您应该实现peripheral(_:didWriteValueFor:error:)以查看该值是否已实际写入.我认为问题出在这里:

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

您没有将该特征配置为允许在没有响应的情况下写入(PROPERTY_WRITE_NR).在任何情况下,你通常都不希望出现这种情况.你应该在这里用.withResponse.

Swift相关问答推荐

如何防止自动状态恢复,如果应用程序被启动打开特定的文档?

如何获取SCNCamera正在查看的网格点(SCNNode)的局部坐标和局部法线?

与视图交互使工具栏&;标题消失

Result类型的初始值设定项失败?

Swift String.firstIndex(of: "\n") 返回 nil,即使字符串有 \n

将 ArgumentParser 与 Swift 并发一起使用

如何让飞机与 RealityKit 中的物体相撞

Swift-SceneKit-无法从art.scnassets加载.scn文件

如果 Swift 无法分配内存会怎样?

UUID 哈希值是不确定的吗?

带有屏幕参数的 NSWindow 初始化程序在初始化时导致致命错误

临时添加到视图层次 struct 后,Weak view引用不会被释放

Swift 2 中的新 @convention(c):我该如何使用它?

try 在解除分配时加载视图控制器的视图... UIAlertController

在 Swift 中指定 UITextField 的边框半径

<<错误类型>> 奇怪的错误

'类 'className' 的 NSManagedObject 必须具有有效的 NSEntityDescription.错误

Switch 语句中的字符串:String不符合协议IntervalType

如何在swift中的每N个字符处为字符串添加分隔符?

在这个例子中美元符号有什么作用?