5 years, 6 months ago.

GATT Server - sending non-numeric data as part of custom GATT Service

Hi

Apologies, as ever, for my stupidity - I'm still fairly new to all this.

I have edited the BLE_BatteryLevel example to create my own GATT service. This works fine, and I can connect and listen to the updated values. However, I'd like to be able to send data other than a numeric value representing the battery level. This is theoretically possible, according to Kevin Townsend's book "Getting Started with Bluetooth Low Energy" - I should be able to send any data I like (within the size limitations) but I can't work how how to implement this.

My gatt service code is as follows:

class BroadcasterService
{
public:
    /**
    * @param[ref] _ble
    *
    * @param[in]
    */
    
    const static uint16_t BROADCAST_SERVICE_UUID            = 0x2A67;
    const static uint16_t BROADCAST_CHARACTERISTIC_UUID     = 0x1817;
    
    BroadcasterService(BLEDevice &_ble, uint8_t _command) :
        ble(_ble),
        command(_command),
        
        broadcasterCharacteristic(BROADCAST_CHARACTERISTIC_UUID, &command, sizeof(command), sizeof(command),
                                  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
                                  // GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
                                  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) {

       
        static bool serviceAdded = false; /* We should only ever need to add the service once. */
        if (serviceAdded) {
            return;
        }

        GattCharacteristic *charTable[] = {&broadcasterCharacteristic};
        GattService         broadcasterService(BroadcasterService::BROADCAST_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));

        ble.addService(broadcasterService);
        serviceAdded = true;
    }

    /**
     * @brief
     *
     * @param
     */
    void sendCommand(uint8_t _newCommand) {
        command = _newCommand;
        ble.updateCharacteristicValue(broadcasterCharacteristic.getValueAttribute().getHandle(), &command, 1);
    }

private:
    BLEDevice           &ble;
    uint8_t             command;    
    GattCharacteristic  broadcasterCharacteristic;
};

Any help/pointers would be appreciated!

Question relating to:

High level Bluetooth Low Energy API and radio abstraction layer

2 Answers

5 years, 6 months ago.

You can pass a pointer to an array of uint8_t to updateCharacteristicValue, and the length of the data inside this array that you would like to be transmitted. How you represent the data inside of this array is up to you. If you're sending a string, you can cast from char to uint8_t without harm (ignoring Unicode).

Accepted Answer

My send command method now looks like this (with command defined as uint8_t command[8]):

void sendCommand(uint8_t _newCommand[8]) { memcpy(&command, &_newCommand, sizeof(_newCommand)); ble.updateCharacteristicValue(broadcasterCharacteristic.getValueAttribute().getHandle(), command, sizeof(command), false); }

But it won't let me pass &command as a parameter into updateCharacteristicValue(): it gives me the error:

Error: Argument of type "std::uint8_t (*)[8]" is incompatible with parameter of type "const std::uint8_t *" in "BroadcasterService.h".

Would you be able to offer any more advice, please?

posted by Alexander Lea 11 Apr 2015
5 years, 6 months ago.

You can also send a structure in same way, as a pointer to byte array size of structure. A union of structure and byte array can ease this. You need to ensure any matching app packs the structure the same, if different the loading/unloading a byte array in app from its structure/object (more code space in app).

Needs an update, but bleIO example project and matching app show an example of this for send/receive/notify.