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.

Parents
  • 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

Reply
  • 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

Children
  • 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

  • Hi

    I have looked at my code and carried out a few modifications and have a better understand how the SoftDevice works.

    The following is working, on the following event, it calls handle_ble_char:

    case BLE_SRVC_OPT_EVT_CONNECTED:
            t_value = SET;
            handle_ble_char(p_cus_service, &p_cus_service->status_char_handles , &t_value);
            break;

    The structure of handle_ble_char is as follows:

    static void handle_ble_char (ble_srvc_opt_t *p_service, ble_gatts_char_handles_t *p_char_handle, m_setget *p_type) {
    
        uint32_t err_code;
        ble_gatts_value_t	t_value;
    
        //Get & Set for ble_src_opt - Char - Status
        if (p_char_handle->value_handle == m_cus.status_char_handles.value_handle) {
            
            t_value.p_value = &m_srm_state.evt_type;
    	    t_value.len      = 1;
    	    t_value.offset   = 0;
    
            switch (*p_type)
            {
            case SET:
                err_code = sd_ble_gatts_value_set(p_service->conn_handle, p_char_handle->value_handle, &t_value);
        	    APP_ERROR_CHECK(err_code);
                break;
            case GET:
                err_code = sd_ble_gatts_value_get(p_service->conn_handle, p_char_handle->value_handle, &t_value);
        	    APP_ERROR_CHECK(err_code);
                break;
            default:
                break;
            }
        }
    
    }

    This is a universal bit of code which allows me to tell it which service and characteristic to set or get.

    It is working as planned now...thanks for the help on this one.

Related