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

Adding characteristic (for purpose of long read) fails

I've added a custom service for transferring data. It shall contain one characteristic that will notify when data is available, and the other should be a long read characteristic (no notify). sd_ble_gatts_characteristic_add is failing (return 0x7) when I add the second characteristic.

I've made attr_char_value.max_len to 512. I am enabling attr_md.rd_auth = 1 to handle the long read as mentioned in the post devzone.nordicsemi.com/.../

Is this the right way, or are there any new preferred way to enable long read ?

Could someone please point out what is the invalid parameter ? I'm using sdk 14.1 with GCC compiler. The code is below:

static uint32_t sensor_data_char_add(ble_ksh_t * p_ksh, ble_ksh_init_t const * p_pke_init) {
ble_gatts_char_md_t char_md;
ble_gatts_attr_md_t cccd_md;
ble_gatts_attr_t    attr_char_value;
ble_uuid_t          ble_uuid;
ble_gatts_attr_md_t attr_md;

extern uint8_t sensor_data_buffer[BLE_KSH_MAX_DATA_CHAR_LEN];

memset(&cccd_md, 0, sizeof(cccd_md));

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);

cccd_md.vloc = BLE_GATTS_VLOC_STACK;

memset(&char_md, 0, sizeof(char_md));

char_md.char_props.read = 1;
char_md.p_char_user_desc  = NULL;
char_md.p_char_pf         = NULL;
char_md.p_user_desc_md    = NULL;
char_md.p_cccd_md         = &cccd_md;
char_md.p_sccd_md         = NULL;

ble_uuid.type = p_ksh->uuid_type;
ble_uuid.uuid = BLE_UUID_KSH_DATA_CHARACTERISTIC;

memset(&attr_md, 0, sizeof(attr_md));

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);

attr_md.vloc    = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 1;
attr_md.wr_auth = 0;
attr_md.vlen    = 1;

memset(&attr_char_value, 0, sizeof(attr_char_value));

attr_char_value.p_uuid    = &ble_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len  = sizeof(uint8_t);
attr_char_value.init_offs = 0;
attr_char_value.max_len   = BLE_GATTS_VAR_ATTR_LEN_MAX;
attr_char_value.p_value   = &sensor_data_buffer[0];

return sd_ble_gatts_characteristic_add(p_ksh->service_handle,
                                       &char_md,
                                       &attr_char_value,
                                       &p_ksh->data_handles);

}

  • :

    1. No. Why you talk about GATT client here? we are talking about gatt server.

    2. It should as it's defined in BLE_GATTS_VAR_ATTR_LEN_MAX isn't it.

    3. "The Client Characteristic Configuration declaration shall be readable and writable." It's defined in the spec (section 3.3.3.3 Vol 3 Part G Spec v4.0)

    4. I don't understand you. Authorization has nothing to do with long read. Have you looked at the sequence chart I mentioned in the answer ??

    5. Check the message sequence chart.

    6. You mean sd_ble_gatts_value_set? This function tells nothing to the peer device, it only update the value of the characteristic. You need to send a notification if you want to tell the peer device you have new data (using sd_ble_gatts_hvx() function). This function take a pointer and length and then update it to the buffer you declare when you initialize the characteristic. The buffer can be inside the stack if you use BLE_GATTS_VLOC_STACK. If you use BLE_GATTS_VLOC_USER, the it will be the buffer you provided as the initialize value of the characteristic.

  • @hungbui Let me try to clear the misunderstanding. I did look into the message sequence chart. I would like to clarify that my requirement is not to read long characteristic from a peer device. Rather, when a peer device does a read, my device should be able to send a long sequence of bytes. So from your response, I infer that sd_ble_gattc_read() is used to do a long read on a peer's characteristic. Am I right ?

  • Hi Aurabindo,

    What do you mean by "send a long sequence of bytes" ? Do you mean that you can send different data instead of the value of the characteristic ? If it's the case, you may need read with authorization, where you can actually set the data you want to set to the characteristic and send it via read response.

    sd_ble_gattc_read() can be used on the client side to do a read. Offset parameter can be used to do a read blob /read long. Meaning you need to do several sd_ble_gattc_read() and move the offset to read the whole characteristic.

    Note that if you use authorization, you can think of updating the characteristic value to send different trunk of data based on the number of read instead of using offset, This is useful when you don't want to use a large buffer or if the size of your data is bigger than the max size for characteristic (512).

  • @hungbui by "send a long sequence of bytes", I did not specifically mean about setting characteristic's data or not setting it. Either way it would work fine for me, unless one method has considerable performance penalty in terms of data throughput. Thanks for the suggestion

Related