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

Multiperipheral NUS connection handle issue

Hi!

My setup:

* nRF52 DK

* nRF5_SDK_15.0.0_a53641a

* s132_nrf52_6.0.0

* SES V3.34b 64-bit

* android ver.8 smartphone with nRF Connect 

I have solved my previous problem with UART service but now it is working, I am able to send data and receive it.

Now I am trying to merge NUS with multiperipheral example. I am able to connect two mobile devices to nRF chip at once, send data with RX Characteristics simultaneously from both smartphones (it then shows on TERMITE terminal). I am struggling with sending data from chip (TX Characteristics) to smartphones with ble_nus_data_send() function.

Originally in SDK the call looks like this:

void uart_event_handle(app_uart_evt_t * p_event)
{
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;
    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;
            if ((data_array[index - 1] == '\n') || (index >= (m_ble_nus_max_data_len)))
            {
                NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                NRF_LOG_HEXDUMP_DEBUG(data_array, index);
                do
                {
                    uint16_t length = (uint16_t)index;
                    err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
                    if ( (err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_BUSY) &&
                         (err_code != NRF_ERROR_NOT_FOUND) )
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
                index = 0;
            }
            break;
        ...
        ...
    }
}

but it uses m_conn_handle which is declared as static! 

static uint16_t   m_conn_handle          = BLE_CONN_HANDLE_INVALID;

Problem exists when I want to connect more than one device and send data to it - the connection handles may vary, for example =0, =1, =2 etc. In the ble_app_uart example there is only one connection handle used all the time.

What I tried to do:

void uart_event_handle(app_uart_evt_t * p_event)
{
    ble_gap_evt_t* p_gap_evt = (ble_gap_evt_t*) p_event;
    p_gap_evt->conn_handle;
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;
    NRF_LOG_INFO("....handle: %d", p_gap_evt->conn_handle);
    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;
            if ((data_array[index - 1] == '\n') || (index >= (m_ble_nus_max_data_len)))
            {
                NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                NRF_LOG_HEXDUMP_DEBUG(data_array, index);
                do
                { 
                    uint16_t length = (uint16_t)index;
                    err_code = ble_nus_data_send(&m_nus, data_array, &length, p_gap_evt->conn_handle);
                    if ( (err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_BUSY) &&
                         (err_code != NRF_ERROR_NOT_FOUND) )
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
                index = 0;
            }
            break;
        ...
        ...
    }
}

The app_uart_evt_t structure doesn't contain connection handle data so I tried to cast it the following way:

   ble_gap_evt_t* p_gap_evt = (ble_gap_evt_t*) p_event;

but getting the correct value of connection handle is a matter of luck, mostly I get random values so I believe this is a wrong idea.

My question:

What would you suggest me to do in order to send data with UART from nRF chip to every connected device at once? Is it a good idea, is it safe to just iterate through all the connection handles and just:

err_code = ble_nus_data_send(&m_nus, data_array, &length, 0);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_data_send(&m_nus, data_array, &length, 1);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_data_send(&m_nus, data_array, &length, 2);
APP_ERROR_CHECK(err_code);
...

And in order to send to only one chosen device should I use ble_nus_data_send() simply outside uart_event_handle()?

Any advices highly appreciated, thanks

  • You will need to call ble_lbs_led_status_send(), or ble_nus_data_send() in your case, for each connected device. You may also want to filter/ignore BLE_ERROR_INVALID_CONN_HANDLE error code, in case you are in process of connecting or disconnecting.

    It may be easier to start with \nRF5_SDK_15.0.0_a53641a\examples\ble_central\ble_app_multilink_central, and add NUS client, than the other way around.

Related