I'm developing a BLE application using a ESP32-WROOM-32
.
Everything works great, but there's a strange behavior that I can't address: I have 5 characteristics, 4 are read-only and one is write-only. Every characteristic has a descriptor, whose value indicates the content of the characteristic.
If I assign a descriptor to every characteristic, the write-only one doesn't get its value
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_1 "7285ab1e-217e-4595-97a1-85975fe801b3"
#define CHARACTERISTIC_UUID_2 "248386d7-cda1-4ffd-a45b-502a7e709ce9"
#define CHARACTERISTIC_UUID_3 "88ac4be2-45e9-4578-9459-124066251e22"
#define CHARACTERISTIC_UUID_4 "596639c8-d4de-4562-9365-7ee0d5409812"
#define CHARACTERISTIC_UUID_5 "945353c0-b3a4-4946-bab7-85da9c8346e3"
BLECharacteristic *pCharacteristic1, *pCharacteristic2, *pCharacteristic3, *pCharacteristic4, *pCharacteristic5;
class ServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer)
{
Serial.println(F("Connected"));
};
void onDisconnect(BLEServer *pServer)
{
Serial.println(F("Disconnected"));
BLEDevice::startAdvertising();
}
};
class WriteCharacteristicCallback : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic, esp_ble_gatts_cb_param_t *param)
{
Serial.print(F("Received data: value is "));
Serial.println((pCharacteristic->getValue()).c_str());
}
};
void setup()
{
Serial.begin(115200);
Serial.println("\n");
Serial.println(F("Setup started"));
BLEDevice::init("TEST Descriptors");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic1 = pService->createCharacteristic(
CHARACTERISTIC_UUID_1,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic2 = pService->createCharacteristic(
CHARACTERISTIC_UUID_2,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic3 = pService->createCharacteristic(
CHARACTERISTIC_UUID_3,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic4 = pService->createCharacteristic(
CHARACTERISTIC_UUID_4,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic5 = pService->createCharacteristic(
CHARACTERISTIC_UUID_5,
BLECharacteristic::PROPERTY_WRITE);
BLEDescriptor *pCharacteristicDescriptor1 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor2 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor3 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor4 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor5 = new BLEDescriptor("2901");
pCharacteristicDescriptor1->setValue("CHARACTERISTIC 1");
pCharacteristic1->addDescriptor(pCharacteristicDescriptor1);
pCharacteristicDescriptor2->setValue("CHARACTERISTIC 2");
pCharacteristic2->addDescriptor(pCharacteristicDescriptor2);
pCharacteristicDescriptor3->setValue("CHARACTERISTIC 3");
pCharacteristic3->addDescriptor(pCharacteristicDescriptor3);
pCharacteristicDescriptor4->setValue("CHARACTERISTIC 4");
pCharacteristic4->addDescriptor(pCharacteristicDescriptor4);
pCharacteristicDescriptor5->setValue("CHARACTERISTIC 5");
pCharacteristic5->addDescriptor(pCharacteristicDescriptor5);
pCharacteristic5->setCallbacks(new WriteCharacteristicCallback());
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
BLEDevice::startAdvertising();
Serial.println(F("Setup done"));
}
void loop()
{
delay(5000);
}
If I remove one of the descriptors then everything works
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_1 "7285ab1e-217e-4595-97a1-85975fe801b3"
#define CHARACTERISTIC_UUID_2 "248386d7-cda1-4ffd-a45b-502a7e709ce9"
#define CHARACTERISTIC_UUID_3 "88ac4be2-45e9-4578-9459-124066251e22"
#define CHARACTERISTIC_UUID_4 "596639c8-d4de-4562-9365-7ee0d5409812"
#define CHARACTERISTIC_UUID_5 "945353c0-b3a4-4946-bab7-85da9c8346e3"
BLECharacteristic *pCharacteristic1, *pCharacteristic2, *pCharacteristic3, *pCharacteristic4, *pCharacteristic5;
class ServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer)
{
Serial.println(F("Connected"));
};
void onDisconnect(BLEServer *pServer)
{
Serial.println(F("Disconnected"));
BLEDevice::startAdvertising();
}
};
class WriteCharacteristicCallback : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic, esp_ble_gatts_cb_param_t *param)
{
Serial.print(F("Received data: value is "));
Serial.println((pCharacteristic->getValue()).c_str());
}
};
void setup()
{
Serial.begin(115200);
Serial.println("\n");
Serial.println(F("Setup started"));
BLEDevice::init("TEST Descriptors");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic1 = pService->createCharacteristic(
CHARACTERISTIC_UUID_1,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic2 = pService->createCharacteristic(
CHARACTERISTIC_UUID_2,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic3 = pService->createCharacteristic(
CHARACTERISTIC_UUID_3,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic4 = pService->createCharacteristic(
CHARACTERISTIC_UUID_4,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic5 = pService->createCharacteristic(
CHARACTERISTIC_UUID_5,
BLECharacteristic::PROPERTY_WRITE);
BLEDescriptor *pCharacteristicDescriptor1 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor2 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor3 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor4 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor5 = new BLEDescriptor("2901");
pCharacteristicDescriptor1->setValue("CHARACTERISTIC 1");
pCharacteristic1->addDescriptor(pCharacteristicDescriptor1);
pCharacteristicDescriptor2->setValue("CHARACTERISTIC 2");
pCharacteristic2->addDescriptor(pCharacteristicDescriptor2);
pCharacteristicDescriptor3->setValue("CHARACTERISTIC 3");
pCharacteristic3->addDescriptor(pCharacteristicDescriptor3);
pCharacteristicDescriptor4->setValue("CHARACTERISTIC 4");
// pCharacteristic4->addDescriptor(pCharacteristicDescriptor4);
pCharacteristicDescriptor5->setValue("CHARACTERISTIC 5");
pCharacteristic5->addDescriptor(pCharacteristicDescriptor5);
pCharacteristic5->setCallbacks(new WriteCharacteristicCallback());
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
BLEDevice::startAdvertising();
Serial.println(F("Setup done"));
}
void loop()
{
delay(5000);
}
If I put the write-only characteristic on a separate service it works
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define WRITE_SERVICE_UUID "1f425e27-0174-4591-b081-45732e0d93ad"
#define CHARACTERISTIC_UUID_1 "7285ab1e-217e-4595-97a1-85975fe801b3"
#define CHARACTERISTIC_UUID_2 "248386d7-cda1-4ffd-a45b-502a7e709ce9"
#define CHARACTERISTIC_UUID_3 "88ac4be2-45e9-4578-9459-124066251e22"
#define CHARACTERISTIC_UUID_4 "596639c8-d4de-4562-9365-7ee0d5409812"
#define CHARACTERISTIC_UUID_5 "945353c0-b3a4-4946-bab7-85da9c8346e3"
BLECharacteristic *pCharacteristic1, *pCharacteristic2, *pCharacteristic3, *pCharacteristic4, *pCharacteristic5;
class ServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer)
{
Serial.println(F("Connected"));
};
void onDisconnect(BLEServer *pServer)
{
Serial.println(F("Disconnected"));
BLEDevice::startAdvertising();
}
};
class WriteCharacteristicCallback : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic, esp_ble_gatts_cb_param_t *param)
{
Serial.print(F("Received data: value is "));
Serial.println((pCharacteristic->getValue()).c_str());
}
};
void setup()
{
Serial.begin(115200);
Serial.println("\n");
Serial.println(F("Setup started"));
BLEDevice::init("TEST Descriptors");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
BLEService *pWriteService = pServer->createService(WRITE_SERVICE_UUID);
pCharacteristic1 = pService->createCharacteristic(
CHARACTERISTIC_UUID_1,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic2 = pService->createCharacteristic(
CHARACTERISTIC_UUID_2,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic3 = pService->createCharacteristic(
CHARACTERISTIC_UUID_3,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic4 = pService->createCharacteristic(
CHARACTERISTIC_UUID_4,
BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pCharacteristic5 = pWriteService->createCharacteristic(
CHARACTERISTIC_UUID_5,
BLECharacteristic::PROPERTY_WRITE);
BLEDescriptor *pCharacteristicDescriptor1 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor2 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor3 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor4 = new BLEDescriptor("2901");
BLEDescriptor *pCharacteristicDescriptor5 = new BLEDescriptor("2901");
pCharacteristicDescriptor1->setValue("CHARACTERISTIC 1");
pCharacteristic1->addDescriptor(pCharacteristicDescriptor1);
pCharacteristicDescriptor2->setValue("CHARACTERISTIC 2");
pCharacteristic2->addDescriptor(pCharacteristicDescriptor2);
pCharacteristicDescriptor3->setValue("CHARACTERISTIC 3");
pCharacteristic3->addDescriptor(pCharacteristicDescriptor3);
pCharacteristicDescriptor4->setValue("CHARACTERISTIC 4");
pCharacteristic4->addDescriptor(pCharacteristicDescriptor4);
pCharacteristicDescriptor5->setValue("CHARACTERISTIC 5");
pCharacteristic5->addDescriptor(pCharacteristicDescriptor5);
pCharacteristic5->setCallbacks(new WriteCharacteristicCallback());
pService->start();
pWriteService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->addServiceUUID(WRITE_SERVICE_UUID);
BLEDevice::startAdvertising();
Serial.println(F("Setup done"));
}
void loop()
{
delay(5000);
}
Could this mean that I can have a maximum of 4 characteristics with value-descriptors per service? It sounds really weird to me!