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
  • Hello,

    The number of notifications you can send (within one connection interval, I assume you mean) depends on your connection parameters. The connection interval length, MTU_SIZE, EVENT_LENGTH and PHY (1 or 2Mpbs).

    Some of the limitations are dependent on how much time you have to use the radio within the connection interval, while some of the limitations are due to buffer sizes.

    I recommend that you check out the example: SDK14.2.0\examples\ble_central_and_peripheral\experimental\ble_app_att_mtu_throughput. A guide on how to use it is found here. Although you can't adjust the packet (notification) size, it gives a good idea for what the other connection parameters does to the speed.

    A notification of 8 bytes is no problem, but you should know that you get more overhead to the data you are sending when you split them up in smaller packages.

     

    If you want to test this with another example, you can use pretty much any example, and just queue up the notifications. In the ble_app_uart example, this can be done with ble_nus_string_send, which you can see, in turn calls sd_ble_gatts_hvx(). You must check the return value of this call. If it returns NRF_SUCCESS; then the package is queued, and you can assume it will be received on the other side of the link (it will be retransmitted if not). If it returns NRF_ERROR_RESOURCES, it means that too many notifications is queued, and you will have to wait for the event BLE_GATTS_EVT_HVN_TX_COMPLETE before you can try to queue notifications again.

     

    Best regards,

    Edvin

     

Reply
  • Hello,

    The number of notifications you can send (within one connection interval, I assume you mean) depends on your connection parameters. The connection interval length, MTU_SIZE, EVENT_LENGTH and PHY (1 or 2Mpbs).

    Some of the limitations are dependent on how much time you have to use the radio within the connection interval, while some of the limitations are due to buffer sizes.

    I recommend that you check out the example: SDK14.2.0\examples\ble_central_and_peripheral\experimental\ble_app_att_mtu_throughput. A guide on how to use it is found here. Although you can't adjust the packet (notification) size, it gives a good idea for what the other connection parameters does to the speed.

    A notification of 8 bytes is no problem, but you should know that you get more overhead to the data you are sending when you split them up in smaller packages.

     

    If you want to test this with another example, you can use pretty much any example, and just queue up the notifications. In the ble_app_uart example, this can be done with ble_nus_string_send, which you can see, in turn calls sd_ble_gatts_hvx(). You must check the return value of this call. If it returns NRF_SUCCESS; then the package is queued, and you can assume it will be received on the other side of the link (it will be retransmitted if not). If it returns NRF_ERROR_RESOURCES, it means that too many notifications is queued, and you will have to wait for the event BLE_GATTS_EVT_HVN_TX_COMPLETE before you can try to queue notifications again.

     

    Best regards,

    Edvin

     

Children
  • Thank you already for your information and advice!

    In fact I followed the tutorial: https://github.com/bjornspockeli/custom_ble_service_example

    Then as a result of that, I directly used the example :  https://github.com/bjornspockeli/custom_ble_service_example/tree/master/pca10040/s132 using the SDK 15.0 (which I then took now)

    the problem is that i would like to get a value for my characteristic 1 and another for my characteristic 2 on the application nrf connect :

    Creation

    I defined a new uuid for the new characteristics (0x1402)

    I created a characteristics by changing the UUID (line 32)

    static uint32_t custom_value_char_add2(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
    {
        uint32_t            err_code;
        ble_gatts_char_md_t char_md;
        ble_gatts_attr_md_t cccd_md;
        ble_gatts_attr_t    attr_char_value;
        ble_uuid_t          ble_uuid;
        ble_gatts_attr_md_t attr_md;
    
        // Add Custom Value characteristic
        memset(&cccd_md, 0, sizeof(cccd_md));
    
        //  Read  operation on cccd should be possible without authentication.
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
        
        cccd_md.write_perm = p_cus_init->custom_value_char_attr_md.cccd_write_perm;
        cccd_md.vloc       = BLE_GATTS_VLOC_STACK;
    
        memset(&char_md, 0, sizeof(char_md));
    
        char_md.char_props.read   = 0;
        char_md.char_props.write  = 1;
        char_md.char_props.notify = 1; 
        char_md.p_char_user_desc  = NULL;
        char_md.p_char_pf         = NULL;
        char_md.p_user_desc_md    = NULL;
        char_md.p_cccd_md         = &cccd_md; 
        char_md.p_sccd_md         = NULL;
    		
        ble_uuid.type = p_cus->uuid_type;
        ble_uuid.uuid = CUSTOM_VALUE2_CHAR_UUID;
    
        memset(&attr_md, 0, sizeof(attr_md));
    
        attr_md.read_perm  = p_cus_init->custom_value_char_attr_md.read_perm;
        attr_md.write_perm = p_cus_init->custom_value_char_attr_md.write_perm;
        attr_md.vloc       = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth    = 0;
        attr_md.wr_auth    = 0;
        attr_md.vlen       = 0;
    
        memset(&attr_char_value, 0, sizeof(attr_char_value));
    
        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);
    
        err_code = sd_ble_gatts_characteristic_add(p_cus->service_handle, &char_md,
                                                   &attr_char_value,
                                                   &p_cus->custom_value_handles);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        return NRF_SUCCESS;
    }

    I added it at the end of the ble_cus_init.

    Here for the creation of the 2nd characteristic.

    Then in main.c :

    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.
        custom++;
        custom2++;
        
        ble_cus_custom_value_update(&m_cus, custom);
        ble_cus_custom_value_update(&m_cus, custom2);
    
    }

    and in ble_cus.c :

    uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, uint8_t custom_value)
    {
        NRF_LOG_INFO("In ble_cus_custom_value_update. \r\n"); 
        if (p_cus == NULL)
        {
            return NRF_ERROR_NULL;
        }
        nrf_gpio_pin_toggle(LED_3);
        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);
            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"); 
        }
    
    
        return err_code;
    }

    Here I am blocked, I continue to search but I do not see, I tested several things but without success.

    The "conn_handle" is to connect that to the peripheral not to the characteristicistic, no?

    Thanks in advance Slight smile

Related