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

Implementing a bonding mode

Device:

  • Peripheral only
  • Peer Manager and Bonding working
  • S140 radio
  • nRF5 SDK 15.2.0
  • Rigado BMD-340 module
  • Central == iOS devices

Our nRF5 module is controlled by a Kinetis which uses a GPIO to indicate it should boot into a "bonding mode".  In this mode, it should advertise to any device with power at -40. (This is working). When not in bonding mode, we want the device to advertise only to bonded devices (and do this at +8 power).  The idea is that bonding should occur in close proximity only, and only bonded devices can connect when in non-bonding mode at higher power (allowing connection at a larger distance).

I have been trying to accomplish this through various means such as whitelist.  This is implemented and works, but I can not stop it from doing some other sort of advertising (fast/slow). If I configure advertising to only do whitelist, the API returns an error (don't have it handy, but was along the lines of "incorrect parameter").

My testing for this involved adding the HRM guid to our advertising data, which allows it to appear in the iOS Bluetooth browse list. (Our device normally advertises BAS, DI, and a custom service - which won't show up in the normal "device browser", can only be discovered using APIs in our iOS app.)

Code for our advertising init is below. In this code I tried setting fast/slow to low timeouts, but iOS still sees it.  Any suggestions on how to make this work properly, or a different approach?

   memset(&init, 0, sizeof(init));
    init.evt_handler                                = on_adv_evt;
    init.error_handler                              = ble_advertising_error_handler;
    init.advdata.name_type                          = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance                 = true;
    init.advdata.flags                              = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
    init.srdata.uuids_complete.uuid_cnt             = sizeof(s_adv_uuids) / sizeof(s_adv_uuids[0]);
    init.srdata.uuids_complete.p_uuids              = s_adv_uuids;
    init.config.ble_adv_on_disconnect_disabled      = false;
    if (nrf_gpio_pin_read(PIN_BOND))
    {
        init.config.ble_adv_fast_enabled            = true;
        init.config.ble_adv_fast_interval           = APP_ADV_FAST_INTERVAL;
        init.config.ble_adv_fast_timeout            = APP_ADV_FAST_DURATION;
        init.config.ble_adv_slow_enabled            = true;
        init.config.ble_adv_slow_interval           = APP_ADV_SLOW_INTERVAL;
        init.config.ble_adv_slow_timeout            = APP_ADV_SLOW_DURATION;
        init.config.ble_adv_whitelist_enabled       = false;
    }
    else
    {
        init.config.ble_adv_directed_high_duty_enabled = true;
        init.config.ble_adv_directed_enabled        = true;
        init.config.ble_adv_directed_interval       = APP_ADV_FAST_INTERVAL;
        init.config.ble_adv_directed_timeout        = APP_ADV_FAST_DURATION;
        init.config.ble_adv_whitelist_enabled       = true;
        init.config.ble_adv_fast_enabled            = true;
        init.config.ble_adv_fast_interval           = 40;
        init.config.ble_adv_fast_timeout            = 100;
        init.config.ble_adv_slow_enabled            = true;
        init.config.ble_adv_slow_interval           = 1600;
        init.config.ble_adv_slow_timeout            = 100;
    }
    err_code = ble_advertising_init(&s_advertising, &init);
    APP_ERROR_CHECK(err_code);
    ble_advertising_conn_cfg_tag_set(&s_advertising, APP_BLE_CONN_CFG_TAG);

Thanks!

Parents
  • Hi!

    Did some research about this together with a colleague. 

    Without doing some extensive research in the spec. and the code, I think we found a valid workaround for you.

    I suspect the error you are seeing is related to the advertising module wanting to increment the advertising mode on timeout, but slow/fast is not enabled.

    A workaround for this is not to increment the advertising mode, but rather restart the advertising using directed advertising. 

    static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode)
    {
        if(adv_mode== BLE_ADV_MODE_DIRECTED_HIGH_DUTY )
        {
          return BLE_ADV_MODE_DIRECTED_HIGH_DUTY;
        }
        else
        {
        return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES);
        }
    } 

    Let me know if this is something that could work for you. 

    Best regards, 
    Joakim

  • I believe we have come up with a working solution... in on_adv_evt() we now do the following:

            case BLE_ADV_EVT_FAST:
                // If we are not in bonding mode, do not enter FAST
                if (!nrf_gpio_pin_read(PIN_BOND))
                {
                    NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_FAST - Restarting advertising");
    
                    APP_ERROR_CHECK(ble_advertising_start(&s_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY));
                    break;
                }
    
                // Set the power output to the appropriate level (default is 0 dBm)
                NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_FAST - ADV_TX_POWER_LEVEL: %d", ADV_TX_POWER_LEVEL);
                err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, s_advertising.adv_handle, ADV_TX_POWER_LEVEL);
                APP_ERROR_CHECK(err_code);
    
                break;
    
            case BLE_ADV_EVT_SLOW:
                // If we are not in bonding mode, do not enter SLOW
                if (!nrf_gpio_pin_read(PIN_BOND))
                {
                    NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_SLOW - Restarting advertising");
    
                    APP_ERROR_CHECK(ble_advertising_start(&s_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY));
                    break;
                }
    
    

    If we are not in bonding mode, and FAST/SLOW WHITELIST timeout, we will move back to trying directed (if possible) then back to FAST WHITELIST.

    Do you see any issues with doing it this way?

Reply
  • I believe we have come up with a working solution... in on_adv_evt() we now do the following:

            case BLE_ADV_EVT_FAST:
                // If we are not in bonding mode, do not enter FAST
                if (!nrf_gpio_pin_read(PIN_BOND))
                {
                    NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_FAST - Restarting advertising");
    
                    APP_ERROR_CHECK(ble_advertising_start(&s_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY));
                    break;
                }
    
                // Set the power output to the appropriate level (default is 0 dBm)
                NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_FAST - ADV_TX_POWER_LEVEL: %d", ADV_TX_POWER_LEVEL);
                err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, s_advertising.adv_handle, ADV_TX_POWER_LEVEL);
                APP_ERROR_CHECK(err_code);
    
                break;
    
            case BLE_ADV_EVT_SLOW:
                // If we are not in bonding mode, do not enter SLOW
                if (!nrf_gpio_pin_read(PIN_BOND))
                {
                    NRF_LOG_INFO("on_adv_evt():BLE_ADV_EVT_SLOW - Restarting advertising");
    
                    APP_ERROR_CHECK(ble_advertising_start(&s_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY));
                    break;
                }
    
    

    If we are not in bonding mode, and FAST/SLOW WHITELIST timeout, we will move back to trying directed (if possible) then back to FAST WHITELIST.

    Do you see any issues with doing it this way?

Children
Related