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

Mismatch between connection handles in ble_nus?

I'm using the nus_c service with multiple central connections. Obviously, I need the connection handle in my event handler - ble_nus_c_evt_handler(ble_nus_c_t* p_ble_nus_c, const ble_nus_c_evt_t* p_ble_nus_evt).

I've noticed that when BLE_NUS_C_EVT_NUS_RX_EVT is raised, the connection handle in the NUS context object and the event object are different: p_ble_nus_c->conn_handle == 1, as expected, while p_ble_nus_evt->conn_handle == 0.

I've traced it down to on_hvx() in ble_nus_c.c, not setting the connection handle from the GATTC event to the ble_nus_c_evt_t structure it dispatches.

Is this by design or a bug?

Parents
  • Hi,

    Yes, the on_hvx() is not setting the conn_handle for the BLE_NUS_C_EVT_NUS_RX_EVT event, but you have access to the conn_handle in the p_ble_nus_c struct. Ideally it should also be set for the ble_nus_c_evt, i.e. ble_nus_c_evt.conn_handle = p_ble_nus_c->conn_handle; in on_hvx().

    When the nus_c service was initially designed, the nRF5 series only had support for one connection. Later the code was refactored and ble_nus_c_handles_assign() was added so we can keep track of what connection belongs to what instance of NUS.

    So if the overall goal is to use the nus_c service in multiple connections, I recommend that you create a separate NUS and DB structure instance for each connection:

    static ble_nus_c_t              m_ble_nus_c[TOTAL_LINK_COUNT];
    static uint8_t                  m_ble_nus_c_count;  
    static ble_db_discovery_t       m_ble_db_discovery[TOTAL_LINK_COUNT];
    

    Then each instance of NUS would have to be assigned a connection handle with ble_nus_c_handles_assign() when you get the event BLE_NUS_C_EVT_DISCOVERY_COMPLETE. In nus_c_init() and db_discovery_init() you will need to initialize each instance. In nus_c_init() this could look something like this:

    static void nus_c_init(void)
    {
        uint32_t         err_code;
        ble_nus_c_init_t nus_c_init_t;
    
        nus_c_init_t.evt_handler = ble_nus_c_evt_handler;
        
    	for (m_ble_nus_c_count = 0; m_ble_nus_c_count < TOTAL_LINK_COUNT; m_ble_nus_c_count++)
        {
            err_code = ble_nus_c_init(&m_ble_nus_c[m_ble_nus_c_count], &nus_c_init_t);
            APP_ERROR_CHECK(err_code);
        }
        m_ble_nus_c_count = 0;
    }
    

    The db_disc_handler() function would look something like this:

    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
    }
    

    In ble_evt_dispatch(), ble_db_discovery_on_ble_evt() and ble_nus_c_on_ble_evt() should be changed to something like this:

    uint16_t conn_handle;
    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
    ble_db_discovery_on_ble_evt(&m_ble_db_discovery[conn_handle], p_ble_evt);
    ble_nus_c_on_ble_evt(&m_ble_nus_c[conn_handle],p_ble_evt);
    

    You should also take a look at the multilink central example in the SDK to see how this example handles multiple connections.

