Hi,
I’m trying to connect two Sededs XIAO ESP32 C3 together via BLE. I’ve been using ChatGPT for the past 3 nights to try and trouble shoot it and feel i’m close, but just can’t quite crack the last issue.
I am able to set up the Server and Client and send simple Chars back and forth. Great!
However, I want to be able to send Data packs based on what function is running on the Server back and forth. It seems I am able to Send Data from the Server and Receive it on the Client. Unfortuntately I can’t get it to work the other way round. I am pretty sure the Client is sending it, but the Server either is not receiving it, or can’t interpret the incoming data.
Here is the Code for the Server:
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// Define UUIDs and Variables
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_TX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_RX "e66e361a-e7c8-44ea-9cf5-d60b151b3f93" // Additional characteristic for receiving data
int Pong_P1_Score;
struct PongData {
int var1;
int var2;
int var3;
int var4;
};
struct JumpData {
int var1;
int var2;
float var3;
};
union DataPacket {
PongData pong;
JumpData jump;
};
struct CombinedDataPacket {
uint8_t type; // 0 for PongData, 1 for JumpData
DataPacket data;
};
CombinedDataPacket dataToSend;
CombinedDataPacket dataReceived;
BLECharacteristic *txCharacteristic;
BLECharacteristic *rxCharacteristic;
bool deviceConnected = false;
// BLE Server Callbacks
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println("Client connected");
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("Client disconnected");
}
};
// BLE Characteristic Callbacks
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
// Get data from the characteristic as a String
String value = pCharacteristic->getValue().c_str();
size_t length = value.length();
Serial.print("Received data length: ");
Serial.println(length);
// Debugging: Print the received string data
Serial.print("Received data: ");
Serial.println(value);
// Check length and ensure data is not empty
if (length == sizeof(CombinedDataPacket)) {
// Convert the String data to a byte array
byte* byteArray = (byte*) value.c_str();
// Copy received data to our struct
memcpy(&dataReceived, byteArray, sizeof(CombinedDataPacket));
// Handle the received data based on its type
if (dataReceived.type == 0) {
Serial.println("Received Pong Data:");
Serial.print("Pong var1: ");
Serial.println(dataReceived.data.pong.var1);
Serial.print("Pong var2: ");
Serial.println(dataReceived.data.pong.var2);
Serial.print("Pong var3: ");
Serial.println(dataReceived.data.pong.var3);
Serial.print("Pong var4: ");
Serial.println(dataReceived.data.pong.var4);
} else if (dataReceived.type == 1) {
Serial.println("Received Jump Data:");
Serial.print("Jump var1: ");
Serial.println(dataReceived.data.jump.var1);
Serial.print("Jump var2: ");
Serial.println(dataReceived.data.jump.var2);
Serial.print("Jump var3: ");
Serial.println(dataReceived.data.jump.var3);
}
} else {
Serial.println("Received data length mismatch");
}
}
};
void sendData() {
if (deviceConnected) {
// Sending data to client
txCharacteristic->setValue((uint8_t*)&dataToSend, sizeof(dataToSend));
txCharacteristic->notify();
Serial.println("Data sent to client");
}
}
void updatePongData() {
// Update the Pong data based on game logic
dataToSend.type = 0; // 0 for PongData
dataToSend.data.pong.var1 = Pong_P1_Score;
dataToSend.data.pong.var2 = 20;
dataToSend.data.pong.var3 = 30;
dataToSend.data.pong.var4 = 40;
// Send the updated data
sendData();
}
void updateJumpData() {
// Update the Jump data based on game logic
dataToSend.type = 1; // 1 for JumpData
dataToSend.data.jump.var1 = 10;
dataToSend.data.jump.var2 = 20;
dataToSend.data.jump.var3 = 30.5;
// Send the updated data
sendData();
}
void setup() {
Serial.begin(115200);
// Initialize BLE
BLEDevice::init("ESP32_Server");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create BLE service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create BLE characteristics
txCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
txCharacteristic->addDescriptor(new BLE2902());
rxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
rxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting for a client connection...");
}
void loop() {
Pong_P1_Score += 1;
// Call the function to update Pong data and send it
updatePongData();
delay(1000); // Adjust the delay as needed
}
Here is the Client Code:
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// Define UUIDs and Variables
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_TX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_RX "e66e361a-e7c8-44ea-9cf5-d60b151b3f93" // Additional characteristic for receiving data
int Pong_P1_Score;
struct PongData {
int var1;
int var2;
int var3;
int var4;
};
struct JumpData {
int var1;
int var2;
float var3;
};
union DataPacket {
PongData pong;
JumpData jump;
};
struct CombinedDataPacket {
uint8_t type; // 0 for PongData, 1 for JumpData
DataPacket data;
};
CombinedDataPacket dataToSend;
CombinedDataPacket dataReceived;
BLECharacteristic *txCharacteristic;
BLECharacteristic *rxCharacteristic;
bool deviceConnected = false;
// BLE Server Callbacks
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println("Client connected");
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("Client disconnected");
}
};
// BLE Characteristic Callbacks
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
// Get data from the characteristic as a String
String value = pCharacteristic->getValue().c_str();
size_t length = value.length();
Serial.print("Received data length: ");
Serial.println(length);
// Debugging: Print the received string data
Serial.print("Received data: ");
Serial.println(value);
// Check length and ensure data is not empty
if (length == sizeof(CombinedDataPacket)) {
// Convert the String data to a byte array
byte* byteArray = (byte*) value.c_str();
// Copy received data to our struct
memcpy(&dataReceived, byteArray, sizeof(CombinedDataPacket));
// Handle the received data based on its type
if (dataReceived.type == 0) {
Serial.println("Received Pong Data:");
Serial.print("Pong var1: ");
Serial.println(dataReceived.data.pong.var1);
Serial.print("Pong var2: ");
Serial.println(dataReceived.data.pong.var2);
Serial.print("Pong var3: ");
Serial.println(dataReceived.data.pong.var3);
Serial.print("Pong var4: ");
Serial.println(dataReceived.data.pong.var4);
} else if (dataReceived.type == 1) {
Serial.println("Received Jump Data:");
Serial.print("Jump var1: ");
Serial.println(dataReceived.data.jump.var1);
Serial.print("Jump var2: ");
Serial.println(dataReceived.data.jump.var2);
Serial.print("Jump var3: ");
Serial.println(dataReceived.data.jump.var3);
}
} else {
Serial.println("Received data length mismatch");
}
}
};
void sendData() {
if (deviceConnected) {
// Sending data to client
txCharacteristic->setValue((uint8_t*)&dataToSend, sizeof(dataToSend));
txCharacteristic->notify();
Serial.println("Data sent to client");
}
}
void updatePongData() {
// Update the Pong data based on game logic
dataToSend.type = 0; // 0 for PongData
dataToSend.data.pong.var1 = Pong_P1_Score;
dataToSend.data.pong.var2 = 20;
dataToSend.data.pong.var3 = 30;
dataToSend.data.pong.var4 = 40;
// Send the updated data
sendData();
}
void updateJumpData() {
// Update the Jump data based on game logic
dataToSend.type = 1; // 1 for JumpData
dataToSend.data.jump.var1 = 10;
dataToSend.data.jump.var2 = 20;
dataToSend.data.jump.var3 = 30.5;
// Send the updated data
sendData();
}
void setup() {
Serial.begin(115200);
// Initialize BLE
BLEDevice::init("ESP32_Server");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create BLE service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create BLE characteristics
txCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
txCharacteristic->addDescriptor(new BLE2902());
rxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
rxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting for a client connection...");
}
void loop() {
Pong_P1_Score += 1;
// Call the function to update Pong data and send it
updatePongData();
delay(1000); // Adjust the delay as needed
}
Both codes compile fine if you can/want to try it out.
ChatGPT tries to suggest to adjust the following Server code:
String value = pCharacteristic->getValue().c_str();
to:
std::string value = pCharacteristic->getValue(); // This line causes issues
But then the Arduino IDE can’t compile it anymore.
I’m stuck. How can I make that the Server can read what the client is sending?
Thank you very much for your time and help.