buongiorno, chiedo supporto per un problema a cui sto dietro da un sacco senza trovare una soluzione.
sto scrivendo un programma da eseguire su una scheda esp32 che controlli un anello led. tramite l'app nRF Connect ho 'sniffato' il traffico tra l'app per controllare il led, e il led e ho scoperto che per cambiare colore viene mandato questo byte: 0x7b 0xff 0x07 R G B 0x00 0xff 0xbf, dove r,g e b sono chiaramente i valori rgb; per esempio, quindi, per cambiare il colore in bianco il byte mandato sarebbe questo: 0x7b 0xff 0x07 0xff 0xff 0xff 0x00 0xff 0xbf (ff = 255 in esadecimale).
lo scopo del programma sarebbe di cambiare rapidamente colore tramite un interruttore di cui però non sono ancora a disposizione, quindi sto scrivendo il codice in una versione "test".
questo programma dovrebbe svolgere sia funzione di client, che server BLE: la funzione 'client' è quella precedentemente descritta che si collega al led, mentre quella 'server' ha lo scopo di creare una connessione con il telefono, in modo tale che scrivendo sulla sua caratteristica un valore rgb, si potrà scegliere il colore nel momento in cui l'interruttore non è in posizione "bianco".
il problema è che nel momento in cui chiamo il metodo caratteristicaRemota->writeValue(), il programma crasha e la scheda si riavvia, con questo errore nel monitor seriale: Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
questo, però, succede solo se il byte viene costruito utilizzando per i valori r, g e b delle variabili; mentre se le inserisco manualmente nel codice non si presenta nessun problema.
ecco il codice:
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Wire.h>
#define serverName "esp32-server"
BLEClient* bleClient;
BLERemoteService* servizioRemoto;
BLERemoteCharacteristic* caratteristicaRemota;
#define SERVIZIO_UUID "ffe0"
#define COLORE_UUID "ffe1"
#define ANIMAZIONE_UUID "ffe2"
#define INDIRIZZO_MAC_LED "CF:FF:F3:0F:00:71"
bool deviceConnected = false;
uint8_t rgb[3];
int i = 0;
int animazione;
bool coloreAggiornato = false;
bool animazioneAggiornata = false;
void setColor(int red, int green, int blue) {
String redHexString = String(red, HEX);
Serial.println(redHexString);
String greenHexString = String(green, HEX);
Serial.println(greenHexString);
String blueHexString = String(blue, HEX);
Serial.println(blueHexString);
char redHexChar[10];
redHexString.toCharArray(redHexChar, 10);
Serial.println(redHexChar);
char greenHexChar[10];
greenHexString.toCharArray(greenHexChar, 10);
Serial.println(greenHexChar);
char blueHexChar[10];
blueHexString.toCharArray(blueHexChar, 10);
Serial.println(blueHexChar);
uint8_t redHex = strtol(redHexChar, NULL, 16);
Serial.println(redHex);
uint8_t greenHex = strtol(greenHexChar, NULL, 16);
Serial.println(greenHex);
uint8_t blueHex = strtol(blueHexChar, NULL, 16);
Serial.println(blueHex);
uint8_t data[9];
data[0] = 0x7b;
data[1] = 0xff;
data[2] = 0x07;
data[3] = 0XFF;
data[4] = 0XFF;
data[5] = 0XFF;
data[6] = 0x00;
data[7] = 0xff;
data[8] = 0xbf;
caratteristicaRemota->writeValue(data, sizeof(data));
}
class CaratteristicheCallback: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string uuid_intero = pCharacteristic->getUUID().toString(); // UUID completo
std::string uuid_abbreviato = uuid_intero.substr(4, 4); // estrae "ffe1" da x esempio "0000ffe1-0000-1000-8000-00805f9b34fb"
std::string value = pCharacteristic->getValue();
if(uuid_abbreviato == COLORE_UUID) {
// --- cosa fare in caso di scrittura nella caratteristica del colore ---
Serial.println("[ server | ~ ] dati ricevuti su caratteristica colore");
// --- check decimale ---
bool valido = true;
for(char c: value) {
if(!isdigit(c)) {
valido = false;
break;
}
}
// --- check lunghezza (3 cifre x 3)
if(valido && value.length() == 9) {
// --- nel caso in cui il valore rispetta tutti i "requisiti" suddividere in tre variabili r,g,b e stampare nel monitor seriale ---
rgb[0] = atoi(value.substr(0, 3).c_str());
rgb[1] = atoi(value.substr(3, 3).c_str());
rgb[2] = atoi(value.substr(6, 3).c_str());
if(rgb[0]<=255 && rgb[1]<=255 && rgb[2]<=255) {
coloreAggiornato = true;
}
} else {
Serial.println("[ server | ! ] il formato dei dati inseriti non è corretto");
};
} else if (uuid_abbreviato == ANIMAZIONE_UUID) {
// --- cosa fare in caso di scirttura nella caratteristica dell'animazione ---
if(value.length() == 1) {
Serial.println("[ server | ~ ] dati ricevuti su caratteristica animazione");
animazioneAggiornata = true;
} else { Serial.println("[ server | ! ] il formato dei dati inseriti non è corretto"); };
}
}
};
// --- gestione eventi server ---
class ServerCallback : public BLEServerCallbacks {
// --- evento di connessione ---
void onConnect(BLEServer *pServer) {
deviceConnected = true;
Serial.println("[ server | + ] un client si è connesso!");
};
// --- evento di disconessione ---
void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
Serial.println("[ server | - ] un client si è disconnesso");
}
};
void setup() {
// --- inizializzare il monitor seriale ---
Serial.begin(115200);
// --- dual role ---
// --- inizializzare server BLE e assegnare callback per gestire connessioni, disconnessioni e traffico dati ---
BLEDevice::init(serverName);
xTaskCreatePinnedToCore(
client,
"client",
5000,
NULL,
0,
NULL,
0
);
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallback());
// --- creazione servizio ---
BLEService *testService = pServer->createService(SERVIZIO_UUID);
BLECharacteristic *caratteristicaColore = testService->createCharacteristic(COLORE_UUID, BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ);
BLECharacteristic *caratteristicaAnimazione = testService->createCharacteristic(ANIMAZIONE_UUID, BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ);
caratteristicaColore->setCallbacks(new CaratteristicheCallback());
caratteristicaAnimazione->setCallbacks(new CaratteristicheCallback());
// --- inizializzazione servizio ---
testService->start();
// --- inizializzazione advertising (comparsa sulle liste bluetooth) ---
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVIZIO_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("[ server | ... ] attendo connesioni");
}
void client(void *pvParameters) {
BLEAddress indirizzoLed(INDIRIZZO_MAC_LED);
// --- connessione all'angel eye ---
bleClient = BLEDevice::createClient();
// BLERemoteService *servizioRemoto = client->getService(BLEUUID("ffe0"));
// BLERemoteCharacteristic *caratteristicaRemota = servizioRemoto->getCharacteristic(BLEUUID("ffe1"));
// --- verificare connessione ---
if (bleClient->connect(indirizzoLed)) {
Serial.println("[ client | ~ ] connessione a angel eye effetuata!");
servizioRemoto = bleClient->getService(BLEUUID("ffe0"));
// --- creazione e gestione servizio remoto ---
if (servizioRemoto == nullptr) {
Serial.println("[ client | ! ] è stato impossibile trovare il servizio con UUID=ffe0");
} else {
Serial.println("[ client | ~ ] servizio con UUID=ffe0 trovato");
}
caratteristicaRemota = servizioRemoto->getCharacteristic(BLEUUID("ffe1"));
// --- creazione e gestione caratteristica remota ---
if (caratteristicaRemota == nullptr) {
Serial.println("[ client | ! ] è stato impossibile trovare la caratteristica con UUID=ffe1");
} else {
Serial.println("[ client | ~ ] caratteristica con UUID=ffe1 trovato");
}
} else {
Serial.println("[ client | ! ] connessione a angel eye fallita!");
}
// --- deallocare la memoria dedicata al client per evitare leak ---
delete bleClient;
// --- termina il task parallelo ---
vTaskDelete(NULL);
}
void loop() {
if (coloreAggiornato) {
Serial.print("rgb[0]: ");
Serial.println(rgb[0]);
Serial.print("rgb[1]: ");
Serial.println(rgb[1]);
Serial.print("rgb[2]: ");
Serial.println(rgb[2]);
String rgbString = String(rgb[0]) + String(rgb[1]) + String(rgb[2]);
const char* utf8Data = rgbString.c_str();
uint8_t data[] = {123, 255, 7, utf8Data[0], utf8Data[1], utf8Data[2], 0, 255, 191};
Serial.println(sizeof(data));
Serial.println(sizeof(rgb));
for (int i = 0; i < 9; i++) {
Serial.println(data[i]);
}
caratteristicaRemota->writeValue(data, 9);
coloreAggiornato = false;
}
if(animazioneAggiornata) {
Serial.println("animazione aggiornata");
animazioneAggiornata = false;
}
}
scusatemi se mi sono dilungato, e se non mi sono spiegato bene,
grazie in anticipo