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

Connection of nrf52382 (as peripheral) and nrf connect application as central

#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_dis.h"
#include "boards.h"
#include "sensorsim.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "bsp.h"
#include "bsp_btn_ble.h"
#include "peer_manager.h"
#include "peer_manager_handler.h"
#include "fds.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "ble_conn_state.h"

#include "app_error.h"
#include "app_timer.h"
#include "task_manager.h"
#include "nrf_cli.h"
#include "nrf_cli_rtt.h"
#include "nrf_cli_uart.h"
#include "nrf_cli_ble_uart.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_drv_clock.h"
#include "nrf_stack_guard.h"
#include "nrf_fstorage_sd.h"
#include "nrf_ble_scan.h"
#include "ble_db_discovery.h"
#include "ble_nus.h"
#include "ble_cus.h"
//#include "ble_hts.h"
#include "ble_conn_params.h"
#include "flash_write.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_backend_flash.h"


#define DEVICE_NAME                     "Nordic_CLI"                                /**< Name of device. Will be included in the advertising data. */
#define MANUFACTURER_NAME               "NordicSemiconductor"                       /**< Manufacturer. Will be passed to Device Information Service. */
#define APP_ADV_INTERVAL                300                                         /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */

#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

#define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */

#define BATTERY_LEVEL_MEAS_INTERVAL      APP_TIMER_TICKS(2000)                      /**< Battery level measurement interval (ticks). */
#define MIN_BATTERY_LEVEL                81                                         /**< Minimum simulated battery level. */
#define MAX_BATTERY_LEVEL                100                                        /**< Maximum simulated 7battery level. */
#define BATTERY_LEVEL_INCREMENT          1                                          /**< Increment between each simulated battery level measurement. */

#define MIN_CONN_INTERVAL                MSEC_TO_UNITS(400, UNIT_1_25_MS)           /**< Minimum acceptable connection interval (0.4 seconds). */
#define MAX_CONN_INTERVAL                MSEC_TO_UNITS(650, UNIT_1_25_MS)           /**< Maximum acceptable connection interval (0.65 second). */
#define SLAVE_LATENCY                    0                                          /**< Slave latency. */
#define CONN_SUP_TIMEOUT                 MSEC_TO_UNITS(4000, UNIT_10_MS)            /**< Connection supervisory timeout (4 seconds). */

#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */

#define SEC_PARAM_BOND                  1                                           /**< Perform bonding. */
#define SEC_PARAM_MITM                  0                                           /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC                  0                                           /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS              0                                           /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_NONE                        /**< No I/O capabilities. */
#define SEC_PARAM_OOB                   0                                           /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE          7                                           /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE          16                                          /**< Maximum encryption key size. */

#define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */


#define SCHED_MAX_EVENT_DATA_SIZE           APP_TIMER_SCHED_EVENT_DATA_SIZE            /**< Maximum size of scheduler events. */
#ifdef SVCALL_AS_NORMAL_FUNCTION
#define SCHED_QUEUE_SIZE                    20                                         /**< Maximum number of events in the scheduler queue. More is needed in case of Serialization. */
#else
#define SCHED_QUEUE_SIZE                    10                                         /**< Maximum number of events in the scheduler queue. */
#endif



#ifdef RK_CLI

#define ADDR_STRING_LEN         (2 * (BLE_GAP_ADDR_LEN)+6)
#define BLE_UUID_NUS_SERVICE            0x0001                      /**< The UUID of the Nordic UART Service. */
#define NUS_SERVICE_UUID_TYPE   BLE_UUID_TYPE_VENDOR_BEGIN              /**< UUID type for the Nordic UART Service (vendor specific). */
NRF_BLE_SCAN_DEF(m_scan);
#define N_AD_TYPES 4
#define UUID128_SIZE    16  /**< Size of 128 bit UUID. */
#define UUID16_SIZE 2


#define APP_SCHED_EVENT_HEADER_SIZE 8       /**< Size of app_scheduler.event_header_t (only for use inside APP_SCHED_BUF_SIZE()). */

/**@brief Compute number of bytes required to hold the scheduler buffer.
 *
 * @param[in] EVENT_SIZE   Maximum size of events to be passed through the scheduler.
 * @param[in] QUEUE_SIZE   Number of entries in scheduler queue (i.e. the maximum number of events
 *                         that can be scheduled for execution).
 *
 * @return    Required scheduler buffer size (in bytes).
 */
#define APP_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE)                                                 \
            (((EVENT_SIZE) + APP_SCHED_EVENT_HEADER_SIZE) * ((QUEUE_SIZE) + 1))

/**@brief Scheduler event handler type. */
typedef void (*app_sched_event_handler_t)(void * p_event_data, uint16_t event_size);

/**@brief Macro for initializing the event scheduler.
 *
 * @details It will also handle dimensioning and allocation of the memory buffer required by the
 *          scheduler, making sure the buffer is correctly aligned.
 *
 * @param[in] EVENT_SIZE   Maximum size of events to be passed through the scheduler.
 * @param[in] QUEUE_SIZE   Number of entries in scheduler queue (i.e. the maximum number of events
 *                         that can be scheduled for execution).
 *
 * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it
 *       several times as long as it is from the same location, e.g. to do a reinitialization).
 */
#define APP_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE)                                                     \
    do                                                                                             \
    {                                                                                              \
        static uint32_t APP_SCHED_BUF[CEIL_DIV(APP_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)),     \
                                               sizeof(uint32_t))];                                 \
        uint32_t ERR_CODE = app_sched_init((EVENT_SIZE), (QUEUE_SIZE), APP_SCHED_BUF);             \
        APP_ERROR_CHECK(ERR_CODE);                                                                 \
    } while (0)



/**@brief Function for executing all scheduled events.
 *
 * @details This function must be called from within the main loop. It will execute all events
 *          scheduled since the last time it was called.
 */
void app_sched_execute(void);

/**@brief Function for scheduling an event.
 *
 * @details Puts an event into the event queue.
 *
 * @param[in]   p_event_data   Pointer to event data to be scheduled.
 * @param[in]   event_size     Size of event data to be scheduled.
 * @param[in]   handler        Event handler to receive the event.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
uint32_t app_sched_event_put(void const *              p_event_data,
                             uint16_t                  event_size,
                             app_sched_event_handler_t handler);

/**Buffer queue access macros
 *
 * @{ */
/** Initialization of buffer list */
#define BUFFER_LIST_INIT()     \
    do                         \
    {                          \
        buffer_list.rp    = 0; \
        buffer_list.wp    = 0; \
        buffer_list.count = 0; \
    } while (0)

/** Provide status of data list is full or not */
#define BUFFER_LIST_FULL() \
    ((MAX_BUFFER_ENTRIES == buffer_list.count - 1) ? true : false)

