BLE Generic Access Service characteristics not showing up

I wrote a little app to advertise Generic Access Service characteristics. When I run the code, the service shows up, but the characteristics do not. Any ideas?

#include "Particle.h"

SYSTEM_MODE(MANUAL); // No Particle Mesh used

const char * devName = "MyDevice";
const unsigned long UPDATE_INTERVAL_MS = 1000;
unsigned long lastUpdate = 0;

BleAdvertisingData advData;

BleUuid genericAccessService(BLE_SIG_UUID_GENERIC_ACCESS_SVC);
BleCharacteristic deviceNameCharacteristic("devName",
    BleCharacteristicProperty::NOTIFY,
    BleUuid(BLE_SIG_UUID_DEVICE_NAME_CHAR), genericAccessService);
BleCharacteristic deviceAppearanceCharacteristic("devAppearance",
    BleCharacteristicProperty::NOTIFY,
    BleUuid(BLE_SIG_UUID_APPEARANCE_CHAR), genericAccessService);

void setup() {
    BLE.addCharacteristic(deviceNameCharacteristic);
    BLE.addCharacteristic(deviceAppearanceCharacteristic);

    advData.appendServiceUUID(genericAccessService);

    deviceNameCharacteristic.setValue(devName);
    deviceAppearanceCharacteristic.setValue(BLE_SIG_APPEARANCE_GENERIC_TAG);

    BLE.advertise(&advData);
}

void loop() {
    if ( millis() - lastUpdate >= UPDATE_INTERVAL_MS ) {
        lastUpdate = millis();

        if ( BLE.connected() ) {
            deviceNameCharacteristic.setValue(devName);
            deviceAppearanceCharacteristic.setValue(BLE_SIG_APPEARANCE_GENERIC_TAG);
        }
    }
}

Just an off-the-cuff answer:
The advertising data payload is rather limited with 31 bytes and hence can only be a short “excerpt” of its properties/capabilites to “attract interest”. Similar to the blurb on a book cover to make a potential reader buy it to find out more.

e.g. a full UUID taking 16 bytes would not even allow two such UUIDs to be advertised, so the prime service should suffice for a central to decide whether it is interested in connecting to that device and then learn more about its full set of properties and capabilities.

I see, and that makes sense. The fuller code would not advertise GAS, I’m just learning the API.

One thing not shown is in addition to the code above, is I implemented the Battery Level Service in the same app. That shows up in the advertisement along with its characteristic. Thus I’m assuming it’s a bug in my code.

Where does it show up?

With standardised services their standard characterisitcs are also known without the need to actually advertise them. So when an app knows that a peripheral advertises one of these services it can infer that the respective characteristics must be exposed too.
Also standardised services usually feature short UUIDs and hence would leave some space to add some extra info.

So, this is not necessarily an indication for a bug in your code.

Where does it show up?

I'm debugging with standard iOS apps for inspecting BLE devices like BlueSee and LightBlue.

Here's an example of the device showing up.

Here are the services after connecting. Interestingly, the battery service does not show up until I connect.

Here is the GAS detail with no characteristics.

Here is the battery service detail with a characteristic (decrements once a second as a "demo").

I see, you are missing the characteristics when connected - I was of the impression you were missing it in the advertising data before establishing the connection.

That’s a different story :face_with_raised_eyebrow:

Missing in both scenarios. When advertising I see GAS and no characteristics. When connected I see GAS and Batt. Batt has characteristic, GAS still doesn’t.

I added some Serial.print() statements for the initialisation statements in setup() and I do get error responses -250 and -170 (that would be one of the basic debugging steps anybody could take).
I’d have to look up what that means.


Update:
Here are the SYSTEM_ERROR codes

-250 means some SYSTEM_ERROR_INTERNAL (further investigation needed) and -170 (SYSTEM_ERROR_NOT_FOUND) follows since the first call failed any subsequent calls to a non-existent characteristic would return that.

You’d need to follow the lead from instantiating the service to instantiating the characteristics for that service and finally adding the characteristic to the BLE device. In one of these steps something fails (probably due to misconfiguration) and consequently the charateristics can’t be added.

Once again, you’ve had to remind me to do the basics. I’m really sorry about that.

1 Like

I dug a bit deeper and found out that the already existing General Access Service is created by default and application code cannot access it (yet).
Particle is planning to add high level APIs to be used instead of setValue() for the device name characteristic and the appearance.

However, I have proposed to consider opening a way that application code can be granted access to the default services and characteristics to make something like what you intended above may become possible.


Update:
I got to confirmation that GAP and GATT service will be sealed and we’ll have to wait for APIs to set the values of the individual characteristics.

Particle is planning to add high level APIs to be used instead of setValue() for the device name characteristic and the appearance.

Very interesting. I'll just stick to using advData.appendLocalName("some name") for now.

Has there been any updates on this? I still haven’t been able to get characteristics to show up either.