I need to send text from an Iphone via BLE to an ESP32. The phone App connects to the ESP32 and stays connected successfully. But when I press send the console says the sending was successful. But on der Serial Monitor of the ESP32 appeares nothing. With an BLE scanner App all works fine.
Here is the code for the 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
}
And here from the App:
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)")
}
}
}
Thanks for helping
I´ve asked ChatGPT but it has no idea, and I searched in the internet
You're not checking for errors here, so it's hard to be certain what's happening. Typically you should implement peripheral(_:didWriteValueFor:error:)
to see that the value was actually written. I expect the problem is here:
peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
You didn't configure the characteristic to allow writing without response (PROPERTY_WRITE_NR
). You generally don't want that in any case. You should be using .withResponse
here.