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

How to retrieve multiple values from a server with 1 services with several characteristics ?

Hello everybody !
Designing with the development board nRF52832 and SDK14.2.

My code is based on the code of the "ble_app_multilink_central" on which, I added some of the code "ble_app_uart_c" for the initialization and the event manager on the uart. I have a nrf52832 development board as a central and 2 nrf52832 developpement boards as a peripheral.

In a device, I created my personalized service composed of 4 characteristics.

My first question:
it's possible to send up to how many notifications at the same time to a single Client? Could I, in your opinion, send notifications with a size of 8 bytes? (I thought I saw that the max was 20 bytes so it's good).

Here is a simple diagram representing my system :

How to retrieve the value1, value2, value3 and value4 in the client?

Thank you in advance !

Parents
  • Yes. The conn_handle is usually used for the connection handle, but you also have a characteristic handle. If you look in one of the examples with several services and characteristics, e.g. the ble_app_hrs example, you can see that it sends the heart rate measurement from main.c in heart_rate_meas_timeout_handler(...) --> ble_hrs_heart_rate_measurement_send(...) --> sd_ble_gatts_hvx(...)

     

    It is the last function that actually sends the notification. you can see that it takes the argument hvx_params, which has a handle set by:

    hvx_params.handle =  p_hrs->hrm_handles.value_handle;

    So you need a different handle for all of your characteristics.

     

    Another example is the ble_app_uart example, which has two characterisitcs within one service, which is closer to what you are doing. You can see there that it sets the handle within:

    uart_event_handle(...) --> ble_nus_data_send(...) --> sd_ble_gatts_hvx(...)

    and it sets the handle with:

    hvx_params.handle = p_nus->tx_handles.value_handle;

    If you look in the file ble_nus.h, you can see that it has two characteristic handles. tx_handles and rx_handles, which both has a .value_handle, so you need one handle for each of your characteristics. 

    Please look at the ble_app_uart example, and see how the tx_char_add() and rx_char_add() are set up, and see if you can port that to your own project.

     

    Best regards,

    Edvin

  • Thank you for all this help I managed to make 4 characteristic that sends a notification.
    The problem is that only the button to allow notifications of characteristic 1 makes me enter the function notification_timeout_handler (void * p_context)

    the function notification_timeout_handler (void * p_context) :

    static void notification_timeout_handler(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
        ret_code_t err_code;
        nrf_gpio_pin_toggle(LED_4); 
        // Increment the value of m_custom_value before nortifing it.
        m_custom_value1=m_custom_value1+1;
        m_custom_value2=m_custom_value2+256;
        m_custom_value3=m_custom_value3+256*256;
        m_custom_value4=m_custom_value4+256*256*256;
    
        ble_cus_custom_value_update(&m_cus, m_custom_value1, m_custom_value2, m_custom_value3, m_custom_value4);
    }

    I'm sure the solution is in the on_cus_evt part with the BLE_CUS_EVT_NOTIFICATION_ENABLED but I do not see where.

    I would like to understand what this button interacts with

  • That button is used to enable notification on a service. If it is pressed (so that the icon gets the cross over, like in the pictures that you have posted) it means that notifications are enabled.

    I am not sure how you have set up your notification_timeout_handler() function. Notifications are usually used like this:

    When notifications are not enabled, any sensor updates is just stored in the device.

    If notifications are enabled, the device will notify the connected device whenever the characteristic changes. So what you should try to do is to enable the notifications and then set up a timer or something to send updated values of the characteristics. I suspect this is what you are trying to do, but I am not sure what your ble_cus_custom_value_update() looks like. I suspect that the version that you sent earlier is an outdated version?

     

    In this function, you should check that notifications are enabled, and send the data for each characteristic with sd_ble_gatts_hvx(conn_handle, &hvx_params);

     

    Best regards,

    Edvin

     

  • In fact, I know what it serves but I wanted to know what it interacts with the pheripheral code.

    It's true that I did not explain my project, it's my fault. So my project is to retrieve data from a sensor with the peripheral and store this data in its characteristics and after that, every 100ms (33ms objective) I send a notification to the central. As for a notification every second, I use the end of step 8 of this: https://github.com/bjornspockeli/custom_ble_service_example

    As far as my "notification_timeout_handler ()" is concerned, I have not yet set the values "m_custom_value = data_sensor" in my main () function, that's just an example of incrementing for my debugging

    This is the function ble_cus_custom_value_update () :

    uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, uint64_t custom_value, uint64_t custom_value2, uint64_t custom_value3, uint64_t custom_value4)
    {
        NRF_LOG_INFO("In ble_cus_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;
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //                                Sensor n°1                                      //
    ////////////////////////////////////////////////////////////////////////////////////////
    
        // Initialize value struct.
        memset(&gatts_value, 0, sizeof(gatts_value));
    
        gatts_value.len     = sizeof(uint64_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);
            NRF_LOG_INFO("sd_ble_gatts_hvx result: %x. \r\n", err_code); 
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
            NRF_LOG_INFO("sd_ble_gatts_hvx result: NRF_ERROR_INVALID_STATE. \r\n"); 
        }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //                                Sensor n°2                                      //
    ////////////////////////////////////////////////////////////////////////////////////////
    
    ...
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //                                Sensor n°3                                      //
    ////////////////////////////////////////////////////////////////////////////////////////
    
    ...
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //                                Sensor n°4                                      //
    ////////////////////////////////////////////////////////////////////////////////////////
    
    ...
    
        return err_code;
    }

    We can see that the function sd_ble_gatts_hvx () is there (line 45).

    In fact, I may have been poorly expressed, in terms of sending feature values to my smartphone, that's fine but it works for characteristics 2, 3 and 4 data only if I press the button that allows the notifications of the characteristicistic 1.

    Thanks again for the quality of the answer and the speed,

    Yoann_F

  • The button sets the CCCD to 0x01. 

    If I understand you correctly, this is working?

    I will follow up in your new case.

    If you want me to look at why the button for characteristics 2, 3 and 4 does not work, could you upload your project, so that I can test it?

     

    Best regards,

    Edvin

Reply Children
Related