/** Provides status of buffer list is empty or not */
#define BUFFER_LIST_EMPTY() \
    ((0 == buffer_list.count) ? true : false)

#define BUFFER_ELEMENT_INIT(i)                 \
    do                                         \
    {                                          \
        buffer_list.buffer[(i)].p_data = NULL; \
    } while (0)


//Tabs end

typedef struct
{
  bool    is_not_empty;                   /**< Indicates that the structure is not empty. */
  uint8_t addr[BLE_GAP_ADDR_LEN];         /**< Device address. */
  char    dev_name[DEVICE_NAME_MAX_SIZE]; /**< Device name. */
  int8_t RSSI_value_RK;   
  uint8_t   uuid_buffer_1[UUID128_SIZE];        /**< Buffer for storing an  UUID128. */

  uint16_t uuid_len;
  uint8_t uuid_type;
  
}scanned_device_t;

typedef struct
{
  uint8_t * p_data;   /**< Pointer to data. */
  uint16_t  data_len; /**< Length of data. */
} data_t;

scanned_device_t   m_device[DEVICE_TO_FIND_MAX];                 /**< Stores device info from scan data. */

scanned_device_t * scan_device_info_get(void)
{
  return m_device;
}

void scan_device_info_clear(void)
{
  memset(m_device, 0, sizeof(m_device));
}
static void device_to_list_add(ble_gap_evt_adv_report_t const * p_adv_report);
void scan_start(void);
void int_addr_to_hex_str(char * p_result, uint8_t result_len, uint8_t const * const p_addr);

#define RSSI_THRESHOLD -80
static void adv_list_timer_handle(void * p_context);
static bool               m_scanning = false;                           /**< Variable that informs about the ongoing scanning. True when scan is ON. */
#define FOUND_DEVICE_REFRESH_TIME APP_TIMER_TICKS(SCAN_LIST_REFRESH_INTERVAL) /**< Time after which the device list is clean and refreshed. */

BLE_DB_DISCOVERY_ARRAY_DEF(m_db_disc, NRF_SDH_BLE_CENTRAL_LINK_COUNT);  /**< Database discovery module instances. */
#define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0
#define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1
static void db_discovery_init(void);
static void db_disc_handler(ble_db_discovery_evt_t * p_evt);
//extern ble_nus_t m_nus;
void ble_serv_on_db_disc_evt(ble_db_discovery_evt_t const * p_evt);

//static bool device_uuid_search(ble_gap_evt_adv_report_t const * p_adv_report);
void print_uuid(char * p_result, uint8_t result_len, uint8_t const * const p_uuid, uint8_t size);

typedef struct 
{
  uint32_t addr[BLE_GAP_ADDR_LEN];         /**< Device address. */
  char    dev_name[DEVICE_NAME_MAX_SIZE]; /**< Device name. */
  int8_t RSSI_value_RK;
  uint16_t uuid;
}known_list_t; __ALIGN(4)
#define MAX_DEVICE 8
extern known_list_t k_device[MAX_DEVICE];__ALIGN(4) 

known_list_t temp_device;

//static bool service_flag = false;
extern uint8_t k_count = 0;



#define SCAN_INTERVAL             0x00A0                                     /**< Determines scan interval in units of 0.625 millisecond. */
#define SCAN_WINDOW               0x0050                                     /**< Determines scan window in units of 0.625 millisecond. */
#define SCAN_TIMEOUT              0x0000                                     /**< Timout when scanning. 0x0000 disables timeout. */
#define SCAN_REQUEST              0                                          /**< Active scannin is not set. */
#define SCAN_WHITELIST_ONLY       0                                          /**< We will not ignore unknown devices. */

static const ble_gap_scan_params_t m_scan_param =
{
  .extended = 1,
  .report_incomplete_evts = 1,
  .active = SCAN_REQUEST,
  .filter_policy = SCAN_WHITELIST_ONLY,
  .scan_phys = NULL,
  .interval = (uint16_t)SCAN_INTERVAL,
  .window = (uint16_t)SCAN_WINDOW,
  .timeout = SCAN_TIMEOUT
};
static const ble_gap_conn_params_t m_connection_param =
{
  (uint16_t)MIN_CONN_INTERVAL,
  (uint16_t)MAX_CONN_INTERVAL,
  (uint16_t)SLAVE_LATENCY,
  (uint16_t)CONN_SUP_TIMEOUT
};


//Added custom service 

#define NOTIFICATION_INTERVAL           APP_TIMER_TICKS(1000) 
static void on_cus_evt(ble_cus_t     * p_cus_service, ble_cus_evt_t * p_evt);
BLE_CUS_DEF(m_cus);
APP_TIMER_DEF(m_notification_timer_id);
ble_cus_init_t   cus_init;


static ble_uuid_t const m_scan_uuid[] =  {{BLE_UUID_NUS_SERVICE,0x03},
{BLE_UUID_HEALTH_THERMOMETER_SERVICE,BLE_UUID_TYPE_BLE},
{BLE_UUID_NONIN_SENSOR_SERVICE,BLE_UUID_TYPE_VENDOR_BEGIN}};
static void connect_to_target(ble_gap_evt_adv_report_t const * p_adv_report);
static bool connect = false;
static void conn_params_init(void);
static void conn_params_error_handler(uint32_t nrf_error);
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt);
#endif

NRF_BLE_GATT_DEF(m_gatt);                                                           /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr);                                                             /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */


NRF_CLI_UART_DEF(cli_uart,0 , 256, 16);
NRF_CLI_BLE_UART_DEF(cli_ble_uart, &m_gatt, 64, 32);
NRF_CLI_DEF(m_cli_uart, "uart_cli:~$ ", &cli_uart.transport,'\r', 4);
NRF_CLI_DEF(m_ble_cli, "ble_cli:~$ ", &cli_ble_uart.transport,'\r', 8);

static uint16_t  m_conn_handle = BLE_CONN_HANDLE_INVALID;                           /**< Handle of the current connection. */

task_id_t m_ble_console_task_id;