Reply
  • Hi,

    Yes, the on_hvx() is not setting the conn_handle for the BLE_NUS_C_EVT_NUS_RX_EVT event, but you have access to the conn_handle in the p_ble_nus_c struct. Ideally it should also be set for the ble_nus_c_evt, i.e. ble_nus_c_evt.conn_handle = p_ble_nus_c->conn_handle; in on_hvx().

    When the nus_c service was initially designed, the nRF5 series only had support for one connection. Later the code was refactored and ble_nus_c_handles_assign() was added so we can keep track of what connection belongs to what instance of NUS.

    So if the overall goal is to use the nus_c service in multiple connections, I recommend that you create a separate NUS and DB structure instance for each connection:

    static ble_nus_c_t              m_ble_nus_c[TOTAL_LINK_COUNT];
    static uint8_t                  m_ble_nus_c_count;  
    static ble_db_discovery_t       m_ble_db_discovery[TOTAL_LINK_COUNT];
    

    Then each instance of NUS would have to be assigned a connection handle with ble_nus_c_handles_assign() when you get the event BLE_NUS_C_EVT_DISCOVERY_COMPLETE. In nus_c_init() and db_discovery_init() you will need to initialize each instance. In nus_c_init() this could look something like this:

    static void nus_c_init(void)
    {
        uint32_t         err_code;
        ble_nus_c_init_t nus_c_init_t;
    
        nus_c_init_t.evt_handler = ble_nus_c_evt_handler;
        
    	for (m_ble_nus_c_count = 0; m_ble_nus_c_count < TOTAL_LINK_COUNT; m_ble_nus_c_count++)
        {
            err_code = ble_nus_c_init(&m_ble_nus_c[m_ble_nus_c_count], &nus_c_init_t);
            APP_ERROR_CHECK(err_code);
        }
        m_ble_nus_c_count = 0;
    }
    

    The db_disc_handler() function would look something like this:

    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_nus_c_on_db_disc_evt(&m_ble_nus_c[p_evt->conn_handle], p_evt);
    }
    

    In ble_evt_dispatch(), ble_db_discovery_on_ble_evt() and ble_nus_c_on_ble_evt() should be changed to something like this:

    uint16_t conn_handle;
    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
    ble_db_discovery_on_ble_evt(&m_ble_db_discovery[conn_handle], p_ble_evt);
    ble_nus_c_on_ble_evt(&m_ble_nus_c[conn_handle],p_ble_evt);
    

    You should also take a look at the multilink central example in the SDK to see how this example handles multiple connections.

Children
  • Thanks Sigurd, that is basically the code I ended up with.

  • Hi Sigurd,

    by referring this above, I am using the multilink central example for NUS_C, i changed the code by combining the multilink central and BLE_APP_UART central, i am trying to print the data, but i am not able to print data and also i am getting error after disconnecting all the peripheral.. please suggest me to resolve this issue

    I am getting error like this 

    Nordic_Blinky.
    .<info> app: Connection 0x1 established, starting DB discovery.
    .<info> app: NUS central link 0x1 disconnected (reason: 0x8)
    .<info> app: Start scanning for device name Nordic_Blinky.
    .<info> app: Connection 0x1 established, starting DB discovery.
    .<info> app: NUS central link 0x1 disconnected (reason: 0x8)
    .<info> app: Start scanning for device name Nordic_Blinky.
    .<info> app: Connection 0x1 established, starting DB discovery.
    .<info> app: NUS central link 0x1 disconnected (reason: 0x8)
    .<info> app: Start scanning for device name Nordic_Blinky.
    .<info> app: NUS central link 0x0 disconnected (reason: 0x8)
    .<info> app: Start scanning for device name Nordic_Blinky.
    .<error> app: ERROR 8 [NRF_ERROR_INVALID_STATE] at D:\Printer_software\New Folder\nRF5_SDK_14.2.0_17b948a\nRF5_SDK_14.2.0_17b948a\examples\ble_central\ble_app_multilink_central -working\main.c:217

  • Hi Kashinath,

    You are running into the APP_ERROR_CHECK(err_code) on line 217 in main.c. You should check what function returned this err_code(often the function right above the APP_ERROR_CHECK), and why it returned NRF_ERROR_INVALID_STATE. If you have more questions about this, you should create your own question here at Devzone.

  • Hi Sigurd,

    Thank you for you reply,

    Now that issue solved, now multi connection to central is working, but it is not printing data received from peripheral, means next event is not working, i getting output like this in terminal:

    <warning> nrf_sdh_ble: RAM starts at 0x20004190, can be adjusted to 0x20002038.
    .<warning> nrf_sdh_ble: RAM size can be adjusted to 0xDFC8.
    .<info> app: Multilink example started.
    .<info> app: Start scanning for device name Nordic_Blinky.
    .<info> app: Connection 0x0 established, starting DB discovery

    Please suggest me, i am new to this. thank you in advance

  • Hello Sigurd,

    where should i set "ble_nus_c_handles_assign(..)" function?

    All the definition are follow the sample code as you provided.

    Thanks.

Related