DA14531 how to handle disconnects as a central

I am using SDK 6.0.16 (I haven't tried the newest SDK update because the rest of my code base is based on this version still) and I am trying to connect 3 DA14531 peripherals to a single DA14531 central. I based my code on the multirole example in the BLE_SDK6_examples Github and only used the central side of the multirole example code. I successfully modified this to be able to scan for 3 specific names that are preset on the peripherals, connect, and scan for their services/characteristics.

However, sometimes the multirole code will find the connection to a peripheral but it will not scan for the services/characteristics that I can read and write to. I want to be able to turn off and back on the peripheral that has not been successfully connected in order to essentially refresh its presence and let the central device reconnect and scan the peripheral. However, currently if I turn off any of the connected peripherals, it will throw an error in the "gapc_disconnect_ind_handler" where an "ASSERT_ERROR(0)" is thrown:

static int gapc_disconnect_ind_handler(ke_msg_id_t const msgid,
                                       struct gapc_disconnect_ind const *param,
                                       ke_task_id_t const dest_id,
                                       ke_task_id_t const src_id)
{
    uint8_t state = ke_state_get(dest_id);
    uint8_t conidx = KE_IDX_GET(src_id);

    if (state == APP_CONNECTED)
    {
        app_env[conidx].conidx = GAP_INVALID_CONIDX;
        app_env[conidx].connection_active = false;
        CALLBACK_ARGS_1(user_app_callbacks.app_on_disconnect, param)
    }
    else
    {
        // We are not in Connected State
        ASSERT_ERROR(0);
    }

    return (KE_MSG_CONSUMED);
}

I am correct in thinking that I should comment out this existing code in the sdk ("app_task.c") and re-implement without the "ASSERT_ERROR(0)" and instead figure out what the handle is of whichever connection was just dropped and then remove that from my global struct (because I'm using a global struct to keep track of all my existing connection id handles)? It is not clear to me what the if/else statement is doing and it seems that the "ASSERT_ERROR" is always going to be thrown unless the central is the one to disconnect.

  • Hi There,

    Thank you for posting your question online.

    However, sometimes the multirole code will find the connection to a peripheral but it will not scan for the services/characteristics that I can read and write to.

    The Central was probably not able to establish a connection with that peripheral. This is the reason you are not able to discover the Services and Characteristics, and this is the reason why in the gapc_disconnect_ind_handler, the state variable is not APP_CONNECTED and you are getting this ASSERT_ERROR.

    I based my code on the multirole example in the BLE_SDK6_examples Github and only used the central side of the multirole example code.

    If you are not going to use the Multirole functionality, you should work with the central example. 

    On the Central example, when we have found one of the Peripheral devices we want to connect to, we stop scanning and initiate the Connection procedure. This happens in the custom callback function user_on_scanning_complete:

        .app_on_scanning_completed          = user_on_scanning_completed,

    In the user_on_scanning_complete callback function, we attempt to connect to the Peripheral device and we start an app_easy_timer. If the timer expires and the connection has not been established, then we do not consider the connection valid and the scan will start again. 
    static void connection_timeout_cb(){
    	
    	central_app_env.connection_timer = EASY_TIMER_INVALID_TIMER;
    	user_ble_cancel_connect();
    }
    
    
    void user_on_scanning_completed(uint8_t reason)
    {
    	
    	if(reason == GAP_ERR_CANCELED)
    	{
    		user_ble_gap_connect(central_app_env.connect_to_addr.addr, central_app_env.connect_to_addr_type);
    		central_app_env.connection_timer = app_easy_timer(CONNECTION_TIMEOUT_10MS, connection_timeout_cb);
    	}
    	else{
    			
    		dbg_printf("%s: ERR: reason: %d\r\n", __func__, reason);
    	}
    	
    	
    	
    }

    Then on the user_on_connection custom callback function we cancel this timer. 
    I believe you should implement in your project something like that, in order to be sure that the connection that was established was valid. 
    Are you working with Security enabled in your project?

    Kind Regards,
    OV_Renesas