static ble_uuid_t m_adv_uuids[] =                                                   /**< Universally unique service identifiers. */
{
  {BLE_UUID_NUS_SERVICE,            BLE_UUID_TYPE_BLE},
  {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
  
};

/**@brief Callback function for asserts in the SoftDevice.
*
* @details This function will be called in case of an assert in the SoftDevice.
*
* @warning This handler is an example only and does not fit a final product. You need to analyze
*          how your product is supposed to react in case of Assert.
* @warning On assert from the SoftDevice, the system can only recover on reset.
*
* @param[in] line_num   Line number of the failing ASSERT call.
* @param[in] file_name  File name of the failing ASSERT call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
  app_error_handler(DEAD_BEEF, line_num, p_file_name);
}


/**@brief Clear bond information from persistent storage.
*/
static void delete_bonds(void)
{
  ret_code_t err_code;
  
  NRF_LOG_INFO("Erase bonds!");
  
  err_code = pm_peers_delete();
  APP_ERROR_CHECK(err_code);
}


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


/**@brief Function for handling Peer Manager events.
*
* @param[in] p_evt  Peer Manager event.
*/
static void pm_evt_handler(pm_evt_t const * p_evt)
{
  pm_handler_on_pm_evt(p_evt);
  pm_handler_flash_clean(p_evt);
  
  switch (p_evt->evt_id)
  {
  case PM_EVT_PEERS_DELETE_SUCCEEDED:
    //If device is in scanning mode don't advertise
    advertising_start(false);
    break;
    
  default:
    break;
  }
}

/**@brief Function for the GAP initialization.
*
* @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
*          device including the device name, appearance, and the preferred connection parameters.
*/
static void gap_params_init(void)
{
  ret_code_t              err_code;
  ble_gap_conn_params_t   gap_conn_params;
  ble_gap_conn_sec_mode_t sec_mode;
  
  BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
  
  err_code = sd_ble_gap_device_name_set(&sec_mode,
                                        (const uint8_t *)DEVICE_NAME,
                                        strlen(DEVICE_NAME));
  APP_ERROR_CHECK(err_code);
  
  memset(&gap_conn_params, 0, sizeof(gap_conn_params));
  
  gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
  gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
  gap_conn_params.slave_latency     = SLAVE_LATENCY;
  gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
  
  err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
  NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                p_gatt->att_mtu_desired_central,
                p_gatt->att_mtu_desired_periph);
}


/**@brief Function for initializing the GATT module.
*/
static void gatt_init(void)
{
  ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
  APP_ERROR_CHECK(err_code);
}


/**@brief Function for handling Queued Write Module errors.
*
* @details A pointer to this function will be passed to each service which may need to inform the
*          application about an error.
*
* @param[in]   nrf_error   Error code containing information about what went wrong.
*/
static void nrf_qwr_error_handler(uint32_t nrf_error)
{
  APP_ERROR_HANDLER(nrf_error);
}


/**@brief Function for initializing services that will be used by the application.
*
* @details Initialize the Heart Rate, Battery and Device Information services.
*/
static void services_init(void)
{
  ret_code_t         err_code;
  ble_dis_init_t     dis_init;
  nrf_ble_qwr_init_t qwr_init = {0};
  //   ble_hts_init_t     hts_init;
  // Initialize Queued Write Module.
  qwr_init.error_handler = nrf_qwr_error_handler;
  
  err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
  APP_ERROR_CHECK(err_code);
  
  // Initialize Device Information Service.
  memset(&dis_init, 0, sizeof(dis_init));
  
  ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
  
  dis_init.dis_char_rd_sec = SEC_OPEN;
  
  err_code = ble_dis_init(&dis_init);
  APP_ERROR_CHECK(err_code);
  
  /*  RK code to initialize the nonin services used by the application.*/
  ble_uuid_t            ble_uuid;
  BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_HEALTH_THERMOMETER_SERVICE);
  

  err_code = ble_db_discovery_evt_register(&ble_uuid);
  if (err_code == NRF_SUCCESS)
  {
    APP_ERROR_CHECK(err_code);
  }
  if(err_code == NRF_ERROR_NULL)
  {
    NRF_LOG_INFO("error null pointer supplied\n\r");
  }
  if(err_code == NRF_ERROR_INVALID_STATE)
  {
    NRF_LOG_INFO("error NRF_ERROR_INVALID_STATE\n\r");
  }
  if(err_code == NRF_ERROR_NO_MEM)
  {
    NRF_LOG_INFO("error NRF_ERROR_NO_MEM\n\r");
  }
  
  
  // Add Nonin Oxy sensor Service UUID BASE
  ble_uuid128_t base_uuid = BLE_UUID_NONIN_SENSOR_SERVICE_BASE;
  
  // Initialize CUS Service init structure to zero.
  memset(&cus_init, 0, sizeof(cus_init));
  cus_init.evt_handler = on_cus_evt;
  
  if (&m_cus == NULL || &cus_init == NULL)
  {
    NRF_LOG_INFO("NRF_ERROR_NULL");
  }
  
  

  
  // Initialize service structure
  m_cus.evt_handler               = cus_init.evt_handler;
  m_cus.conn_handle               = BLE_CONN_HANDLE_INVALID;
  
  err_code =  sd_ble_uuid_vs_add(&base_uuid,  &m_cus.uuid_type);
  if (err_code == NRF_ERROR_INVALID_ADDR)
  {
    NRF_LOG_INFO("error = NRF_ERROR_INVALID_ADDR\n\r");
  }
  if (err_code == NRF_ERROR_NO_MEM)
  {
    NRF_LOG_INFO("error = NRF_ERROR_NO_MEM\n\r");
  }
  
  ble_uuid.uuid = BLE_UUID_NONIN_SENSOR_SERVICE;
  ble_uuid.type = m_cus.uuid_type;
  err_code = ble_db_discovery_evt_register(&ble_uuid);
  if (err_code == NRF_SUCCESS)
  {
    APP_ERROR_CHECK(err_code);
  }
  if(err_code == NRF_ERROR_NULL)
  {
    NRF_LOG_INFO("error null pointer supplied\n\r");
  }
  if(err_code == NRF_ERROR_INVALID_STATE)
  {
    NRF_LOG_INFO("error NRF_ERROR_INVALID_STATE\n\r");
  }
  if(err_code == NRF_ERROR_NO_MEM)
  {
    NRF_LOG_INFO("error NRF_ERROR_NO_MEM\n\r");
  }
  
}

/**@brief Function for handling advertising events.
*
* @details This function will be called for advertising events which are passed to the application.
*
* @param[in] ble_adv_evt  Advertising event.
*/
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
  ret_code_t err_code;
  
  switch (ble_adv_evt)
  {
  case BLE_ADV_EVT_FAST:
    //NRF_LOG_RAW_INFO("Fast advertising.\r");
    err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
    APP_ERROR_CHECK(err_code);
    break;
    
  case BLE_ADV_EVT_IDLE:
    nrf_pwr_mgmt_run();
    break;
    
  default:
    break;
  }
}


