我正在使用
ESP32-WROOM-32
开发 BLE 应用程序。
一切都很好,但有一个我无法解决的奇怪行为:我有 5 个特征,其中 4 个是只读的,一个是只写的。每个特征都有一个描述符,其值表示该特征的内容。
如果我为每个特征分配一个描述符,则只写特征无法获得其值
#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);
}
如果我删除其中一个描述符,那么一切都会正常工作
#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);
}
如果我将只写特性放在单独的服务上,它就可以工作
#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);
}
这是否意味着每个服务最多可以有 4 个带有值描述符的特征?我听起来真的很奇怪!
我不知道怎么做,但我找到了问题和解决方案,而且也非常简单明了。
ESP32 根据设计,在 BLEService 默认情况下最多处理 15 个处理程序。但是,可以通过在调用构造函数时指定它来更改处理程序的数量(因为它重载了 2 个构造函数)。
所以而不是做
BLEService *pService = pServer->createService(SERVICE_UUID);
我们只是做
BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID), 20);
还有田田!一切正常! 来自官方文档
一个特征使用 2 个处理程序,而一个描述符使用 1 个
这意味着对于带有描述符的每个特征,我们至少需要 3 个处理程序。如果描述符和/或特征包含数据(例如值),处理程序的数量就会增加,一旦 ESP32 饱和其默认功能,它就会停止添加内容。
我不确定这是否是 C/C++ 限制,但引发的运行时错误肯定有助于识别问题。
希望有帮助!