英文:
BLE sent String between ESP32 and Iphone
问题
我需要从iPhone通过BLE将文本发送到ESP32。
手机应用程序连接到ESP32并成功保持连接。但是当我按发送按钮时,控制台显示发送成功。但是在ESP32的串行监视器上没有显示任何内容。
使用BLE扫描器应用程序一切正常。
这是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) {
// Connection established
}
void onDisconnect(BLEServer *pServer) {
// Connection disconnected
}
};
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("Received Data:");
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() {
// Additional background actions can be performed here
}
这是应用程序的部分代码:
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 is not powered on or available
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 ? "Connected" : "Disconnected")
.padding()
TextField("Enter number",text: $text)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
bluetoothManager.sendNumberToESP32(text: text)
}) {
Text("Send")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.onAppear {
bluetoothManager.startScanning()
}
.onChange(of: bluetoothManager.isConnected) { isConnected in
print("Connection status changed: \(isConnected)")
}
}
}
感谢您的帮助。
英文:
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
答案1
得分: 2
你没有在这里检查错误,所以很难确定发生了什么。通常你应该实现 peripheral(_:didWriteValueFor:error:)
来查看值是否实际写入。我认为问题出在这里:
peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
你没有配置特征以允许无响应写入(PROPERTY_WRITE_NR
)。一般情况下,你不希望这样做。你应该在这里使用 .withResponse
。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论