/**@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;
  
  // For readability
  ble_gap_evt_t const        * p_gap_evt   = &p_ble_evt->evt.gap_evt;

  
  switch (p_ble_evt->header.evt_id)
  {
#ifdef RK_CLI
  case BLE_GAP_EVT_ADV_REPORT:
    {
      
      //bool res = device_uuid_search(&p_gap_evt->params.adv_report);
      
      device_to_list_add(&p_gap_evt->params.adv_report);        
      
    } break;

    break;
#endif
  case BLE_GAP_EVT_CONNECTED:
    {
      NRF_LOG_INFO("Connected.");
      err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
      APP_ERROR_CHECK(err_code);
      m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
      err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
      APP_ERROR_CHECK(err_code);
      
      nrf_cli_ble_uart_config_t config = { .conn_handle = m_conn_handle };
      
      err_code = nrf_cli_init(&m_ble_cli, &config, true, true, NRF_LOG_SEVERITY_INFO);
      APP_ERROR_CHECK(nrf_cli_task_create(&m_ble_cli));
      NRF_LOG_INFO("error code after connection = %d\n", err_code);
      
      APP_ERROR_CHECK(err_code);
      
      
      //  err_code =  sd_ble_gattc_primary_services_discover(conn_handle,0x0001,NULL);
      do 
      {
        err_code = ble_db_discovery_start(&m_db_disc[p_gap_evt->conn_handle],
                                          p_gap_evt->conn_handle);
        if (err_code == NRF_SUCCESS)
        {
          NRF_LOG_INFO("discovery started :busy staus\n");
          //  NRF_LOG_INFO("service uuid found = %d\n\r", m_db_disc[p_gap_evt->conn_handle].srv_count );
          APP_ERROR_CHECK(err_code);
        }
        
      }while(err_code == NRF_ERROR_BUSY);
      
      
      // Update LEDs status and check whether it is needed to look for more
      // peripherals to connect to.
      bsp_board_led_on(CENTRAL_CONNECTED_LED);
      if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
      {
        bsp_board_led_off(CENTRAL_SCANNING_LED);
      }
      else
      {
        // Resume scanning.
        bsp_board_led_on(CENTRAL_SCANNING_LED);
        scan_start();
      }
      
    } break;
    
  case BLE_GAP_EVT_DISCONNECTED:
    {
      connect = false;
      NRF_LOG_INFO("Disconnected, reason %d.",
                   p_ble_evt->evt.gap_evt.params.disconnected.reason);
      m_conn_handle = BLE_CONN_HANDLE_INVALID;
      (void)nrf_cli_uninit(&m_ble_cli);
      
      if (ble_conn_state_central_conn_count() == 0)
      {
        // Turn off the LED that indicates the connection.
        bsp_board_led_off(CENTRAL_CONNECTED_LED);
      }
      
      // Start scanning.
      if (m_scanning)
      {
        scan_start();
      }
      
      // Turn on the LED for indicating scanning.
      bsp_board_led_on(CENTRAL_SCANNING_LED);
    }break;
    
  case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
      NRF_LOG_DEBUG("PHY update request.");
      ble_gap_phys_t const phys =
      {
        .rx_phys = BLE_GAP_PHY_AUTO,
        .tx_phys = BLE_GAP_PHY_AUTO,
      };
      err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
      APP_ERROR_CHECK(err_code);
    } break;
    
  case BLE_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    NRF_LOG_DEBUG("GATT Client Timeout.");
    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                     BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
    break;
    
  case BLE_GATTS_EVT_TIMEOUT:
    // Disconnect on GATT Server timeout event.
    NRF_LOG_DEBUG("GATT Server Timeout.");
    err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                     BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    APP_ERROR_CHECK(err_code);
    break;
    
    
  
  default:
    // No implementation needed.
    break;
  }
}

/**@brief Function for the SoftDevice initialization.
*
* @details This function initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
  ret_code_t err_code;
  
  err_code = nrf_sdh_enable_request();
  APP_ERROR_CHECK(err_code);
  
  // Configure the BLE stack using the default settings.
  // Fetch the start address of the application RAM.
  uint32_t ram_start = 0;
  err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
  APP_ERROR_CHECK(err_code);
  
  // Enable BLE stack.
  err_code = nrf_sdh_ble_enable(&ram_start);
  APP_ERROR_CHECK(err_code);
  
  // Register a handler for BLE events.
  NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}


/**@brief Function for handling events from the BSP module.
*
* @param[in]   event   Event generated by button press.
*/
void bsp_event_handler(bsp_event_t event)
{
  ret_code_t err_code;
  
  switch (event)
  {
  case BSP_EVENT_SLEEP:
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    break;
    
  case BSP_EVENT_DISCONNECT:
    err_code = sd_ble_gap_disconnect(m_conn_handle,
                                     BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_ERROR_INVALID_STATE)
    {
      APP_ERROR_CHECK(err_code);
    }
    break;
    
  case BSP_EVENT_WHITELIST_OFF:
    if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
    {
      err_code = ble_advertising_restart_without_whitelist(&m_advertising);
      if (err_code != NRF_ERROR_INVALID_STATE)
      {
        APP_ERROR_CHECK(err_code);
      }
    }
    break;
    
  default:
    break;
  }
}


/**@brief Function for the Peer Manager initialization.
*/
static void peer_manager_init(void)
{
  ble_gap_sec_params_t sec_param;
  ret_code_t           err_code;
  
  err_code = pm_init();
  APP_ERROR_CHECK(err_code);
  
  memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
  
  // Security parameters to be used for all security procedures.
  sec_param.bond           = SEC_PARAM_BOND;
  sec_param.mitm           = SEC_PARAM_MITM;
  sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
  sec_param.oob            = SEC_PARAM_OOB;
  sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
  sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
  sec_param.kdist_own.enc  = 1;
  sec_param.kdist_own.id   = 1;
  sec_param.kdist_peer.enc = 1;
  sec_param.kdist_peer.id  = 1;
  
  err_code = pm_sec_params_set(&sec_param);
  APP_ERROR_CHECK(err_code);
  
  err_code = pm_register(pm_evt_handler);
  APP_ERROR_CHECK(err_code);
}


/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
  ret_code_t             err_code;
  ble_advertising_init_t init;
  
  memset(&init, 0, sizeof(init));
  
  init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
  init.advdata.include_appearance      = true;
  init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
  init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
  
  init.config.ble_adv_fast_enabled  = true;
  init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
  init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
  
  init.evt_handler = on_adv_evt;
  
  err_code = ble_advertising_init(&m_advertising, &init);
  APP_ERROR_CHECK(err_code);
  
  ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

#ifdef RK_CLI
/**@brief Function for handling an event from the Connection Parameters Module.
*
* @details This function will be called for all events in the Connection Parameters Module
*          which are passed to the application.
*
* @note All this function does is to disconnect. This could have been done by simply setting
*       the disconnect_on_fail config parameter, but instead we use the event handler
*       mechanism to demonstrate its use.
*
* @param[in] p_evt  Event received from the Connection Parameters Module.
*/
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
  uint32_t err_code;
  
  if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
  {
    err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
    APP_ERROR_CHECK(err_code);
  }
}


