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

ble_cus_custom_value_update only updating for one characteristic in a custom service

Hi I am using the custom_ble_service example from https://github.com/bjornspockeli/custom_ble_service_example/blob/master/main.c. The example code will turn a custom characteristic value into a time counter if the user enables notification the characteristic. So after the user enables notification and reads characteristic value the value goes from 0x01 to 0x02, 0x03, etc. 

I have added a second custom characteristic to the custom service. However, when I enable notifications on the second custom characteristic the value does not change from the time counter. 

This is the code that updates the first custom characteristic value as the time counter increments.

static void notification_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    ret_code_t err_code;
    
    // Increment the value of m_custom_value before nortifing it.
    m_custom_value++;
    
    err_code = ble_cus_custom_value_update(&m_cus, m_custom_value);
    APP_ERROR_CHECK(err_code);
}

 I made sure that the second custom characteristic was added to the custom service created and initialized in m_cus. 

static void services_init(void)
{
        ret_code_t          err_code;
        nrf_ble_qwr_init_t  qwr_init = {0};
        ble_cus_init_t      cus_init = {0};

        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;

        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);

         // Initialize CUS Service init structure to zero.
        cus_init.evt_handler                = on_cus_evt;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.cccd_write_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.write_perm);
    
        err_code = ble_cus_init(&m_cus, &cus_init);
        APP_ERROR_CHECK(err_code);
        
        //ble_cus_2nd_char_init() is a function I defined to add a second
        //custom characteristic to the custom service
        /*
            uint32_t ble_cus_2nd_char_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
                {
                if (p_cus == NULL || p_cus_init == NULL)
                    {
                        return NRF_ERROR_NULL;
                    }
                //custom_value_char_add2 is a copy of custom_value_char_add()
                // with different characteristic UUID assigned to the second
                //custom characteristic
                 return custom_value_char_add2(p_cus, p_cus_init); 
                }
        
        */
        ble_cus_2nd_char_init(&m_cus, &cus_init);
        

Since I can see both custom characteristics in the custom service I am fairly certain I added the second custom characteristic correctly.

I am confused as to why ble_cus_custom_value_update(&m_cus, m_custom_value) doesn't affect the second custom characteristic if that characteristic has been successfully added to m_cus. Can someone please explain why? Thank you

Parents
  • Hi Thoric, 

    As you can see in the call ble_cus_init() m_cus is a variable that the application has to provide to get the service's instance initialized. This is the documentation of the function: 

    /**@brief Function for initializing the Custom Service.
     *
     * @param[out]  p_cus       Custom Service structure. This structure will have to be supplied by
     *                          the application. It will be initialized by this function, and will later
     *                          be used to identify this particular service instance.
     * @param[in]   p_cus_init  Information needed to initialize the service.
     *
     * @return      NRF_SUCCESS on successful initialization of service, otherwise an error code.
     */
    uint32_t ble_cus_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init);

    This mean you have to provide different m_cus variables for each of the service you declare. Each ble_cus_s will hold the following information (specific to each service instance you declare):

     

    struct ble_cus_s
    {
        ble_cus_evt_handler_t         evt_handler;                    /**< Event handler to be called for handling events in the Custom Service. */
        uint16_t                      service_handle;                 /**< Handle of Custom Service (as provided by the BLE stack). */
        ble_gatts_char_handles_t      custom_value_handles;           /**< Handles related to the Custom Value characteristic. */
        uint16_t                      conn_handle;                    /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */
        uint8_t                       uuid_type; 
    };
    

    You don't need to declare ble_cus_2nd_char_init(). If your second service is the same as the CUS service, you can call for example: 

    ble_cus_init(&m_cus2, &cus_init2);

    And when you have to interface to the second service with any API call , you always use m_cus2 as the input instead. 

  • Hi Hung,

    But what if I am trying to create only one custom service with two custom characteristics? Would I have to modify the custom service struct ble_cus_s to hold two custom characteristics then? 

Reply Children
Related