Dear all
I am trying to send data through BLE on a ESP32. I have one model code working. However, in this code [setup given below], the BLE server is not coming up OR it is not advertising.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
void setup()
{
Serial.begin(115200);
Serial.println("ready to connect");
// set up all the pins here
pinMode(step, OUTPUT);
pinMode(dir,OUTPUT);
pinMode(led,OUTPUT);
// set the direction to LOW - for microstepper
digitalWrite(dir,LOW);
// Initiate BLE Device
BLEDevice::init("InsulinPump");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyCallBacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
// set periodic dose for patient
periodic_dose = set_periodic_dose();
//start timer
old_timer=millis();
// use these characteristics alone
insulinUnits = pService->createCharacteristic(CHARACTERISTIC_UUID2, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
insulinDeliveryAlarms = pService->createCharacteristic(CHARACTERISTIC_UUID7, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
// set up service notification
// use these Descriptors alone
insulinUnits->addDescriptor(new BLE2902());
insulinDeliveryAlarms->addDescriptor(new BLE2902());
// Start BLE Service
pService->start();
BLEAdvertising *pAdvert = BLEDevice::getAdvertising();
pAdvert->addServiceUUID(SERVICE_UUID);
pAdvert->setScanResponse(true);
BLEDevice::startAdvertising();
}
I tried something VERY similar in another test code:
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("BLE Starting");
BLEDevice::init("ESP32_BLE");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyCallBacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pChar = pService->createCharacteristic(CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
loopCount = pService->createCharacteristic(CHARACTERISTIC_UUID2,BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
loopCount->addDescriptor(new BLE2902());
pChar->setValue("Hello Human!");
pService->start();
BLEAdvertising *pAdvert = BLEDevice::getAdvertising();
pAdvert->addServiceUUID(SERVICE_UUID);
pAdvert->setScanResponse(true);
BLEDevice::startAdvertising();
}
And this one works perfectly.
The declarations for BLECharacteristics insulinUnits and insulinDeliveryAlarms are set properly as a global variable. The program compiles fine and is getting uploaded to the ESP32 fine as well.
Except for the variable names / UUIDs, I haven't changed anything. I checked whether all the steps are covered, and couldn't find anything amiss.
What am I doing wrong? Thanks in advance.
Adding more details.
When I went from a random UUID 31ecc430-4307-4ea3-957c-efa4807edbd5 to Insulin pump UUID 0x0D40 (GATT designated service UUID), the code compiles and uploads, but the server doesn't advertise.
Please provide complete code which compiles and can be tested by others. The snippets of the original post are not the way to get help on this forum.
Should have done it - here is the full code. The original problem got resolved when I went from 0x0D40 for SERVICE_UUID to 00000D40 (added 4 zeros to the beginning). So, that is done. Now there is another one. Problem statement below the code block.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2901.h>
#include <BLE2902.h>
// Define all UUIDs here
#define SERVICE_UUID "00000D40"
#define CHARACTERISTIC_UUID1 "3a64dc90-7039-40de-b76a-448cc47e1e0d"
#define CHARACTERISTIC_UUID2 "145015be-6f8a-46ea-a040-96ec9b71d74a"
#define CHARACTERISTIC_UUID3 "d1148a0a-e83a-469f-af8e-da2891d13e01"
#define CHARACTERISTIC_UUID4 "7685fcea-b736-4bce-818d-1ff52019ddea"
#define CHARACTERISTIC_UUID5 "69613f83-3cdd-46ac-9e44-f50ff9308991"
#define CHARACTERISTIC_UUID6 "e509f87a-bdaa-46b5-9131-b3aa8454645b"
#define CHARACTERISTIC_UUID7 "3a645bfb-f437-4f51-992a-1904620242e1"
// Declare all global variables here.
int l = 0;
std::string message="";
float total_dose = 60; // 300 is the default value
float decrement = 1; // 0.25 is the default value
const int step = 33; // PIN for STEP signal from ESP32
const int dir = 32; // PIN for DIR signal from ESP32
const int led = 2 ; // LED for testing code / response. Will be defunct in final version.
int total_steps = 0;
float dose_units = 0;
float remaining_units = 60; // 300 is the default value
//int total_dose = 300; // adjust this based on the total capacity of the reservoir
int periodic_dose = 8; // set to steps per 15 mins
long timer, old_timer;
long time_gap = 5000 ;// 60 * 1000 * 15 900 * 1000 => 9E5
char buffer[16]={0};
bool deviceConnected = false;
std::string warning_message;
// Declare BLECharacteristic variables
BLECharacteristic *insulinRemaining = NULL;
BLECharacteristic *insulinUnits = NULL; // send (milli) units delivered
BLECharacteristic *insulinDeliveryMode = NULL; // Predefined values?
//BLECharacteristic *insulinDeliveryStatus = NULL; // send as notification?
//BLECharacteristic *insulinControlPoint = NULL; // should be part of Insulin client?
//BLECharacteristic *insulinHistory = NULL; // ??
BLECharacteristic *insulinDeliveryAlarms = NULL; // Annunciation characteristic
// Server Callback Class
class MyCallBacks: public BLEServerCallbacks
{
void onConnect(BLEServer* pServer)
{
deviceConnected=true;
}
void onDisconnect(BLEServer* pServer)
{
deviceConnected=false;
}
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("BLE Starting");
// Start device, server and service for BLE.
BLEDevice::init("ESP32_BLE");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyCallBacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
// Assign all characteristic pointers to service
insulinRemaining = pService->createCharacteristic(CHARACTERISTIC_UUID1, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
insulinUnits = pService->createCharacteristic(CHARACTERISTIC_UUID2, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
insulinDeliveryMode = pService->createCharacteristic(CHARACTERISTIC_UUID3, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
insulinDeliveryAlarms = pService->createCharacteristic(CHARACTERISTIC_UUID4, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
//insulinDeliveryStatus = pService->createCharacteristic(CHARACTERISTIC_UUID5, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
//insulinControlPoint = pService->createCharacteristic(CHARACTERISTIC_UUID6, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
//insulinHistory = pService->createCharacteristic(CHARACTERISTIC_UUID7, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);
/* insulinRemaining, insulinUnits, insulinDeliveryMode, insulinDeliveryStatus,
insulinControlPoint, insulinHistory, insulinDeliveryAlarms*/
// Add Descriptor to all characteristics
BLE2901 *IUDesc = new BLE2901();
IUDesc->setDescription("Units Delivered");
insulinUnits->addDescriptor(new BLE2902());
insulinUnits->addDescriptor(IUDesc);
BLE2901 *IRDesc = new BLE2901();
IRDesc->setDescription("Units Remaining");
insulinRemaining->addDescriptor(IRDesc);
insulinRemaining->addDescriptor(new BLE2902());
BLE2901 *IDMDesc = new BLE2901();
IDMDesc->setDescription("Delivery Mode");
insulinDeliveryMode->addDescriptor(IDMDesc);
insulinDeliveryMode->addDescriptor(new BLE2902());
BLE2901 *IDADesc = new BLE2901();
IDADesc->setDescription("Ding Dong");
insulinDeliveryAlarms->addDescriptor(new BLE2902());
insulinDeliveryAlarms->addDescriptor(IDADesc);
/*
BLE2901 *IDSDesc = new BLE2901();
IDSDesc->setDescription("Delivery Status");
insulinDeliveryStatus->addDescriptor(IDSDesc);
insulinDeliveryStatus->addDescriptor(new BLE2902());
insulinControlPoint->addDescriptor(new BLE2902());
insulinHistory->addDescriptor(new BLE2902());
*/
// start the service and start advertising
pService->start();
BLEAdvertising *pAdvert = BLEDevice::getAdvertising();
pAdvert->addServiceUUID(SERVICE_UUID);
pAdvert->setScanResponse(true);
BLEDevice::startAdvertising();
}
void loop() {
delay(2000);
remaining_units = remaining_units - decrement;
dose_units = dose_units + decrement;
if(deviceConnected)
{
insulinRemaining->setValue(remaining_units);
insulinRemaining->notify();
insulinUnits->setValue(dose_units);
insulinUnits->notify();
if(remaining_units >=10)
{
insulinDeliveryMode->setValue("normal");
insulinDeliveryMode->notify();
insulinDeliveryAlarms->setValue("None");
insulinDeliveryAlarms->notify();
}
if(remaining_units < 10)
{
insulinDeliveryAlarms->setValue("Reservoir Low");
insulinDeliveryAlarms->notify();
insulinDeliveryMode->setValue("Normal. No PPD.");
insulinDeliveryMode->notify();
}
if(remaining_units < 2)
{
insulinDeliveryAlarms->setValue("Reservoir Empty");
insulinDeliveryAlarms->notify();
insulinDeliveryMode->setValue("Stopped");
insulinDeliveryMode->notify();
delay(10000);
remaining_units=60;
dose_units=0;
}
}
}
Problem - I am trying to set notify on InsulinDeliveryAlarms. I am not getting it. I am following the same method I have done for the other three (DeliveryMode, Units, Remaining). They all seem to work fine. Again, should be something very basic that I am missing here.
(either that, or my ESP32 is acting funny).
This is the part that trips me up. The first block, involving IDMDesc works fine. Two other blocks before that adding two descriptors works fine as well. The last BLE2901 block for IDADesc is not working.
I can confirm your issue, but I have not found the cause.
Hi @cattledog - thanks for trying the code and confirming the issue. Upon digging a bit more, I found that the fourth BLE2901 descriptor works if I comment out the third (or the second) descriptor assignment. It seems the Service can take only 3 BLE2901 Descriptors. I still don't have a solution though.
Thanks for any thoughts in advance.
Solved this issue (thanks Gemini)
There seems to be a default limit of "handles" that are provided to a service. The calculation is as follows:
No. of handles for a service = 1
No. of handles for a characteristic = 2
No. of handles for each descriptor (BLE2901 or BLE2902) = 1
For 4 characteristics, the total handles are as follows:
1 + (2 x 4) + (1 x 3 BLE2901) + (1 x 3 BLE2902) = 15. This is the default limit. Therefore additional descriptors don't have space to be assigned. However, this doesn't interfere with the compilation or functionality.
The solution is to declare the number of descriptors needed while declaring the service.
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID),30);
Also note - the original pService declaration of
BLEService *pService = pServer->createService(SERVICE_UUID); - doesn't work. It has to be specified as a BLEUUID variable specifically (as shown in code block above). Now the code compiles, and I can see the characteristic BLE2901 descriptors.
// closing this issue //