/**@brief Function for handling errors from the Connection Parameters module.
*
* @param[in] nrf_error  Error code containing information about what went wrong.
*/
static void conn_params_error_handler(uint32_t nrf_error)
{
  APP_ERROR_HANDLER(nrf_error);
}


/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
  uint32_t               err_code;
  ble_conn_params_init_t cp_init;
  
  memset(&cp_init, 0, sizeof(cp_init));
  
  cp_init.p_conn_params                  = NULL;
  cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
  cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
  cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
  cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
  cp_init.disconnect_on_fail             = false;
  cp_init.evt_handler                    = on_conn_params_evt;
  cp_init.error_handler                  = conn_params_error_handler;
  
  err_code = ble_conn_params_init(&cp_init);
  APP_ERROR_CHECK(err_code);
}

static void connect_to_target(ble_gap_evt_adv_report_t const * p_adv_report)
{
  // For readability.
  ble_gap_addr_t const        * p_addr        = &p_adv_report->peer_addr;
  ret_code_t             err_code;
  scan_evt_t scan_evt;
  
  nrf_ble_scan_stop();
  // NRF_LOG_INFO("addr = %x %x %x\n\r",p_addr->addr[0], p_addr->addr[1], p_addr->addr[5] );
  memset(&scan_evt, 0, sizeof(scan_evt));
  
  // Establish connection.
  err_code = sd_ble_gap_connect(p_addr,
                                &m_scan_param,
                                &m_connection_param,
                                APP_BLE_CONN_CFG_TAG);
  
  if (err_code == NRF_SUCCESS)
  {
    connect = true;
  }
  else if(err_code == NRF_ERROR_INVALID_ADDR)
  {
    NRF_LOG_INFO("NRF_ERROR_INVALID_ADDR failed\n\r");
  }
  else if(err_code == NRF_ERROR_INVALID_PARAM)
  {
    NRF_LOG_INFO("NRF_ERROR_INVALID_PARAM failed\n\r");
  }
  else if(err_code == NRF_ERROR_NOT_FOUND)
  {
    NRF_LOG_INFO("NRF_ERROR_NOT_FOUND failed\n\r");
  }
  else if (err_code == NRF_ERROR_INVALID_STATE)
  {
    NRF_LOG_INFO("NRF_ERROR_INVALID_STATE failed\n\r");
  }
  else if (err_code == BLE_ERROR_GAP_INVALID_BLE_ADDR)
  {
    NRF_LOG_INFO("BLE_ERROR_GAP_INVALID_BLE_ADDR failed\n\r");
  }
  else if (err_code == NRF_ERROR_CONN_COUNT)
  {
    //    NRF_LOG_INFO("NRF_ERROR_CONN_COUNT failed\n\r");
  }
  else if (err_code == NRF_ERROR_RESOURCES)
  {
    NRF_LOG_INFO("NRF_ERROR_RESOURCES failed\n\r");
  }
  else if (err_code == NRF_ERROR_NOT_SUPPORTED)
  {
    NRF_LOG_INFO("NRF_ERROR_NOT_SUPPORTED failed\n\r");
  }
  
  scan_evt.scan_evt_id                    = NRF_BLE_SCAN_EVT_CONNECTING_ERROR;
  scan_evt.params.connecting_err.err_code = err_code;
  
  NRF_LOG_DEBUG("Connection status: %d", err_code);
  
  
  nrf_ble_scan_start(&m_scan);    
}



/**@brief Function for handling the Custom Service Service events.
*
* @details This function will be called for all Custom Service events which are passed to
*          the application.
*
* @param[in]   p_cus_service  Custom Service structure.
* @param[in]   p_evt          Event received from the Custom Service.
*
*/
static void on_cus_evt(ble_cus_t     * p_cus_service,
                       ble_cus_evt_t * p_evt)
{
  ret_code_t err_code;
  
  switch(p_evt->evt_type)
  {
  case BLE_CUS_EVT_NOTIFICATION_ENABLED:
    
    err_code = app_timer_start(m_notification_timer_id, NOTIFICATION_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);
    break;
    
  case BLE_CUS_EVT_NOTIFICATION_DISABLED:
    // Stop the application timer that is triggering the notifications
    err_code = app_timer_stop(m_notification_timer_id);
    APP_ERROR_CHECK(err_code);
    break;
    
  case BLE_CUS_EVT_CONNECTED:
    break;
    
  case BLE_CUS_EVT_DISCONNECTED:
    break;
  case BLE_CUS_EVT_SERVO_CTR_VALUE_RECEIVED:
    break;    
    
  default:
    // No implementation needed.
    break;
  }
}

void ble_serv_on_db_disc_evt(ble_db_discovery_evt_t const * p_evt)
{

  ret_code_t err_code;
  
  for (uint8_t i =0; i < sizeof(m_scan_uuid)/sizeof(m_scan_uuid[0]); i++)
  {
    
    //     if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
    //        p_evt->params.discovered_db.srv_uuid.uuid == m_scan_uuid[i].uuid)
    if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
        p_evt->params.discovered_db.srv_uuid.uuid == m_scan_uuid[i].uuid &&
          p_evt->params.discovered_db.srv_uuid.type == m_scan_uuid[i].type)
    {
      NRF_LOG_INFO("Service available:%x \n\r", p_evt->params.discovered_db.srv_uuid.uuid);
      //      service_flag = true;
      
      // move device to known device list - copy MAC ID and UUID 
      if (k_count < DEVICE_TO_FIND_MAX)
      {
        for (uint8_t i = 0; i < k_count; i++)
        {
          if (memcmp(temp_device.addr,k_device[i].addr,sizeof(temp_device.addr)) == 0)
          {
            return;
          }
        }
        memcpy(k_device[k_count].addr, temp_device.addr, sizeof(temp_device.addr));
        memcpy(&k_device[k_count].RSSI_value_RK, &temp_device.RSSI_value_RK,sizeof(temp_device.RSSI_value_RK));
        k_device[k_count].uuid = p_evt->params.discovered_db.srv_uuid.uuid;
        k_count++;
      }
      break;
    }
    
    
  }
  
  if (connect == true)
  {
    err_code = sd_ble_gap_disconnect(m_conn_handle,BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_ERROR_INVALID_STATE)
    {
      APP_ERROR_CHECK(err_code);
    }
    if (err_code == NRF_SUCCESS)
    {
      connect = false;
      NRF_LOG_INFO("Disconnected after discovery\n\r");
    }
  }
}
/**@brief Function for handling database discovery events.
*
* @details This function is a callback function to handle events from the database discovery module.
*          Depending on the UUIDs that are discovered, this function forwards the events
*          to their respective services.
*
* @param[in] p_event  Pointer to the database discovery event.
*/
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{

  
  
  ble_serv_on_db_disc_evt( p_evt);
}


