Request for info - Dynamic MachineData Advertising/BroadCast
Please could I ask for some help with getting Dynamic MachineData Advertising / BroadCast working?
I have Googled and LLM my way to what I think should work, but keep running into
E NimBLEAdvertisementData: Data length exceeded
my function been:
void setAdvertisingData() {
NimBLEAdvertisementData advData = pAdvertising->getAdvertisementData(); // Get existing data
uint8_t manufacturerData[12];
manufacturerData[0] = 0xff; // manufacturer data value - custom
manufacturerData[1] = 0xff;
manufacturerData[2] = 0xa0; // begin sig
manufacturerData[3] = 0x00;
manufacturerData[4] = advertiseInterval; // how often broadcast
manufacturerData[5] = batteryLevel; // battery level
manufacturerData[6] = chargingState; // charging state
manufacturerData[7] = uint8_t(internalTempInt); // temp of SOC
manufacturerData[8] = uint8_t(internalTempDec); // temp below decimal
manufacturerData[9] = 0x00; // end sig
manufacturerData[10] = 0xa0;
advData.setManufacturerData(std::string((char *)manufacturerData, sizeof(manufacturerData)));
pAdvertising->setAdvertisementData(advData);
}
First call works correctly, but future calls fails with the Data length exceeded.
I was not able to find any examples that did this, thou I did find a few PRs and issues that refer to this. I was also not able to following the Classes reference, like removeData() int, but which int Types?
Thinking I might need to remove the old setManufacturerData before updating and refreshAdvertisingData?
I was also wondering how I could get the Advertising data length? This is limited to 31 characters, if I understand. Would be nice to catch and oversized data length. I was not sure if sizeof(NimBLEAdvertisementData::getPayload()) would be correct.
If seeing the rest of my sketch is helpful - esp32base-test
When updating the advertised data you need to first clear all of the existing data and rebuild the entire advertisement with the new data. Unfortunately there is no way to update just a part of the data because of varying lengths of some types which would be a pain to work around, easier just to erase and add it all again.
Thank @h2zero
Mind if I ask what I think are some very basic questions? Sorry, I currently only have very basic C skills.
Using the base or starting advertising data as a template and then copy this into a new Advertising Data, and add the updated setManufacturerData possibility?
Think I tried that, but now I am thinking I was getting the current Advertising data and then adding the custom data.
I will try and might have more questions. Thanks for a great library. More implementation documentation could be helpful for newbie like me. The examples help did help.
The recommended way to do this is to call clearData then add all your data back in and update the advertisement.
Thanks, I will try as soon as I get a chance.
Just for completeness, I finally got this working as follows
// Set custom advertising with HID Service UUID
void setAdvertisingData() {
NimBLEAdvertisementData adData;
Serial.println("Clearing old advertisement data...");
pAdvertising->clearData(); // Important: Clear old advertisement data
//adData.clearData();
adData.setAppearance(HID_GAMEPAD);
adData.setShortName("lgp");
adData.addTxPower();
adData.addServiceUUID(hidDevice->getHidService()->getUUID());
// Add battery level to Manufacturer Data
uint8_t manufacturerData[10];
//manufacturer code (0x02E5 for Espressif)
manufacturerData[0] = 0xff; // manufacturer data value - custom
manufacturerData[1] = 0xff;
manufacturerData[2] = 0xa0; // begin sig
manufacturerData[3] = 0x00;
manufacturerData[4] = advertiseInterval; // how often broadcast
manufacturerData[5] = batteryLevel; // battery level
manufacturerData[6] = chargingState; // charging state
manufacturerData[7] = uint8_t(internalTempInt); // temp of SOC
manufacturerData[8] = uint8_t(internalTempDec); // temp below decimal
manufacturerData[9] = 0x00; // end sig
adData.setManufacturerData(std::string((char *)manufacturerData, sizeof(manufacturerData)));
// Debug: Check total advertisement data size
size_t adSize = adData.getPayload().size();
Serial.printf("Advertisement Data Size: %d bytes (Max: 31 bytes)\n", adSize);
if (adSize > 31) {
Serial.println("⚠️ Warning: Advertisement data exceeds 31 bytes!");
} else {
Serial.println("✅ Advertisement data is within limits.");
}
pAdvertising->setAdvertisementData(adData);
// clearData resets flags to BLE_HS_ADV_F_DISC_GEN
pAdvertising->setConnectableMode(BLE_GAP_CONN_MODE_UND);
pAdvertising->setDiscoverableMode(BLE_GAP_DISC_MODE_GEN);
}
I have two last questions in the quest to understand as much as possible.
First, what does BLE_HS_ADV_F_DISC_GEN stand for? BLE, HS (High Speed?), ADV (Advertisement), F (Function or Full?), GEN (General) - bad guess
Second question, is getPayload, does not include the two control bytes or is this three byte or am I missing something else? The reason I ask, is that I found that things work if the getPayload is 28 bytes, anything else seems to exceed the advertising limit.
Thanks again.
Glad you got it working.
First, what does BLE_HS_ADV_F_DISC_GEN stand for? BLE, HS (High Speed?), ADV (Advertisement), F (Function or Full?), GEN (General) - bad guess
These macros are named by the devs at Apache-Mynewt. This one is BLE Host advertisement flag generally <-> discoverable.
Second question, is getPayload, does not include the two control bytes or is this three byte or am I missing something else? The reason I ask, is that I found that things work if the getPayload is 28 bytes, anything else seems to exceed the advertising limit.
The first 3 bytes are occupied by the mandatory advertisement flags data.
Glad you got it working.
Thank you, and thanks for your super awesome library!
First, what does BLE_HS_ADV_F_DISC_GEN stand for? BLE, HS (High Speed?), ADV (Advertisement), F (Function or Full?), GEN (General) - bad guess
These macros are named by the devs at Apache-Mynewt. This one is BLE Host advertisement flag generally <-> discoverable.
I would not have guest Host, but now I can see it. Is there a place where one could see what these macros might mean? I really don't like buggy anybody, especially busy people like yourself, that are doing awesome stuff.
Second question, is getPayload, does not include the two control bytes or is this three byte or am I missing something else? The reason I ask, is that I found that things work if the getPayload is 28 bytes, anything else seems to exceed the advertising limit.
The first 3 bytes are occupied by the mandatory advertisement flags data.
Thanks, I did think there was only two bytes, not sure where I saw that. Confirmation also saved my sanity. ;-)
If I could wish for things in regards to NimBLE-Arduino, is a little more resources or documentation on implementation. A low skilled tinker like myself hopefully would not bug the community so often.