My ESP32-based custom-PCB BLE peripheral is advertising LiFP batteries dynamic physical values, such as current or SoC (State of Charge).
Basically, the code is as follows:
/// Returns the manufacturer data as a String
void Ble :: setAdvertisingManufacturerData(BLEAdvertisementData *advertisementData) {
const float soc = battery.getSoc();
log("Advertising Soc %d%%", soc);
const char bytes[] = {
(manCode>>8)&0xff, manCode&0xff,
// SoC: 2 bytes | 0~2 bytes
(soc>>8)&0xff, soc&0xff,
};
advertisementData->setManufacturerData(std::string(bytes, sizeof(bytes)));
}
/// Prepares the advertising manif data
void Ble :: advertise() {
BLEAdvertisementData advertisementData;
advertisementData.setFlags(0x6);
setAdvertisingManufacturerData(&advertisementData);
pAdvertising = BLEDevice::getAdvertising();
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
pAdvertising->setAdvertisementData(advertisementData);
pAdvertising->start();
}
void Ble :: setup() {
// == Start the advertising
advertise();
}
/// Dynamically advertises every seconds
void Ble :: loop() {
// == Dynamically advertise
static unsigned lastAdvertised = 0;
const unsigned now = millis();
if (!lastAdvertised || now - lastAdvertised > 1000) {
lastAdvertised = now;
BLEAdvertisementData scanResponse;
setAdvertisingManufacturerData(&scanResponse);
pAdvertising->stop();
pAdvertising->setScanResponseData(scanResponse);
pAdvertising->start();
}
}
So far so good. But from the Flutter app, the advertisement manufacturer data still shows SoC to be zero (aka the initial value) despite the evolving value I see in my ESP32 logs.
I probably made a mistake, any help welcome!
[UPDATE] With the nRF mobile app I get this:
And I see there are two sections with type 0x09: the first one is "empty" while the second has the right data.
I finally did that, that makes my advertising being dynamic.
I removed the setScanResponseData()
and replaced by another call of setAdvertisementData()
as I do in advertise()
.
But I still don't get what setScanResponseData()
is for.
void Ble :: loop() {
// == Dynamically advertise
static unsigned lastAdvertised = 0;
const unsigned now = millis();
if (!lastAdvertised || now - lastAdvertised > 5000) {
lastAdvertised = now;
log("Dynamic advertising");
BLEAdvertisementData scanResponse;
std::string md = getAdvertisingManufacturerData();
setAdvertisingManufacturerData(md, &scanResponse);
pAdvertising->stop();
//pAdvertising->setScanResponseData(scanResponse);
pAdvertising->setAdvertisementData(scanResponse);
pAdvertising->start();
}
}