/** @brief Database discovery initialization.
*/
static void db_discovery_init(void)
{
  ret_code_t err_code = ble_db_discovery_init(db_disc_handler);
  APP_ERROR_CHECK(err_code);
}

bool is_scanning(void)
{
  return m_scanning;
}
/**@brief Function for handling the adv_list_timer event, which refreshes the connectable devices.
*/
static void adv_list_timer_handle(void * p_context)
{
  if (is_scanning())
  {
    scan_device_info_clear();
  }
}

#if 0
static bool device_uuid_search(ble_gap_evt_adv_report_t const * p_adv_report)
{
  uint8_t  idx             = 0;
  uint16_t dev_name_offset = 0;
  uint16_t field_len;
  data_t   adv_data;
  int8_t peripheral_rssi = p_adv_report->rssi;
  
  // Initialize advertisement report for parsing
  adv_data.p_data   = (uint8_t *)p_adv_report->data.p_data;
  adv_data.data_len = p_adv_report->data.len;
  
  for ( idx = 0; idx < DEVICE_TO_FIND_MAX; idx++)
  {
    // If address is duplicated(already in the list), then return.
    if (memcmp(p_adv_report->peer_addr.addr,
               m_device[idx].addr,
               sizeof(p_adv_report->peer_addr.addr)) == 0)
    {
      /* store rssi value */
      memcpy(&m_device[idx].RSSI_value_RK, 
             &p_adv_report->rssi, 
             sizeof(p_adv_report->rssi));
      return true;
    }
  }
  
  // Device is not in the list.
  for (idx = 0; idx < DEVICE_TO_FIND_MAX; idx++)
  {
    if (!m_device[idx].is_not_empty && (peripheral_rssi > RSSI_THRESHOLD)) // We find an empty entry in the list
    {
      
      uint16_t        data_offset = 0;
      uint8_t         ad_types[N_AD_TYPES];
      uint8_t       * p_parsed_uuid;
      uint16_t        parsed_uuid_len = adv_data.data_len;
      uint8_t uuid_type;
      uint8_t raw_uuid_len;
      ad_types[0] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE;
      ad_types[1] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE;
      ad_types[2] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE;
      ad_types[3] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE;
      
      
      for (uint8_t i = 0; (i < N_AD_TYPES) && (data_offset == 0); i++)
      {
        parsed_uuid_len = ble_advdata_search(adv_data.p_data, adv_data.data_len, &data_offset, ad_types[i]);
        
        if (data_offset != 0)
        {
          uuid_type = ad_types[i];
        }
      }
      
      
      if (data_offset == 0)
      {
        

        
        return false;
      }
      
      
      
      p_parsed_uuid = &adv_data.p_data[data_offset]; //The UUID we found
      //  if (parsed_uuid_len != 0)
      //            // Verify if any UUID matches the given UUID.
      if (uuid_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE || uuid_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE)
      {
        raw_uuid_len = UUID128_SIZE;
        
      }
      else if(uuid_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE || uuid_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE)
      {
        raw_uuid_len = UUID16_SIZE;
        
      }
      //   for (uint16_t list_offset = 0; list_offset < parsed_uuid_len; lisraw_uuid_lent_offset += raw_uuid_len)
      //   {
      
      if (raw_uuid_len == UUID128_SIZE)
      {
        
        for (uint8_t ele = 0; ele < sizeof(m_uuid128); ele++)
        {               
          if ( memcmp(p_parsed_uuid,  &m_uuid128->uuid128[ele], raw_uuid_len) == 0)
          {
            NRF_LOG_INFO("matched uuid128 %x\r\n", m_uuid128->uuid128[ele]);
          }
        }
      }
      else
      {
        for (uint8_t ele = 0; ele < sizeof(m_uuid16); ele++)
        {
          //                  for (uint8_t id = 0; id <parsed_uuid_len; id =+ raw_uuid_len)
          //                  {
          // NRF_LOG_INFO("uuid addr %x\r\n", &p_parsed_uuid[ele]);
          if ( memcmp(&p_parsed_uuid[id],  &m_uuid16[ele], raw_uuid_len) == 0)
          {
            NRF_LOG_INFO("matched uuid16 %x\r\n", m_uuid16[ele].uuid);
          }
          //                  }
        }
      }
      //   }
      m_device[idx].is_not_empty = true; //Validating the list record
      
      
      //Copy the UUID to our list of devices
      memset(m_device[idx].uuid_buffer_1,0,UUID128_SIZE);
      memcpy(m_device[idx].uuid_buffer_1, p_parsed_uuid, parsed_uuid_len);
      // NRF_LOG_INFO("uuid - %x uuid_buff = %x \n", p_parsed_uuid[0], m_device[idx].uuid_buffer_1[0]);
      memcpy(&m_device[idx].uuid_len, &parsed_uuid_len, sizeof(parsed_uuid_len));
      memcpy(&m_device[idx].uuid_type, &uuid_type, sizeof(uuid_type));
      
      memcpy(m_device[idx].addr,
             p_adv_report->peer_addr.addr,
             sizeof(p_adv_report->peer_addr.addr));
      /* store rssi value */
      memcpy(&m_device[idx].RSSI_value_RK, 
             &p_adv_report->rssi, 
             sizeof(p_adv_report->rssi));
      
      // Search for advertising names.
      field_len = ble_advdata_search(adv_data.p_data,
                                     adv_data.data_len,
                                     &dev_name_offset,
                                     BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
      
      if (field_len == 0)
      {
        field_len = ble_advdata_search(adv_data.p_data,
                                       adv_data.data_len,
                                       &dev_name_offset,
                                       BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME);
        // If name is not found, then return.
        if (field_len == 0) 
        {
          return true;
        }
      }
      
      memcpy(m_device[idx].dev_name, &adv_data.p_data[dev_name_offset], field_len);         
      m_device[idx].dev_name[field_len] = 0;
      
      
      
      return true;   
    }
    
    
  } 
  return true;
}
#endif


/**@brief Function for searching for a device name and adding it to a dynamic command.
*
* @details Use this function to parse the received advertising data and to find a given
* name in them either as 'complete_local_name' or as 'short_local_name'.
*
* @param[in]   p_adv_report   Advertising data to parse.
*/
static void device_to_list_add(ble_gap_evt_adv_report_t const * p_adv_report)
{
  uint8_t  idx             = 0;
  uint16_t dev_name_offset = 0;
  uint16_t field_len;
  data_t   adv_data;
  int8_t peripheral_rssi = p_adv_report->rssi;
  // Initialize advertisement report for parsing
  adv_data.p_data   = (uint8_t *)p_adv_report->data.p_data;
  adv_data.data_len = p_adv_report->data.len;
  
  
  for ( idx = 0; idx < DEVICE_TO_FIND_MAX; idx++)
  {
    // If address is duplicated, then return.
    if (memcmp(p_adv_report->peer_addr.addr,
               m_device[idx].addr,
               sizeof(p_adv_report->peer_addr.addr)) == 0)
    {
      /* update rssi value */
      memcpy(&m_device[idx].RSSI_value_RK, 
             &p_adv_report->rssi, 
             sizeof(p_adv_report->rssi));
      return;
    }
  }
  
  // Add device data if an empty record is found.
  for (idx = 0; idx < DEVICE_TO_FIND_MAX; idx++)
  {
    if (!m_device[idx].is_not_empty)
    {
      if (peripheral_rssi > RSSI_THRESHOLD)
      {
        /* store peer address */
        memcpy(m_device[idx].addr,
               p_adv_report->peer_addr.addr,
               sizeof(p_adv_report->peer_addr.addr));
        
        /* store rssi value */
        memcpy(&m_device[idx].RSSI_value_RK, 
               &p_adv_report->rssi, 
               sizeof(p_adv_report->rssi));
        
        m_device[idx].is_not_empty = true;
        
        //connect to target
        
        //            if (p_adv_report->type.connectable && p_adv_report->peer_addr.addr[0] == 0xAB  )
        if (p_adv_report->type.connectable && connect == false )
        {
          connect_to_target(p_adv_report);
          
          //              /* store peer address */
          memcpy(m_device[idx].addr,
                 p_adv_report->peer_addr.addr,
                 sizeof(p_adv_report->peer_addr.addr));
          
          /* Copy MAC ID and RSSI to known device list */
          memcpy(temp_device.addr,
                 p_adv_report->peer_addr.addr,
                 sizeof(p_adv_report->peer_addr.addr));
          
          memcpy(&temp_device.RSSI_value_RK,
                 &p_adv_report->rssi,
                 sizeof(p_adv_report->rssi));
          
        }
        // Search for advertising names.
        field_len = ble_advdata_search(adv_data.p_data,
                                       adv_data.data_len,
                                       &dev_name_offset,
                                       BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
        
        if (field_len == 0)
        {
          field_len = ble_advdata_search(adv_data.p_data,
                                         adv_data.data_len,
                                         &dev_name_offset,
                                         BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME);
          // If name is not found, then return.
          if (field_len == 0) 
          {
            return;
          }
        }
        
        memcpy(m_device[idx].dev_name, &adv_data.p_data[dev_name_offset], field_len);         
        m_device[idx].dev_name[field_len] = 0;
        
      }
      return;
      
    }
    
  }
}


/**@brief Function for handling Scanning Module events.
*/
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
  ret_code_t err_code;
  
  switch(p_scan_evt->scan_evt_id)
  {
  case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
    {
      err_code = p_scan_evt->params.connecting_err.err_code;
      APP_ERROR_CHECK(err_code);
    } break;
    
  case NRF_BLE_SCAN_EVT_CONNECTED:
    {
      ble_gap_evt_connected_t const * p_connected =
        p_scan_evt->params.connected.p_connected;
      // Scan is automatically stopped by the connection.
      NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x",
                   p_connected->peer_addr.addr[0],
                   p_connected->peer_addr.addr[1],
                   p_connected->peer_addr.addr[2],
                   p_connected->peer_addr.addr[3],
                   p_connected->peer_addr.addr[4],
                   p_connected->peer_addr.addr[5]
                     );
    } break;
    
  case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
    {
      NRF_LOG_INFO("Scan timed out.");
      scan_start();
      ret_code_t ret;
      
      ret = nrf_ble_scan_start(&m_scan);
      APP_ERROR_CHECK(ret);
      
      ret = bsp_indication_set(BSP_INDICATE_SCANNING);
      APP_ERROR_CHECK(ret);
    } break;
    
    
    
  default:
    break;
  }
}
/**@brief Function for initializing the scanning and setting the filters.
*/
static void scan_init(void)
{
  
  ret_code_t          err_code;
  nrf_ble_scan_init_t init_scan;
  
  memset(&init_scan, 0, sizeof(init_scan));
  
  
  //init_scan.connect_if_match = true;
  init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
  
  err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
  APP_ERROR_CHECK(err_code);
  
}
#endif

