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

BLE Tutorial to Add Charactersitic - Unknown error code 13312 returned by sd_ble_gatts_hvx.

The tutorial is a huge help. I've been working on this for some days now, and it looks like I'm almost there. But just one last hurdle (I hope). The title pretty much says it all. I've even traced thre the error code translation to the table of error codes, no joy. Can anyone suggest where I might look?

  • Hi Steve,

    13312 (it's in decimal) -> 0x3400 -->  NRF_GATTS_ERR_BASE ("GATT server specific errors.") --> BLE_ERROR_GATTS_INVALID_ATTR_TYPE   ("Invalid attribute type.")

    Which you can see is one of the return values for sd_ble_gatts_hvx().

    • "Invalid attribute type(s) supplied, only characteristic values may be notified and indicated."

     

    Make sure that you are using the correct parameters for sd_ble_gatts_hvx() as described in the documentation. 

    (similar thread)

  • I will pursue that and likely be able to fix this one, but I'm still at a loss as to where that value is documented. I searched the entire project for the definition of the function, and dead-ended at an SV_CALL macro. I searched for the number in both decimal and hex form, no joy there either. Where are such things documented? The sheer volume of documentation of the BLE stack is a bit overwhelming, even with my 4 decades of experience in embedded development.

  • I've gone back over my code against the tutorial with a fine-toothed comb and can't see my error. AFAICT I'm passing exactly the parameters requested by ..._gatts_hvx. I tried changing the handle but that yields a different error; it needs the connection handle, and finds the characteristic handle via a field in hvx_params. Let me see if I can trim my code down to just the relevant parts here:

    In the function that is called by my timer, LastGlucose is an int16_t that holds the value I want to notify.:

    if (m_Glucose_service.conn_handle != BLE_CONN_HANDLE_INVALID)
       {
       static uint16_t len = sizeof LastGlucose;
       static ble_gatts_hvx_params_t hvx_params; << I added "static" here as an attempted fix
       memset (&hvx_params, 0, sizeof hvx_params);
       hvx_params.handle = m_Glucose_service.char_handles.value_handle;
    NRF_LOG_INFO ("value_handle=%d LastGlucose=%X", m_Glucose_service.char_handles.value_handle, LastGlucose); << These values look valid when displayed
       hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
       hvx_params.offset = 0;
       hvx_params.p_len  = &len;
       hvx_params.p_data = (uint8_t *) &LastGlucose;
       error_code = sd_ble_gatts_hvx (m_Glucose_service.conn_handle, &hvx_params);
    NRF_LOG_INFO ("hvx=%d", error_code); << This displays the 13312 error code
    APP_ERROR_CHECK (error_code); << As does this
       }

    The function that set up the Characteristic looks like this, again trimmed to just the relevant parts (I hope):

    void AddMeasurementChar (ble_GlucoseService_t *p_Glucose_service)
    {
    uint32_t err_code;
    ble_uuid_t Measurement_uuid;
    ble_uuid128_t     base_uuid = BLE_UUID_NBS_BASE_UUID;
    ble_gatts_char_md_t Measurement_md;
    ble_gatts_attr_t    attr_Measurement_value;
    ble_gatts_char_handles_t  *p_handles;
    ble_gatts_attr_md_t attr_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_char_pf_t Measurement_pf;
    memset (&Measurement_md, 0, sizeof Measurement_md);
    memset (&attr_Measurement_value, 0, sizeof attr_Measurement_value);
    memset (&attr_md, 0, sizeof attr_md);
    memset (&cccd_md, 0, sizeof cccd_md);
    memset (&Measurement_pf, 0, sizeof Measurement_pf);
    Measurement_uuid.uuid = BLE_UUID_MEASUREMENT_CHAR;
    err_code = sd_ble_uuid_vs_add (&base_uuid, &Measurement_uuid.type);
    APP_ERROR_CHECK (err_code);
    attr_md.vloc = BLE_GATTS_VLOC_USER;
    cccd_md.vloc = BLE_GATTS_VLOC_STACK;
    attr_Measurement_value.p_uuid = &Measurement_uuid;
    attr_Measurement_value.p_attr_md = &attr_md;
    attr_Measurement_value.p_value = (uint8_t *) &LastGlucose;
    attr_Measurement_value. max_len = sizeof LastGlucose;
    attr_Measurement_value.init_len = sizeof LastGlucose;
    Measurement_md.p_char_user_desc = "Glucose Concentration";
    Measurement_md.char_user_desc_max_size = 21;
    Measurement_md.char_user_desc_size = 21;
    Measurement_md.char_props.read  = 1;
    Measurement_md.char_props.notify = 1;
    Measurement_md.p_cccd_md = &cccd_md;
    Measurement_md.p_char_pf = &Measurement_pf;
    Measurement_pf.format = 0x16;
    Measurement_pf.unit = 0x27B1;
    BLE_GAP_CONN_SEC_MODE_SET_OPEN (&attr_md. read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN (&attr_md.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN (&cccd_md. read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN (&cccd_md.write_perm);
    err_code = sd_ble_gatts_characteristic_add (p_Glucose_service -> service_handle, &Measurement_md, &attr_Measurement_value, &p_Glucose_service -> char_handles);
    NRF_LOG_INTERNAL_INFO ("Handle %X %X", p_Glucose_service -> char_handles.value_handle, p_Glucose_service -> char_handles.user_desc_handle);
    APP_ERROR_CHECK (err_code);
    }

    I have tried setting both Notify and Indicate flags, which doesn't help at all.

    Any more hints where to look? The error message is rather un-helpful.

  • Hi Steve,

    Which tutorial are you referring to?

    Are you basing your code on one of these tutorials? (if so, the issue can stem from that they are based on older SDKs, which also had some different APIs ++)

    I would recommend you to use this tutorial which is updated for the newest SDK v15  and you could also look up in the "Heart rate example" in the "ble_hrs.c" file how the function in line 375 handles it.

  • I worked thru the "this tutorial" you recommended, and the only significant difference I found is the use of

    sd_ble_gatts_value_set before the call to
     sd_ble_gatts_hvx

    so I tried doing it that way instead of keeping the value in BLE_GATTS_VLOC_USER. The only thing that changed is that the value is now corrupted,
    and I'm still no closer to understanding what my error might be in calling sd_ble_gatts_hvx.
Related