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

  • 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

  • Thanks a lot @awneil. Your code is very helpful! 

    What I did:
    - I replaced my advertising_start() with yours.
    - I added a call to advertising_start() on connected in ble_evt_handler()
    - I commented out the calls that change the Manufacturer Specific Data (set_adv_mfr_spec_busy and ble_advdata_encode). Could you please also share that code? That would be very helpful. I'm using ble_advertising_advdata_update() right now, which is not very satisfying.

    Result:
    - Advertisement starts
    - When connected, a NRF_ERROR_INVALID_PARAM occurs on sd_ble_gap_adv_start() in advertising_start().

    Can you help, how I can track that error down?

  • Could you please also share that code?

    Sorry, no. But I don't think it would help - it's just a flag in a set of entirely proprietary data.

    Can you help, how I can track that error down

    Sadly not.

    It's a very unhelpful code from Nordic:

    https://devzone.nordicsemi.com/f/nordic-q-a/49799/issue-regarding-nrf52840-long-range-mode/198921#198921

    So it's a matter of guesswork, trial & error to work out exactly which parameter is "invalid", and what is "invalid" about it.

    Disappointed

    I guess it must still be wanting something to do with the Manufacturer Specific Data ... ?

  • It is working! Yeay!

    I completely removed the code for Manufacturer Specific Data, so that was not the problem.

    I had to make a memcpy of advdata and store it as m_advdata. That way, I could re-add the call to ble_advdata_encode().

    Then I had the error NRF_ERROR_CONN_COUNT at sd_ble_gap_adv_start(). I solved that by changing 
    BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
    to 
    BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED.
    Maybe you can give me a hint, why I have to keep it scannable.

    But still, it is good enough for the customer presentation tomorrow! Puh! Blush

  • Maybe you can give me a hint, why I have to keep it scannable

    No Idea!

    I did encounter the NRF_ERROR_CONN_COUNT in my travels, but it seemed to be due to doing connectable advertising - which makes sense.

Related