/** @brief Function for initializing BLE components.
*/
void ble_init(void)
{
  ble_stack_init();
  gap_params_init();
  gatt_init();
  db_discovery_init();
  services_init();
  advertising_init();
  
  
  peer_manager_init();
  
#ifdef RK_CLI
  
  scan_init();
#endif
}


/**@brief Function for initializing buttons and leds.
*
* @param[out] p_erase_bonds  Will be true if the clear bonding button was pressed to wake the application up.
*/
static void buttons_leds_init(bool * p_erase_bonds)
{
  ret_code_t err_code;
  bsp_event_t startup_event;
  
  err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
  APP_ERROR_CHECK(err_code);
  
  err_code = bsp_btn_ble_init(NULL, &startup_event);
  APP_ERROR_CHECK(err_code);
  
  *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA);
}

/**
* @brief Function for shutdown events.
*
* @param[in]   event       Shutdown type.
*/
static bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
  ret_code_t err_code;
  
  err_code = bsp_indication_set(BSP_INDICATE_IDLE);
  APP_ERROR_CHECK(err_code);
  
  switch (event)
  {
  case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
    // Prepare wakeup buttons.
    err_code = bsp_btn_ble_sleep_mode_prepare();
    APP_ERROR_CHECK(err_code);
    break;
  default:
    break;
  }
  
  return true;
}

NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);

#ifdef RK_CLI
void scan_start(void)
{
  ret_code_t ret;
  ret = nrf_ble_scan_start(&m_scan);
  APP_ERROR_CHECK(ret);
  
  ret = bsp_indication_set(BSP_INDICATE_SCANNING);
  APP_ERROR_CHECK(ret);
  
  m_scanning = true;
}

void scan_stop(void)
{
  ret_code_t ret;
  
  nrf_ble_scan_stop();
  
  ret = bsp_indication_set(BSP_INDICATE_SCANNING);
  APP_ERROR_CHECK(ret);
  
  m_scanning = false;
}

void int_addr_to_hex_str(char * p_result, uint8_t result_len, uint8_t const * const p_addr)
{
  ASSERT(p_result);
  ASSERT(p_addr);
  
  if (result_len > BLE_GAP_ADDR_LEN)
  {
    return;
  }
  
  // char buffer[BLE_GAP_ADDR_LEN] = {0};
  char tempbuffer = '\0';
  
  memset(p_result, 0, result_len);
  
  for (uint8_t i = 0; i < result_len; ++i)
  {
    sprintf(&tempbuffer, "%.2X", p_addr[result_len - (i+1)]);
    strcat(p_result, &tempbuffer);
    
    if (i < (result_len - 1))
    {
      strcat(p_result, ":");
    }
  }
}

