Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Advertising Stops After Connection - Restarting on Connection Works Most of the Time

We are developing using SDK 15.3.0 and S140. After I noticed that advertising stopped when a connection occurred, I was directed to simply restart upon connection. I have been doing so with largely successful results, but I recently noticed that (on rare occasion) advertising does not restart. This is 1 out of hundreds of connections when the central connecting device is Android, but far more frequent when the central connecting device is a Raspberry Pi 3B running Linux. I would like get an on_ble_evt handler in place and just restart advertising when notified that it has stopped or BLE_ADV_EVT_IDLE, but I cannot see how to set the ble_adv_event_handler_t when the advertising module is not used. I am setting up by advertising using the following code.

// Config advertising.
void xtag_adv_config(bool firstCall)
{
  ret_code_t             err_code;

  // Setup var to hold ble_advdata_t advert data. 
  ble_advdata_t advdata;
  memset(&advdata, 0, sizeof(advdata));

  // Setup var to hold ble_advdata_t scan resp data. 
  ble_advdata_t srdata;
  memset(&srdata, 0, sizeof(srdata));

  // Just use srdata to indicate that we want to expose the name provided in gap_params_init().
  srdata.name_type = BLE_ADVDATA_FULL_NAME;
  
  // Setup variable to hold manufacturer specific advert data
  ble_advdata_manuf_data_t mfr_advdata; 
  memset(&mfr_advdata, 0, sizeof(mfr_advdata));

  // Update mfr_data and add to advdata.
  uint8_t data[MFR_PAYLOAD_SIZE_GAP];
  xtag_adv_mfr_data_setup(data);

  mfr_advdata.company_identifier =  0x030E; //Dworx company ID
  mfr_advdata.data.p_data = data;
  mfr_advdata.data.size = sizeof(data);
  advdata.name_type = BLE_ADVDATA_NO_NAME;
  advdata.p_manuf_specific_data = &mfr_advdata;

  advdata.include_appearance      = true;
  advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
  advdata.uuids_complete.p_uuids  = m_adv_uuids;

  // Initialize advertising parameters (used when starting advertising).
  memset(&m_adv_params, 0, sizeof(m_adv_params));

  m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
  m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
  m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
  m_adv_params.interval        = APP_ADV_INTERVAL;
  m_adv_params.duration        = 0;       // Never time out.

  // Encode advdata to m_gapData[m_bufIdx]
  err_code = ble_advdata_encode(&advdata, m_gapData[m_bufIdx].adv_data.p_data, (uint16_t *) &m_gapData[m_bufIdx].adv_data.len);
  APP_ERROR_CHECK(err_code);

  // Encode srdata to m_gapData[m_bufIdx]
  err_code = ble_advdata_encode(&srdata, m_gapData[m_bufIdx].scan_rsp_data.p_data, (uint16_t *) &m_gapData[m_bufIdx].scan_rsp_data.len);
  APP_ERROR_CHECK(err_code);

  // Setup adverts. On first call, also set advert params.
  if(firstCall)
  {
    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_gapData[m_bufIdx], &m_adv_params);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV,m_adv_handle, xTag_get_tx_pwr()); 
    APP_ERROR_CHECK(err_code);
  }
  else  // Susequent calls - update payloady only.
  {
    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_gapData[m_bufIdx], NULL);
    APP_ERROR_CHECK(err_code);
  }

  // Toggle buffer index to toggle buffer used.
  if(m_bufIdx == 0) {m_bufIdx ++;}
  else {m_bufIdx = 0;}
}

Thanks in advance.

Mark J

Parents
  • ... more info that might help ...

    I only get BLE_GAP_EVT_ADV_SET_TERMINATED within my ble event handler when a timeout occurs. I DO NOT get BLE_GAP_EVT_ADV_SET_TERMINATED when advertising stops due to connection. IF I was able to get BLE_GAP_EVT_ADV_SET_TERMINATED  whenever advertising stopped (for all reasons), I would just trigger a restart when BLE_GAP_EVT_ADV_SET_TERMINATED  was recieved.

    Regards,

    Mark J 

  • Hi,

    I would recommend taking a look at how this is done in the ble_app_multiperipheral example. Here we keep track of the number of connections with the ble_conn_state module, and we start advertising on connect and disconnect event when there are available links. Simply call sd_ble_gap_adv_start().

    but I recently noticed that (on rare occasion) advertising does not restart.

     You get the connected event, then call sd_ble_gap_adv_start() ? Did sd_ble_gap_adv_start() return any error-code ? Are you calling sd_ble_gap_adv_stop() somewhere ?

  • I am calling sd_ble_gap_adv_start() in a similar way to the ble_app_multiperipheral example (i.e. when getting a BLE_GAP_EVT_CONNECTED event). I have not, however, been checking the result of sd_ble_gap_adv_start(). I can log the result and restart firmware as required when sd_ble_gap_adv_start() returns anything except NRF_SUCESS. This, however, seems drastic. 

    To answer your other question - no I am not calling sd_ble_gap_adv_stop().

    I am debating putting the advertising restarts on a timer (i.e. setup 10 sec advertising and then restart every 10.5 sec). This would introduce a minimal delay whenever advertising stops due to connect (or other), but that is far better than having advertising stop all together. Thoughts?

  • Yes, restarting the firmware seems drastic. First step would be to log the return code, print it over UART/RTT and just see if anything else than NRF_SUCESS is returned.

    Are you restarting advertising on disconnect event also ?

    Are you doing non-connectable or connectable advertising after the central device connects? 

    Mark J said:
    I am debating putting the advertising restarts on a timer (i.e. setup 10 sec advertising and then restart every 10.5 sec). This would introduce a minimal delay whenever advertising stops due to connect (or other), but that is far better than having advertising stop all together. Thoughts?

    It's definitely a potential workaround.

  • To answer your questions ...

    Restart on connect event only. Advertising seems to continue fine after disconnection. 

    Always connectable advertising - before and after connection.

    I might jump to the workaround.

    Thanks for getting back to me.

    Mark J

Reply Children
Related