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

Update BLE Characteristic from ENUM

Hi

I would like to use an ENUM and STUCT within my application to maintain device state (IDLE, RUNNING etc). This state needs to update a BLE Characteristic. I have the BLE Service and Characteristic running but am struggling to send the ENUM as a single byte (uint8_t).

The ENUM & STRUCT is as follows:

typedef enum
{
    IDLE    = 0x00,    //0
    RUNNING = 0x01,    //1
    FAULT   = 0x09     //9
} m_srm_state_evt_type_t;

typedef struct
{
    m_srm_state_evt_type_t evt_type;
} m_srm_state_type_t;
static m_srm_state_type_t m_srm_state;

And the BLE update char is as follows:

case BLE_SRVC_OPT_EVT_CONNECTED:
            uint8_t value[1]            = {m_srm_state.value};
            err_code = ble_srvc_opt_custom_value_update(&m_cus, value);
            APP_ERROR_CHECK(err_code);
            break;

I know it's my lack of programming skills, but really stuck on this one. Thanks in advance.

  • Hi,

    I'm interested in seeing more of your code, specifically the initialization of the service and the ble_srvc_opt_custom_value_update(). Also

    I have the BLE Service and Characteristic running but am struggling to send the ENUM as a single byte (uint8_t).

     What exactly happens when you run the application? Are you getting any errors? Have you tried debugging your application?

    regards

    Jared

  • Hi,

    The code won't compile as is, but if I replace the ENUM var with a simple byte of 01 -

    ret_code_t err_code;
    uint8_t value            = 0;
    err_code = ble_srvc_opt_custom_value_update(&m_cus, value);
    APP_ERROR_CHECK(err_code);

    This code is initiated as soon as the following criteria is met within  this static void -

    static void on_srvc_opt_evt(ble_srvc_opt_t     * p_cus_service,
                           ble_srvc_opt_evt_t * p_evt)
    {
    
        ret_code_t err_code;
        uint8_t value            = 0;
        
        switch(p_evt->evt_type)
        {
    
            case BLE_SRVC_OPT_EVT_NOTIFICATION_ENABLED:
                break;
    
            case BLE_SRVC_OPT_EVT_NOTIFICATION_DISABLED:
                break;
    
            case BLE_SRVC_OPT_EVT_CONNECTED:
                //Set BLE Characteristics on connection
                err_code = ble_srvc_opt_custom_value_update(&m_cus, value);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_SRVC_OPT_EVT_DISCONNECTED:
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }

    I get the following crash:

    <info> app: Fast advertising.
    
    <info> app: ble_srvc_data Custom Characteristic - BLE_GAP_EVT_CONNECTED
    
    <info> app: ble_srvc_opt Custom Characteristic - BLE_GAP_EVT_CONNECTED
    
    <info> app: In ble_srvc_opt_custom_value_update. 
    
    <error> app: ERROR 13313 [Unknown error code] at ../../../main.c:206
    
    PC at: 0x0002D141
    
    <error> app: End of error report

    Lines 205 and 206 in main.c are:

    err_code = ble_srvc_opt_custom_value_update(&m_cus, value);
    APP_ERROR_CHECK(err_code);

    Value Update Code:-

    uint32_t ble_srvc_opt_custom_value_update(ble_srvc_opt_t * p_cus, uint8_t custom_value)
    {
        NRF_LOG_INFO("In ble_srvc_opt_custom_value_update. \r\n"); 
        if (p_cus == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        uint32_t err_code = NRF_SUCCESS;
        ble_gatts_value_t gatts_value;
    
        // Initialize value struct.
        memset(&gatts_value, 0, sizeof(gatts_value));
    
        gatts_value.len     = sizeof(uint8_t);
        gatts_value.offset  = 0;
        gatts_value.p_value = &custom_value;
    
        // Update database.
        err_code = sd_ble_gatts_value_set(p_cus->conn_handle,
                                          p_cus->custom_value_handles.value_handle,
                                          &gatts_value);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        // Send value if connected and notifying.
        if ((p_cus->conn_handle != BLE_CONN_HANDLE_INVALID)) 
        {
            ble_gatts_hvx_params_t hvx_params;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
    
            hvx_params.handle = p_cus->custom_value_handles.value_handle;
            hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = gatts_value.offset;
            hvx_params.p_len  = &gatts_value.len;
            hvx_params.p_data = gatts_value.p_value;
    
            err_code = sd_ble_gatts_hvx(p_cus->conn_handle, &hvx_params);
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
        }
    
    
        return err_code;
    }

    Thanks

  • Hi.

    ERROR 13313 is a BLE_ERROR_GATTS_SYS_ATTR_MISSING which is returned by sd_ble_gatts_hvx(). Could you try the solution proposed in this case.  Also I can't see that value is a struct member from your definition of the struct m_srm_state. It seems that the struct member is called evt_type. 

  • Hi

    I think the issue is that I am attempting to send a Characteristic Value before it being ready (i.e. I'm sending as soon as BLE_SRVC_OPT_EVT_CONNECTED). As this is at the Service level, I assume that the Characteristic could still be being negotiated.

    Would this make sense?

  • Hi,

    Did you try the workaround suggest in the linked case in the previous reply? 

    You could try setting err_code =sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0)  before you call  ble_srvc_opt_custom_value_update(). And you should make sure that notifications is enabled.

    regards

    Jared

Related