void print_uuid(char * p_result, uint8_t result_len, uint8_t const * const p_uuid, uint8_t size)
{
  ASSERT(p_result);
  ASSERT(p_uuid);
  
  if (result_len > 100)
  {
    return;
  }			 
  //Printing UUID in "8-4-4-4-12" format
  char buffer[100] = {0};
  
  memset(p_result, 0, result_len);
  memset(buffer, 0, 100);
  
  for (uint8_t j = size; j >= 1; --j)
  {
    sprintf(buffer, "%.2X", p_uuid[j-1]);
    
    strcat(p_result, buffer);
    if ( size < UUID128_SIZE && (j == 3 || j == 5 || j == 7))
    {
      strcat(p_result, ",");
    }
    
    if (j ==13 || j ==11 || j==9 || j==7)
    {
      strcat(p_result, "-");
    }
  }
  
}

/* Below funciton displays the scanned device list */
void device_list(nrf_cli_t const *p_cli, scanned_device_t * p_device )
{
  for (uint8_t i = 0; i < DEVICE_TO_FIND_MAX; i++)
  {
    if (p_device[i].is_not_empty)
    {
      nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Device ");
      
      char buffer[ADDR_STRING_LEN];
      int_addr_to_hex_str(buffer, BLE_GAP_ADDR_LEN, p_device[i].addr);
      char ubuffer[100]={0};
      print_uuid(ubuffer, 100, p_device[i].uuid_buffer_1, p_device[i].uuid_len);
      
      nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s %s %ddB\r\n", buffer,  p_device[i].dev_name, p_device[i].RSSI_value_RK);
      

      
    }
    
  }
  nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Known Device List:\n\r");
  //print known device list
  for (uint8_t i = 0; i < k_count; i++)
  {
    nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "K Device ");
    
    char buffer[ADDR_STRING_LEN];
    int_addr_to_hex_str(buffer, BLE_GAP_ADDR_LEN, (uint8_t *)k_device[i].addr);
    
    
    nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s %ddB uuid = %x\r\n", buffer, k_device[i].RSSI_value_RK, k_device[i].uuid);
  }
  
}

static void scan_on_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
{
  scan_start(); 
  nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Scanning...\r\n");
}

static void scan_off_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
{
  
  scan_stop();
  nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Scan stopped.\r\n");
}

static void display_device_list_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
{
  if (argc >= 2)
  {
    if (nrf_cli_help_requested(p_cli))
    {
      nrf_cli_help_print(p_cli, NULL, 0);
      return;
    }
    else
    {
      nrf_cli_fprintf(p_cli,
                      NRF_CLI_ERROR,
                      "%s:%s%s\r\n",
                      argv[0],
                      " bad parameter ",
                      argv[1]);
      return;
    }
  }
  /* Print connectable devices from scan data.*/
  scanned_device_t * p_device_list = scan_device_info_get();
  device_list(p_cli, p_device_list);
}
static void default_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
{
  if (argc >= 2)
  {
    if (nrf_cli_help_requested(p_cli))
    {
      nrf_cli_help_print(p_cli, NULL, 0);
      return;
    }
    else
    {
      nrf_cli_fprintf(p_cli,
                      NRF_CLI_ERROR,
                      "%s:%s%s\r\n",
                      argv[0],
                      " bad parameter ",
                      argv[1]);
      return;
    }
  }
}

// Register "mpu" command and it's subcommands in CLI.
NRF_CLI_CREATE_STATIC_SUBCMD_SET(scan_commands)
{
  NRF_CLI_CMD(on, NULL, "Scan on.", scan_on_cmd),
  NRF_CLI_CMD(off, NULL, "Scan off.", scan_off_cmd),
  NRF_CLI_SUBCMD_SET_END
};


NRF_CLI_CMD_REGISTER(scan, &scan_commands, "Commands for scan control", default_cmd);
NRF_CLI_CMD_REGISTER(devices, NULL, "print device list", display_device_list_cmd);


#endif

void idle_task(void * p_context)
{
  
  bool erase_bonds = (bool)p_context;
  
  advertising_start(erase_bonds);
  
  
  // Enter main loop.
  for (;;)
  {
    if (NRF_LOG_PROCESS() == false)
    {
      nrf_pwr_mgmt_run();
    }
    task_yield();
  }
  
}

static void core_init(void)
{
  APP_ERROR_CHECK(NRF_LOG_INIT(app_timer_cnt_get));
  
  nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
  uart_config.pseltxd = TX_PIN_NUMBER;
  uart_config.pselrxd = RX_PIN_NUMBER;
  uart_config.hwfc    = NRF_UART_HWFC_DISABLED;
  APP_ERROR_CHECK(nrf_cli_init(&m_cli_uart, &uart_config, true, true, NRF_LOG_SEVERITY_INFO));
  //APP_ERROR_CHECK(nrf_cli_start(&m_cli_uart));
  
  
  APP_ERROR_CHECK(nrf_drv_clock_init());
  
  nrf_drv_clock_lfclk_request(NULL);
  
  APP_ERROR_CHECK(app_timer_init());
  // Timer for refreshing scanned devices data.
  APP_TIMER_DEF(adv_list_timer);
  APP_ERROR_CHECK(app_timer_create(&adv_list_timer, APP_TIMER_MODE_REPEATED, adv_list_timer_handle));
  APP_ERROR_CHECK(app_timer_start(adv_list_timer, FOUND_DEVICE_REFRESH_TIME, NULL));
  
  
  APP_ERROR_CHECK(nrf_pwr_mgmt_init());
  
  APP_ERROR_CHECK(nrf_cli_task_create(&m_cli_uart));
}

ret_code_t fds_test_init (void)
{
  
  ret_code_t ret = fds_register(my_fds_evt_handler);
  if (ret != FDS_SUCCESS)
  {
    return ret;
    
  }
  ret = fds_init();
  if (ret != FDS_SUCCESS)
  {
    return ret;
  }
  
  return NRF_SUCCESS;
  
}





/**@brief Function for application main entry.
*/
int main(void)

{
  
  bool erase_bonds;
  
  core_init();

     
  buttons_leds_init(&erase_bonds);
  
  ble_init();
  conn_params_init();
  
  fds_test_init();
  
  APP_ERROR_CHECK(nrf_cli_ble_uart_service_init());
  
  NRF_LOG_RAW_INFO("BLE Nordic Uart Service started\r\n");
  NRF_LOG_RAW_INFO("Press Tab to view all available commands.\r\n");
  task_manager_start(idle_task, (void *)erase_bonds);
  
  while (true)
  {
    UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
    nrf_cli_process(&m_cli_uart);
  }
  
}

Hi 

Am trying to establish nrf52 DK as peripheral with nRF connect application as central but am unable to establish connection between both.

Please debug the following code and help me out as am new to this device.

Related