We have finally figured out what is happening here, which includes a deeper understanding of how BLE works and how the DeviceOS BLE class actually should be used. Our initial code simply set the BLE name, and then appended our service id to the advertising data like this:
// as part of STARTUP ->
String id;
id = "AQ1-" + System.deviceID().substring(15); // AQI-last 9 of id
BLE.setDeviceName(id.c_str());
...
// within setup()
BLE.on();
// Add ESS characteristics to service
BLE.addCharacteristic(aqiCharacteristic);
BLE.addCharacteristic(vocCharacteristic);
BLE.addCharacteristic(co2Characteristic);
BLE.addCharacteristic(temperatureCharacteristic);
BLE.addCharacteristic(humidityCharacteristic);
BLE.addCharacteristic(pm1Characteristic);
BLE.addCharacteristic(pm25Characteristic);
BLE.addCharacteristic(pm10Characteristic);
// Advertising data setup
BLE.setAdvertisingInterval(1600); // interval set at 1s
BleAdvertisingData advData;
// only advertise the ESS service
advData.appendServiceUUID(uuidEnvironmentalSensingService);
BLE.advertise(&advData); // Start advertising
This actually works on almost every BLE host device in the US; iphone, android, Windows, Mac, iPad, ... The Particle device (Argon, Photon 2, Boron) advertises and you can use a scanner and see your named device in a scan list, connect, and read data. This does NOT work on some older Android devices in the US and for some reason also does NOT work on almost all mobile devices, tablets or computers in the EU.
When you read the the DeviceOS docs, this coding seems like a good way to accomplish naming your BLE device other than the default name. When you test it here in the US you'll likely find it works. I do not know for sure how the BLE.setDeviceName() function works but assume it must shove the name into the advertising data - and it must be preserved to some extent when later in setup() we create our advData and append our service id. Whatever BLE.setDeviceName() does, it must not be 100% according to BLE specs as this does NOT work worldwide. So we have learned that BLE.setDeviceName() should ONLY be used as part of Particle's provisioning mode (which we do not use.)
The correct way to startup BLE and name your device something other than the default is to build out your advertising data directly like this:
// within setup()
BLE.on();
BLE.addCharacteristic(aqiCharacteristic);
BLE.addCharacteristic(vocCharacteristic);
BLE.addCharacteristic(co2Characteristic);
BLE.addCharacteristic(temperatureCharacteristic);
BLE.addCharacteristic(humidityCharacteristic);
BLE.addCharacteristic(pm1Characteristic);
BLE.addCharacteristic(pm25Characteristic);
BLE.addCharacteristic(pm10Characteristic);
// Advertising data setup
BLE.setAdvertisingInterval(1600); // interval set at 1s
BleAdvertisingData advData;
// the flags are automatically included in advData so these next two lines not needed
//uint8_t flagsValue = BLE_SIG_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
//advData.append(BleAdvertisingDataType::FLAGS, &flagsValue, sizeof(flagsValue));
String bleIdFull;
bleIdFull = "PRE-" + System.deviceID().substring(15); // PRE-last 9 of id
advData.append(BleAdvertisingDataType::COMPLETE_LOCAL_NAME, (uint8_t*)&bleIdFull.c_str()[0], bleIdFull.length());
// only advertise the ESS service
advData.appendServiceUUID(uuidEnvironmentalSensingService);
BLE.advertise(&advData); // Start advertising
This method works on all devices we have had access to in the US and the EU. Of course you must be mindful of the length of advData so you don't use more than the max 31 bytes. So in this process you might be forced to truncate the name for instance if your service id is longer than 2 bytes like ours or you need to include additional data. Here is a great explanation for what an advertising packet looks like and is composed -> https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/lessons/lesson-2-bluetooth-le-advertising/topic/advertisement-packet/.
Long story short? DON'T use BLE.setDeviceName() to set your BLE device name.