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

Enabling and disabling Bluetooth

Hi there,

I'm currently working on a project in which I need to be able to deactivate Bluetooth advertising at the press of a button. I am using SDK 15.3 and have built a custom service from the ble_app_template example, following this tutorial. I have been able to get Bluetooth communication up and running, but am having difficulty deactivating it without causing the script to fail. To clarify, all I need it to do is to disable communication, not necessarily disable the entire module.

Here is the way I am currently enabling Bluetooth (working):

/**@brief Function for starting advertising.
 */
static void advertising_start(bool erase_bonds)
{
    if (erase_bonds == true)
    {
        delete_bonds();
        // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED event
    }
    else
    {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);

        APP_ERROR_CHECK(err_code);
    }
}

And this is the function I'm trying to use to disable it:

static void advertising_disconnect(void)
{
    ret_code_t err_code;

    // If connected, disconnect
    if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
    {
        err_code = sd_ble_gap_disconnect(m_conn_handle,
                                         BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        APP_ERROR_CHECK(err_code);
    }
    // Stop advertising
    err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
    APP_ERROR_CHECK(err_code);
}

When the button is pressed while no connected has been established, it hangs on sd_ble_gap_adv_stop() and will not reach the APP_ERROR_CHECK.

When the button is pressed while connected to a device, sd_ble_gap_disconnect() will work, but an error is generated at sd_ble_gap_adv_stop().

Is there a specific file I need to include in order to use sd_ble_gap_adv_stop()? Or maybe another way to achieve this?

*I have also tried using ble_advertising_start() to enter IDLE mode as a way of disabling communication but have not been able to get this to work either.

Any help would be much appreciated.

Cheers,

Charlie

  • I'm away from my main system right now, but I believe the proper way to stop advertising is:

    ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE);

  • Hi Charlie

    You should be able to call ble_advertising_start(BLE_ADV_MODE_IDLE); and sd_ble_gap_adv_stop(); to stop advertising. You can also check out this example, where someone is restarting advertising with a button press. That should be rather similar to what you're trying to do.

    Best regards,

    Simon

  • Hi Simon

    Thank you for your help, I have managed to get sd_ble_gap_adv_stop(); to work when no connection has been established and am able to then toggle between advertising and not. However, I still cannot turn advertising off when a connection is established.

    Simply executing sd_ble_gap_adv_stop(); from the connected state has resulted in a NRF_ERROR_INVALID_STATE. I have tried removing the APP_ERROR_CHECK(err_code); but the connection is still not broken (possible that I am oversimplifying this and removing APP_ERROR_CHECK is not the same as ignoring the error code). 

    Now, I am attempting to break the connection using sd_ble_gap_disconnect as bellow, where the function on_disconnect(); is used to update several parameters to match the new state. 

    /**@brief Function for handling the Disconnect event.
     *
     * @param[in]   p_cus       Custom Service structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    void on_disconnect(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
    {
        UNUSED_PARAMETER(p_ble_evt);
        p_cus->conn_handle = BLE_CONN_HANDLE_INVALID;
        
        ble_cus_evt_t evt;
    
        evt.evt_type = BLE_CUS_EVT_DISCONNECTED;
    
        p_cus->evt_handler(p_cus, &evt);
    }
    
    /**@brief Function for stoping advertising.
     */
    void advertising_stop(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for disconnecting device.
     */
    void advertising_disconnect()
    {
        ret_code_t err_code;
        
        // If connected, disconnect
        if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            APP_ERROR_CHECK(err_code);
        }
    
        ble_evt_t const * p_ble_evt;
        void * p_context;
    
        ble_cus_t * p_cus = (ble_cus_t *) p_context;
    
        on_disconnect(p_cus, p_ble_evt);
    }

    The order these functions are called is: connection is established --> advertising_disconnect(); --> advertising_stop();

    Now with the code above, I am getting the error SOFTDEVICE: INVALID MEMORY ACCESS. 

    When on_disconnect(); is commented out, an NRF_ERROR_INVALID_STATE is once again generated (also doesn't work when the error check is removed).

    I believe the issue may be from the sd_ble_gap_disconnect(); function as the evt_id appears to be different after every time I call it. Is there another way of severing the connection or just a general better way of handling this? 

    Thanks,

    Charlie

  • Hi

    How are you handling your disconnect events? The NRF_ERROR_INVALID_STATE from these functions means a disconnect is already in progress. You'll have to handle the events in the application code. Most of our ble_peripheral examples does this. Please check out the BLE_GAP_EVT_DISCONNECTED in any of them. Also, did you take a look at the post I linked to in my previous reply?

    Best regards,

    Simon

  • Hi,

    I finally managed to get everything working the other day. My main mistake was trying to run advertising_stop() immediately after advertising_disconnect() as the stop function would be called before the disconnect event was complete. To fix this, I added the stop function to the end of my BLE_GAP_EVT_DISCONNECTED event structure to ensure it was competed first (sd_ble_gap_disconnect(), once complete, will generate the BLE_GAP_EVT_DISCONNECTED evt_id and thus trigger the observer leading to the event handler).

    Thank you for your help,

    Charlie

Related