0

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);
}

Descriptor not working

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);
}

enter image description here

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);
}

enter image description here enter image description here

Could this mean that I can have a maximum of 4 characteristics with value-descriptors per service? It sounds really weird to me!

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Ale TheFe
  • 1,540
  • 15
  • 43

0 Answers0