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

Advertise 'Connected' when connected

Hello,

we are developing an asset tracking solution. The Noridic send out BLE Advertisements to show, that they are still available. These signals are received by Receivers in the room. So far, so common.

The special thing in our case is, that the Trackers are connectable. When somebody (not the Receivers) connect to the Trackers, they don't send out Advertisements any more. So the Receivers don't get the "Heartbeat" anymore and think the Devices have left the room and start an alarm.

So the expected behavior could be one of these two options:

  • (Prefered): When a connection is established, they send out a 'Connected' Signal, so the Receivers can remove them from the list of Objects that need to be tracked. (Kind of a sign off the system). We are already using the Manufacturer Specific Data for stuff like that.
  • Continue the advertisement when connected.

We are using SDK 15.3.0 with Softdevice 6.1.1 on Nordic NRF52340.

Thanks for your help in advance!

Sebastian

Parents
  • Especially one question is still not solved in my head: How can I prevent the chip from stopping the advertisement when connected?

  • Are you using the Advertising Module?

    Do you want to continue connectable advertising, or switch to non-connectable?

  • Yes, I'm using the Advertising Module.

    Switching to non-connectable would be preferable.

  • As noted in the other thread, the Advertising Module doesn't support non-connectable - so you have to do that bit manually.

    You can still use the Advertising Module to do your "normal"  (connectable) advertising (I use the Advertising Module to initially start advertising).

     In my BLE Event Handler, I have:

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("GAP EV: Disconnected.");
    
                g_conn_handle = BLE_CONN_HANDLE_INVALID;
    
                advertising_stop();
                advertising_start();
                break;
    
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("GAP EV: Connected.");
    
                g_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
                advertising_start();
                break;
    

    my advertising_start() decides whether to start Connectable or Non-Connectable advertsing, based on the g_conn_handle:

    /**@brief Function for starting advertising - connectable or not, as appropriate.
     *
     * @note Must not be already advertising.
     */
    void advertising_start(void)
    {
        uint32_t    err_code;
        ble_gap_adv_params_t  adv_params;
    
        memcpy(&adv_params, &m_advertising.adv_params, sizeof(adv_params));
    
        if( g_conn_handle == BLE_CONN_HANDLE_INVALID )
        {   // No connection - Do Connectable Advertising
            NRF_LOG_INFO( "Start Connectable adv:" );
            adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        }
        else
        {   // Connected - Do Non Connectable Advertising
            NRF_LOG_INFO( "Start Non-conn Non-scan adv:" );
            adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
        }
    
        // Update the Advertising Data to use the latest Manufacturer-Specific Data
        set_adv_mfr_spec_busy();
        err_code = ble_advdata_encode( &m_advdata, m_advertising.enc_advdata, &m_advertising.adv_data.adv_data.len );
        APP_ERROR_CHECK(err_code);
    
        // Restore parameters which get trashed by the Advertising module
        adv_params.duration = APP_ADV_DURATION;
        adv_params.interval = APP_ADV_INTERVAL;
    
        // Don't let the Advertising module think it's got somewhere else in its advertising sequence
        m_advertising.adv_mode_current = BLE_ADV_MODE_FAST;
    
        err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle,
                                                &m_advertising.adv_data,
                                                &adv_params);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, m_advertising.conn_cfg_tag);
        APP_ERROR_CHECK(err_code);
    }

    Note that I am updating the Manufacturer-Specific Data in the Advertising Data each time I (re-)start - just omit that if you don't want it.

    One of the things in my Manufacturer-Specific Data is a flag which identifies whether the unit is busy (ie, already connected) or not - so that things other don't try to connect while the device is already connected. 

    This is because not all Centrals pas the 'connectable' flag to the application.

    Disappointed

Reply
  • As noted in the other thread, the Advertising Module doesn't support non-connectable - so you have to do that bit manually.

    You can still use the Advertising Module to do your "normal"  (connectable) advertising (I use the Advertising Module to initially start advertising).

     In my BLE Event Handler, I have:

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("GAP EV: Disconnected.");
    
                g_conn_handle = BLE_CONN_HANDLE_INVALID;
    
                advertising_stop();
                advertising_start();
                break;
    
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("GAP EV: Connected.");
    
                g_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
                advertising_start();
                break;
    

    my advertising_start() decides whether to start Connectable or Non-Connectable advertsing, based on the g_conn_handle:

    /**@brief Function for starting advertising - connectable or not, as appropriate.
     *
     * @note Must not be already advertising.
     */
    void advertising_start(void)
    {
        uint32_t    err_code;
        ble_gap_adv_params_t  adv_params;
    
        memcpy(&adv_params, &m_advertising.adv_params, sizeof(adv_params));
    
        if( g_conn_handle == BLE_CONN_HANDLE_INVALID )
        {   // No connection - Do Connectable Advertising
            NRF_LOG_INFO( "Start Connectable adv:" );
            adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        }
        else
        {   // Connected - Do Non Connectable Advertising
            NRF_LOG_INFO( "Start Non-conn Non-scan adv:" );
            adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
        }
    
        // Update the Advertising Data to use the latest Manufacturer-Specific Data
        set_adv_mfr_spec_busy();
        err_code = ble_advdata_encode( &m_advdata, m_advertising.enc_advdata, &m_advertising.adv_data.adv_data.len );
        APP_ERROR_CHECK(err_code);
    
        // Restore parameters which get trashed by the Advertising module
        adv_params.duration = APP_ADV_DURATION;
        adv_params.interval = APP_ADV_INTERVAL;
    
        // Don't let the Advertising module think it's got somewhere else in its advertising sequence
        m_advertising.adv_mode_current = BLE_ADV_MODE_FAST;
    
        err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle,
                                                &m_advertising.adv_data,
                                                &adv_params);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, m_advertising.conn_cfg_tag);
        APP_ERROR_CHECK(err_code);
    }

    Note that I am updating the Manufacturer-Specific Data in the Advertising Data each time I (re-)start - just omit that if you don't want it.

    One of the things in my Manufacturer-Specific Data is a flag which identifies whether the unit is busy (ie, already connected) or not - so that things other don't try to connect while the device is already connected. 

    This is because not all Centrals pas the 'connectable' flag to the application.

    Disappointed

Children
No Data
Related