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

Handle a write event from its descriptor value

Do you know how to handle a write event from its (such as char) descriptor value in a customized BLE service ?

Here is the code of my on_write function :

static void on_write(ble_bod_t * p_bod, ble_evt_t const * p_ble_evt)
{
	// Check if the handle passed with the event matches the Custom Value Characteristic handle.
	if (p_ble_evt->evt.gatts_evt.params.write.handle == p_bod->first_char_handles.value_handle) // If the write event does correspond to the blinky characteristic ...
	{
		bsp_board_led_invert(BSP_BOARD_LED_0);	   
	} else if (p_ble_evt->evt.gatts_evt.params.write.handle == p_bod->second_char_handles.value_handle) {
		change_ble_device_name();				   
	}
}

Setup : nRF52840, SDK 15.0.0, Soft Device s140

Parents
  • Hi,

    There is no difference in how you handle this implementation-vise with custom BLE services or other BLE services that are implemented in the SDK, so you should find good inspiration by looking at the implementation of existing services (<SDK>/components/ble/ble_services/).

    If you want more specific pointers, then perhaps you can be more specific with regards to what you want to achieve and what is not working?

  • To be more precise, I want to get the Characteristic metadata structure (type ble_gatts_char_md_t). Is there any function get it ?

  • Hi,

    No. The ble_gatts_char_md_t struct is only used when configuring/adding a new service, as an input for sd_ble_gatts_characteristic_add(). That means that as your app writes and populates it, you will know it. But I suspect you are after something else?

    If it is that you want to handle a write to a characteristic value (as it looks like from your code in your original question), then you are on to something, and can refer to existing service implementation sin the SDK. One of the simpler examples in this case is the LBS implementation in <SDK>\components\ble\ble_services\ble_lbs\ble_lbs.c.

  • Hi,

    In fact, I want to handle both the characteristic and the descriptor value.

    Here's how I add a descriptor to one of my characteristics:

    static char user_desc[] = "BL654_PARAM";          
    char_md.p_char_user_desc = (uint8_t *) user_desc;
    char_md.char_user_desc_size = strlen(user_desc);
    char_md.char_user_desc_max_size = strlen(user_desc);

    It would be perfect if I could get the "char user_desc[]" value and compare it to a char[] in my on_write function. Do you think this is possible?

Reply
  • Hi,

    In fact, I want to handle both the characteristic and the descriptor value.

    Here's how I add a descriptor to one of my characteristics:

    static char user_desc[] = "BL654_PARAM";          
    char_md.p_char_user_desc = (uint8_t *) user_desc;
    char_md.char_user_desc_size = strlen(user_desc);
    char_md.char_user_desc_max_size = strlen(user_desc);

    It would be perfect if I could get the "char user_desc[]" value and compare it to a char[] in my on_write function. Do you think this is possible?

Children
  • Hi,

    You can see an example of the principle in the LBS service implementation I referred to.

    Let me describe in a bit more detail. Here the characteristic is added  on line 126-129 in <SDK 15.0.0>\components\ble\ble_services\ble_lbs\ble_lbs.c by a call to sd_ble_gatts_characteristic_add():

        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   = sizeof(uint8_t);
        attr_char_value.p_value   = NULL;
    
        return sd_ble_gatts_characteristic_add(p_lbs->service_handle,
                                               &char_md,
                                               &attr_char_value,
                                               &p_lbs->led_char_handles);
    }

    The last parameter here is an output, and is an instance of ble_gatts_char_handles_t which is a struct that holds all the relevant handles. You need to "remember" this. Then come the on_write() function which is called when there is a BLE_GATTS_EVT_WRITE event:

    static void on_write(ble_lbs_t * p_lbs, ble_evt_t const * p_ble_evt)
    {
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
        if (   (p_evt_write->handle == p_lbs->led_char_handles.value_handle)
            && (p_evt_write->len == 1)
            && (p_lbs->led_write_handler != NULL))
        {
            p_lbs->led_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_lbs, p_evt_write->data[0]);
        }
    }
    

    In the on_write function, you can see that this characteristic value handle (p_lbs->led_char_handles.value_handle) is used to see if this write was for the value. Similarly you can compare with the user description handle if that is what you are after, or cccd etc.

Related