This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to configure sd_ble_gatts_characteristic_add()

The documentation for setting up the characteristics is very thin - its no better than what one can read in the h-files. This method

sd_ble_gatts_characteristic_add(uint16_t service_handle, ble_gatts_char_md_t const *p_char_md, ble_gatts_attr_t const *p_attr_char_value, ble_gatts_char_handles_t *p_handles)

requires the population of the ble_gatts_char_md_t and ble_gatts_attr_t structures. Of these two structures, the part that is most vague is the specification of initial values, initial lengths, and maximum lengths and what these lengths have to cover in the .ble_gatts_attr_t structure.

The first question about the lengths and maximum lengths, does that mean just data? Do the max lengths given by

  •  #define  BLE_GATTS_FIX_ATTR_LEN_MAX (510) 
  •  #define  BLE_GATTS_VAR_ATTR_LEN_MAX (512)

mean just data or do they include protocol overhead?

If I have a static value like a DIS characteristic and the actual value of the data is 16 bytes, what is the size of max_value? Is it also 16 bytes?

If I am indicating or notifying a characteristic, does that affect the max_value? If the characteristic can be written, what do I have to take into consideration?

I have one situation where the characteristics are only used as a tunnel.. The first characteristic is never read or written and I use it just to notify data in fragments. The data being notified is a persistent application buffer that may be much longer than the maximum attribute length but it remains in scope for the duration of the app. There is no need to 'place' that value or any part of it in the service table. Can I use BLE_GATTS_VLOC_USER in this case and take up zero space in the service table? Does my buffer have to hold overhead or just data? Will SoftDevice overwrite any data in this buffer (which would be a disaster)? I am not sure what BLE_GATTS_VLOC_USER requires. Do I simply provide space for SoftDevice to use it as it sees fit an my application has to keep its hand off it, or does it allow me to use sections of that data buffer for the notification that CANNOT BE ALTERED?

The second characteristic in this service supports both writes and indications. These are much smaller in size but again, the values written and values indicated are created by and used by the application only. The values written or indicated do not need to be persisted in the service table. How do I handle this case?

In general, I do not know how these sizes and buffers are used and how I can most efficiently (take least memory and minimize the service tables) do my task. I don't know if SoftDevice alters these buffers or whether the sizes have to account for protocol overhead (which probably means SoftDevice freely writes to these buffers. I do have a problem of running out of service table space when I start adding a few standard GATT services like the DIS and Battery Service. But currently everything is using BLE_GATTS_VLOC_STACK.

I wish this were clearly documented so I wouldn't have to ask. 

Note that I cannot use any SDK because these services are prototypes and there is no support for them (yet). If they get accepted into BT-SIG, there may be support in the future.

  • Hi,

    This looks related to this thread.

    The first question about the lengths and maximum lengths, does that mean just data?

    Yes, it is the length of the data.

    do they include protocol overhead?

    No.

    If I have a static value like a DIS characteristic and the actual value of the data is 16 bytes, what is the size of max_value? Is it also 16 bytes?

    Yes.

    If I am indicating or notifying a characteristic, does that affect the max_value? If the characteristic can be written, what do I have to take into consideration?

    Yes. You need to ensure that the max_len is set to the longest value that should be supported. Any larger will not fit.

    I have one situation where the characteristics are only used as a tunnel.. The first characteristic is never read or written and I use it just to notify data in fragments.

    In this case  you can for instance  use a sensible size for the characteristic, and just notify new data on the same characteristic repeatedly. In this case it would not be necessary for the characteristic to hold the entire dataset. It would simply be as you said, a tunnel.

    There is no need to 'place' that value or any part of it in the service table. Can I use BLE_GATTS_VLOC_USER in this case and take up zero space in the service table?

    No, it would not matter. You would still have to provide the memory to the SoftDevice, and it would have to remain available.

    I am not sure what BLE_GATTS_VLOC_USER requires. Do I simply provide space for SoftDevice to use it as it sees fit an my application has to keep its hand off it, or does it allow me to use sections of that data buffer for the notification that CANNOT BE ALTERED?

    You provide space for the SoftDevice and the application has to keep its hands off it.

    The second characteristic in this service supports both writes and indications. These are much smaller in size but again, the values written and values indicated are created by and used by the application only. The values written or indicated do not need to be persisted in the service table. How do I handle this case?

    They will be persistent until overwritten or reset (if bonded you could also keep them persistent across connections by using the peer manager to store it, but that may not be relevant here. It is also possible to use authorized writes etc. to prevent storing data for some reasons, but that does not seem relevant here.)

    In general, I do not know how these sizes and buffers are used and how I can most efficiently (take least memory and minimize the service tables) do my task.

    The sizes we have discussed here are simply the sized of the data for the characteristic. You should set the maximum lengths to the maximum you need to support.

    Note that I cannot use any SDK because these services are prototypes and there is no support for them (yet). If they get accepted into BT-SIG, there may be support in the future.

    There is nothing preventing you from using the SDK when you are using non-standard services.

  • I have done a lot of trial and error and found that I cannot escape making space in the service tables, even though they are never used. So it makes no sense to use BLE_GATTS_VLOC_USER

    But contrary to what you said about the max size I found that the application crashed if I did not include overhead. I had a 16-byte value and set the max value to 16. It crashed. If I set it to valueLength + OPCODE + HANDLE_LENGTH it worked fine.

Related