I have read the forums and seen a few posts regarding setManufacturerData(). Of the posts between February and October 2020, it seems the function either doesn't work or it works under certain conditions.
Unfortunately, I cannot get it to work. Although nRF Connect (for iPhone) shows Manufacturer data from other devices it recognises during a scan, it does not show anything for my peripheral (an Arduino Nano 33 IoT), so I am hopeful a) the function from the ArduinoBLE library - I'm using 1.1.13 - is sound and b) it is my poor programming skills. Here's my code snippet:
Thank you, and I appreciate you volunteering to help me and others on this forum.
I made a post but I got an error about "exceeding maximum length (9000 characters)." Anyway, I could not get it to work. I used your sketch. I've attached a screenshot. nRF Connect for iOS, v.2.4.7 build 70; iPhone 5. Any additional comments are welcomed.
I think I managed to get it working. I downloaded the 1.1.13 BLE library. It shows an alternate function layout:
void setManufacturerData(const uint16_t companyId, const uint8_t manufacturerData[], int manufacturerDataLength);
I plugged in some variables and manufacturing data started showing up on nRF Connect. I don't know if that's specific to the app on my iPhone or if that's some kind of BT standard thing, but it seems to work using the 3 parameter function call (at least for me). Thank you anyway!
Follow-up question that is related to my topic: I am switching between being a central and peripheral. When I am a peripheral, I advertise for a little while then stop advertising and become a central. I then repeat that process indefinitely in the loop() section. I've noticed if I don't advertise long enough my manufacturing data is not shown in nRF Connect. In the sample program Klaus_K wrote there is no stopAdvertise() function call and it displays forever.
My question: Is there a method to maintain manufacturing data even after stopAdvertise() is called?
fluffymarshmallow26:
My question: Is there a method to maintain manufacturing data even after stopAdvertise() is called?
Simple answer, No. The manufacturing data is the content of the advertisement packet broadcast by the Arduino. When you call stopAdvertise the information is no longer send out and therefore nRF Connect no longer displays the information.
Did you try becoming a central with advertising still enabled? I did a short test with the Arduino Nano 33 BLE a few days ago and that worked. I am not sure how stable that is. Maybe I will do the same test with the Nano 33 IoT later.
May I ask why you want to use the manufacturing data instead of broadcasting the service UUID? Service UUIDs are much more generic and allow devices from different suppliers to work together. e.g., when you want to get heart rate data, the manufacturer is not important from a software point of view, you need standardized heart rate data.
I am broadcasting the UUID but I also wish to broadcast the manufacturing data, appearance, local name and other factors as precisely as possible. My goal is to scan for an advertising peripheral, "absorb" everything I can from it as a central then turn into a peripheral and advertise the same data - a repeater, as much as possible. I suspect the end device is more intereseted in the UUID but I ultimately do not know for certain.
I have not tested with advertising stuck on; I made the assumption that advertising as a peripheral would interfere with my ability to connect to peripherals as a central. It's a good idea, though and I will try it.
I just tried it and it works. I never disabled advertising (and it's set to the default rate) and I was able to connect to two different LE peripherals without problem - thanks.
The only problem now is I did not see any of the manufacturing data (in nRF Connect), so I'm going to debug that and try and determine where it breaks. I suppose I could set the advertise time to something long like 4 seconds to save a little power.
I am at a loss as to why I can't advertise, do some work, turn off advertising, then repeat in the main loop(). If that is just the functionality of the BLE functions than so be it. Eventually I'll figure it out or deal with some kind of workaround.
After some debugging I learned a couple of things.
You can turn advertising on and off. As soon as a central connects I turn off advertising and I function as a peripheral until the central disconnects. When that happens, I start functioning as a central and start scanning. I repeat everything in the main loop. So, that is good to know about the Nano IoT's radio functionality.
The problem starts when I use:
BLE.setAdvertisedServiceUuid("1234");
or
BLE.setAdvertisedService(testService0);
When I un-comment either one of the above functions the manufacturing data is disabled and nRF Connect either displays "Services: 1234" or "Generic Services." When I comment out both of these functions then the manufacturer data returns. I am at a loss as to why but maybe it's a sequence thing. Here is the general flow:
BLEService testService0("1800"); // straight outta Compton
BLEUnsignedCharCharacteristic testCharacteristic0("2a00", BLEWriteWithoutResponse | BLENotify);
// BLE.setAdvertisedService(testService0);
testService0.addCharacteristic(testCharacteristic0);
BLE.addService(testService0); // add the service after it has been configured
BLE.setLocalName("MyLittlePony");
BLE.setManufacturerData(companyID, mfgBuf, sizeof(mfgBuf)); // declared in header
// BLE.setAdvertisedServiceUuid("1234"); // top-level service ID???
BLE.setConnectable(true);
BLE.advertise();
There are no compiler errors when both functions are un-commented and nRF does display the correct characteristics and services but it will not show manufacturer data. Comments (on this thread) are always welcomed!
If you have a advertisedServiceUUID the manufacturing data is ignored.
I tried fixing it two days ago by removing the else in line 105 but that did not work because the advertisement data size is only 31. This is the standard BLE packet size. And that is not enough for both the service UUID and the manufacturing data.
I tried using the callback routine but was not successful. I also tried keeping advertising on the entire time. It seems there are only a few events that are allowed for the callback: BLEConnected, BLE Disconnected and BLEDiscovered. I want to advertise services before connecting so I was hoping BLEDiscovered would work but it seems that only identifies peripherals and I need an interrupt when a central is scanning.
Prior to connecting I'd like to show Manufacturing Data and at least one Advertised Service like the Google device below. If anyone has any suggestions I am 100% ears and thanks.
fluffymarshmallow26:
Prior to connecting I'd like to show Manufacturing Data and at least one Advertised Service like the Google device below. If anyone has any suggestions I am 100% ears and thanks.
For this to work you need to remove the else in line 105 of the GAP.cpp (see reply #9). This will allow you to advertise a service and manufacturer data. Right now the library allows only one or the other.
Then you need to make sure your manufacturer data and service UUID do not exceed 22 bytes. e.g.
16-bit Service UUID (2 bytes) + 20 bytes manufacturer data
128-bit Service UUID (16 bytes) + 6 bytes manufacturer data
The rest of the advertising data (total 31 bytes) will be 2 bytes manufacturer UUID plus overhead 7 bytes.
If you want to send service data in the advertisement you would need take it from the 22 bytes.
You can find all this in the GAPP.cpp -> GAPClass::advertise(). There you can see how the advertisingData is filled.
Things are so much better with ArduinoBLE library v1.2.0. I can not only see Manufacturer Data now I get all the values from the characteristics descriptors. I had no idea how much data I was missing with v1.1.3. The only gotcha I can report is that I have to set the top-level service level ID
BLE.setAdvertisedServiceUuid("fe9c");
after all the services are instantiated/enabled. If I do it prior, it just turns into zeroes after I start adding primary and secondary services. It seems there is a sequence.
Now if I could only figure out why my memory is fragmenting if I don't put some variables and arrays outside functions I'll be good! That is another thread...