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

BLE_GAP_EVT_CONNECTED event is not triggered

Hi all,

I have checked in Nordic Devzone for this query but no luck in finding solution for my query.

I am using nrf52832 and configured as central and peripheral.

my device will scan and store peer address in flash and then connect to stored address later.

when i connect to peer address using sd_ble_gap_connect it returns NRF_SUUCESS but BLE_GAP_EVT_CONNECTED  is not triggered.

this issue occurs only for some peripherals and some peripheral i can able to connect and it triggers event as well.

tested with one of the example code: when i try to connect  peripheral  device programmed with ble_app_uart code this issue occurs where  BLE_GAP_EVT_CONNECTED  is not triggered.

but the same peripheral connects successfully through my Android phone.

i am unable understand what is the issue.

Please guide...

Thanks

Rekha

  • Hi i changed scan parameter timeout = 0x01 instead of 0. now i am getting ble gap event timeout error in BLE_GAP_EVT_TIMEOUT event.

    How to solve

    Thanks

  • Hi attched files.

    in flash_write.c - void connect_to_devices(nrf_cli_t const *p_cli) is function where i am trying to connect peripheral device.

    Events are handled by ble_evt_hanlder in main.c

    #include "sdk_common.h"
    #include "flash_write.h"
    #include "ble.h"
    #include <stdio.h>
    #include <string.h>
    
    #define ADDR_STRING_LEN         (2 * (BLE_GAP_ADDR_LEN)+6)
    static volatile uint8_t write_flag=0;
    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 ;
    #define MAX_DEVICE 8
    known_list_t k_device[MAX_DEVICE];
    
    typedef struct 
    {
      uint8_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;
    }flash_list_t ;
    
    flash_list_t N_device[MAX_DEVICE];
    
    extern uint8_t k_count;
    void int_addr_to_hex_str(char * p_result, uint8_t result_len, uint8_t const * const p_addr);
    char id_buffer[ADDR_STRING_LEN];
    #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              0x01                                     /**< 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. */
    #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(900, 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 APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */
    
    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
    };
    
    
    
    void my_fds_evt_handler(fds_evt_t const * const p_fds_evt)
    {
      switch (p_fds_evt->id)
      {
      case FDS_EVT_INIT:
        if (p_fds_evt->result != FDS_SUCCESS)
        {
          // Initialization failed.
        }
        break;
      case FDS_EVT_WRITE:
        if (p_fds_evt->result == FDS_SUCCESS)
        {
          write_flag=1;
        }
        break;
      default:
        break;
      }
    }
    ret_code_t fds_test_write(nrf_cli_t const *p_cli)
    {		
      #define FILE_ID     0x1111		
      #define REC_KEY     0x2222
      //static uint16_t const m_deadbeef[2] = {0x9D,0xBA};
      fds_record_t        record;
      fds_record_desc_t   record_desc;
      fds_flash_record_t  flash_record;
      fds_find_token_t    ftok ={0};//Important, make sure you zero init the ftok token
      uint8_t *data;
      uint32_t err_code;
      uint8_t data_len =0;
      uint8_t id = 0;
      flash_list_t temp_device[MAX_DEVICE];
      // Set up record.
      record.file_id           = FILE_ID;
      record.key               = REC_KEY;        
      //read previously stored data
      while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)               
      {
        err_code = fds_record_open(&record_desc, &flash_record);
        if ( err_code != FDS_SUCCESS)		
        {
          NRF_LOG_INFO("record open failed\n\r");
          return err_code;				
        }
        data =  (uint8_t *)flash_record.p_data;                            
        for (uint8_t i = 0;i< BLE_GAP_ADDR_LEN ;i++)                
        {
          memcpy(&temp_device[id].addr[i], &data[data_len+i], sizeof(data[i]));              
        }          
        id++;
        err_code = fds_record_close(&record_desc);
        if (err_code != FDS_SUCCESS)              
        {
          NRF_LOG_INFO("record close failed\n\r");
          return err_code;	        
        }                      
      }  
      uint8_t loop =  --id;
                
      for (uint8_t j = 0; j < k_count; j++)             
      {
        //Compare address if the address already exists in the flash record discard flash write
        bool id_found = false;
        if (!id_found)            
        {
          for (uint8_t l = 0; l <= loop; l++)           
          {
            if ( memcmp(temp_device[l].addr, k_device[j].addr, sizeof(temp_device[l].addr)) == 0)               
            {
              id_found = true;    
              break; //break inner loop
            }
                          
          }             
        }
        if (!id_found)            
        {
          record.data.p_data       = k_device[j].addr; 
          record.data.length_words = 2;
          ret_code_t ret = fds_record_write(&record_desc, &record);
          //if (ret != FDS_SUCCESS)
          if (ret == FDS_ERR_UNALIGNED_ADDR)             
          {
            NRF_LOG_INFO("writing to flash unsuccessful. \r\n"); 
            return ret;               
          }            
        }           
      }
      NRF_LOG_DEBUG("Writing Record ID = %d \r\n",record_desc.record_id);        
      return NRF_SUCCESS;
                   
    }
    
    ret_code_t fds_read(nrf_cli_t const *p_cli)
    {
      #define FILE_ID     0x1111
      #define REC_KEY     0x2222
      fds_flash_record_t  flash_record;
      fds_record_desc_t   record_desc;
      fds_find_token_t    ftok ={0};//Important, make sure you zero init the ftok token
      uint8_t *data;
      uint32_t err_code;
      
      uint8_t data_len =0;
      uint8_t id = 0;
      
      NRF_LOG_DEBUG("Start searching... \r\n");
      // Loop until all records with the given key and file ID have been found.
      while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)
      {
        err_code = fds_record_open(&record_desc, &flash_record);
        if ( err_code != FDS_SUCCESS)
        {
          return err_code;		
        }
        
        NRF_LOG_DEBUG("Found Record ID = %d\r\n",record_desc.record_id);
        
        data =  (uint8_t *)flash_record.p_data;                            
        for (uint8_t i = 0;i< BLE_GAP_ADDR_LEN ;i++)
        {
          memcpy(&N_device[id].addr[i], &data[data_len+i], sizeof(data[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, N_device[id].addr);
        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s\r\n", buffer);
        id++;
        
        // Access the record through the flash_record structure.
        // Close the record when done.
        err_code = fds_record_close(&record_desc);
        if (err_code != FDS_SUCCESS)
        {
          return err_code;	
        }
        
      }
      
      return NRF_SUCCESS;
    		
    }
    
    ret_code_t fds_test_find_and_delete(nrf_cli_t const *p_cli)
    {
                 
      #define FILE_ID     0x1111
      #define REC_KEY     0x2222
      fds_record_desc_t   record_desc;
      fds_find_token_t    ftok;
      ftok.page=0;
      ftok.p_addr=NULL;
      // Loop and find records with same ID and rec key and mark them as deleted. 
      while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)		
      {
        fds_record_delete(&record_desc);
        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL,"Deleted record ID: %d \r\n",record_desc.record_id);
      }
                    
      // call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration
      ret_code_t ret = fds_gc();
      if (ret != FDS_SUCCESS)		
      {
        return ret;		
      }		
      return NRF_SUCCESS;
    }
    
    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;
    		
    }
    
    void connect_to_devices(nrf_cli_t const *p_cli)
    {
     
      
        #define FILE_ID     0x1111
        #define REC_KEY     0x2222
        fds_flash_record_t  flash_record;
        fds_record_desc_t   record_desc;
        fds_find_token_t    ftok ={0};//Important, make sure you zero init the ftok token
        uint8_t *data;
        uint32_t err_code;
        uint8_t data_len =0;      
              
        ble_gap_addr_t paddr;          
     
        uint8_t id = 0;
        flash_list_t temp_device[MAX_DEVICE]; 
        
        while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)               
        {
        err_code = fds_record_open(&record_desc, &flash_record);
        if ( err_code != FDS_SUCCESS)		
        {
          NRF_LOG_INFO("record open failed\n\r");
          return ;				
        }
        data =  (uint8_t *)flash_record.p_data;                            
        for (uint8_t i = 0;i< BLE_GAP_ADDR_LEN ;i++)                
        {
          memcpy(&temp_device[id].addr[i], &data[data_len+i], sizeof(data[i]));              
        }          
        id++;
        err_code = fds_record_close(&record_desc);
        if (err_code != FDS_SUCCESS)              
        {
          NRF_LOG_INFO("record close failed\n\r");
          return;	        
        }                      
      }  
      uint8_t loop =  --id; 
    nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "loop = %d\n\r", loop);
                    
          for (uint8_t l = 0; l <= loop; l++)           
          {
        
            memset(&paddr, 0, sizeof(paddr));
            for (uint8_t i = 0;i< BLE_GAP_ADDR_LEN ;i++)               
            {
              paddr.addr[i] = temp_device[l].addr[i];                
            } 
           
            nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "connecting address - %2x:%2x:%2x:%2x:%2x:%2x\r\n", 
                            paddr.addr[5], paddr.addr[4], paddr.addr[3], paddr.addr[2], paddr.addr[1], paddr.addr[0] );
              
            ret_code_t err_code;
            // Establish connection.
            err_code = sd_ble_gap_connect(&paddr,
                                      &m_scan_param,
                                      &m_connection_param,
                                      APP_BLE_CONN_CFG_TAG);
          
            if(err_code == NRF_SUCCESS)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_SUCCESS\n\r");
    //          return;
            }
            else if(err_code == NRF_ERROR_INVALID_ADDR)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_ADDR failed\n\r");
            }
            else if(err_code == NRF_ERROR_INVALID_PARAM)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_PARAM failed\n\r");
            }
            else if(err_code == NRF_ERROR_NOT_FOUND)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_NOT_FOUND failed\n\r");
            }
            else if (err_code == NRF_ERROR_INVALID_STATE)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_STATE failed\n\r");
            }
            else if (err_code == BLE_ERROR_GAP_INVALID_BLE_ADDR)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "BLE_ERROR_GAP_INVALID_BLE_ADDR failed\n\r");
            }
            else if (err_code == NRF_ERROR_CONN_COUNT)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_CONN_COUNT failed\n\r");
            }
            else if (err_code == NRF_ERROR_RESOURCES)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_RESOURCES failed\n\r");
            }
            else if (err_code == NRF_ERROR_NOT_SUPPORTED)
            {
              nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_NOT_SUPPORTED failed\n\r");
            }   
          
          }       
                      
                   
        
    //    
    //    
    //    
    //    while (fds_record_find(FILE_ID, REC_KEY, &record_desc, &ftok) == FDS_SUCCESS)     
    //    {
    //      memset(&paddr, 0, sizeof(paddr));
    //      err_code = fds_record_open(&record_desc, &flash_record);
    //      if ( err_code != FDS_SUCCESS)		
    //      {                   
    //        NRF_LOG_INFO("record open failed\n\r");
    //        return ;		
    //      }                  
    //       
    //      data =  (uint8_t *)flash_record.p_data;                                                      
    //      for (uint8_t i = 0;i< BLE_GAP_ADDR_LEN ;i++)               
    //      {
    //        paddr.addr[i] = data[data_len+i];                
    //      }             
    //               
    //      nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "connecting address - %2x:%2x:%2x:%2x:%2x:%2x\r\n", paddr.addr[5], paddr.addr[4], paddr.addr[3], paddr.addr[2], paddr.addr[1], paddr.addr[0] );
    //                     
    //      // Establish connection.
    //      err_code = sd_ble_gap_connect(&paddr,
    //                                  &m_scan_param,
    //                                  &m_connection_param,
    //                                  APP_BLE_CONN_CFG_TAG);
    //      
    //   
    //      if(err_code == NRF_SUCCESS)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_SUCCESS\n\r");
    //
    //        err_code = fds_record_close(&record_desc);
    //        if (err_code != FDS_SUCCESS)              
    //        {
    //          nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "record close failed\n\r");         
    //          return;	                 
    //        }      
    //        return;
    //      }
    //      else if(err_code == NRF_ERROR_INVALID_ADDR)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_ADDR failed\n\r");
    //      }
    //      else if(err_code == NRF_ERROR_INVALID_PARAM)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_PARAM failed\n\r");
    //      }
    //      else if(err_code == NRF_ERROR_NOT_FOUND)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_NOT_FOUND failed\n\r");
    //      }
    //      else if (err_code == NRF_ERROR_INVALID_STATE)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_INVALID_STATE failed\n\r");
    //      }
    //      else if (err_code == BLE_ERROR_GAP_INVALID_BLE_ADDR)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "BLE_ERROR_GAP_INVALID_BLE_ADDR failed\n\r");
    //      }
    //      else if (err_code == NRF_ERROR_CONN_COUNT)
    //      {
    //        //    nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_CONN_COUNT failed\n\r");
    //      }
    //      else if (err_code == NRF_ERROR_RESOURCES)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_RESOURCES failed\n\r");
    //      }
    //      else if (err_code == NRF_ERROR_NOT_SUPPORTED)
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "NRF_ERROR_NOT_SUPPORTED failed\n\r");
    //      }   
    //       
    //      err_code = fds_record_close(&record_desc);
    //      if (err_code != FDS_SUCCESS)              
    //      {
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "record close failed\n\r");         
    //        return;	                 
    //      }    
    //         
    //       
    //    } //end while loop
    }
    
    //connect to devices (Normal mode is on)
    static void connect_device_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;
            }
        }
    //  normal_mode_on = true;
      nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Connect to devices...\r\n");
      connect_to_devices(p_cli);
      
    }
    
    
    void flashwrite_erase_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
    {
        fds_test_find_and_delete(p_cli);
        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Erase flash...\r\n");
    }
    
    void flashwrite_read_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
    {
        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\r\nknown devices \r\n");
        fds_read(p_cli);
        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Read from flash...\r\n");
    }
    
    void flashwrite_write_cmd(nrf_cli_t const *p_cli, size_t argc, char **argv)
    {
       fds_test_write(p_cli);
       nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Writing to flash...\r\n");
    }
    
    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;
            }
        }
    }
    
    NRF_CLI_CREATE_STATIC_SUBCMD_SET(flash_commands)
    {
         NRF_CLI_CMD(erase, NULL, "Erase flash", flashwrite_erase_cmd),
         NRF_CLI_CMD(read, NULL, "Read from flash", flashwrite_read_cmd),
         NRF_CLI_CMD(write, NULL, "Write to flash", flashwrite_write_cmd),
         
         NRF_CLI_SUBCMD_SET_END
    };
    
    NRF_CLI_CMD_REGISTER(flash, &flash_commands, "Access Flash", default_cmd);
    NRF_CLI_CMD_REGISTER(connect, NULL, "Connect to peripheral", connect_device_cmd);
    /** 
    * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    *    list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    *    Semiconductor ASA integrated circuit in a product or a software update for
    *    such product, must reproduce the above copyright notice, this list of
    *    conditions and the following disclaimer in the documentation and/or other
    *    materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    *    contributors may be used to endorse or promote products derived from this
    *    software without specific prior written permission.
    *
    * 4. This software, with or without modification, must only be used with a
    *    Nordic Semiconductor ASA integrated circuit.
    *
    * 5. Any software provided in binary form under this license must not be reverse
    *    engineered, decompiled, modified and/or disassembled.
    *
    * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
    * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
    * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    /** @example examples/ble_peripheral/ble_app_hrs/main.c
    *
    * @brief Heart Rate Service Sample Application main file.
    *
    * This file contains the source code for a sample application using the Heart Rate service
    * (and also Battery and Device Information services). This application uses the
    * @ref srvlib_conn_params module.
    */
    
    #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 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
    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 -70
    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);
    void ble_serv_on_db_disc_evt(ble_db_discovery_evt_t const * p_evt);
    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;
    #define MAX_DEVICE 8
    extern known_list_t k_device[MAX_DEVICE];
    
    known_list_t temp_device;
    
    extern uint8_t k_count = 0;
    
    /* Thermometer UUID = 0x1809 
      NUS UUID = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E};{0x6E400001B5A3F393E0A9E50E24DCCA9E} 
      NONIN UUID = {0x1B, 0xC5, 0xD5, 0xA5, 0x02, 0x00, 0x5E, 0x8B, 0xE2, 0x11, 0x5F, 0x0D, 0x00, 0x00, 0xA9, 0x46}
      static ble_uuid_t m_uuid16[] = {{0x1809,BLE_UUID_TYPE_BLE }, {0xFEE0, BLE_UUID_TYPE_BLE}, {0x180A, BLE_UUID_TYPE_BLE}}; */
    
    #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;
    
    /* array of UUID to be filtered */
    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);
    
    bool normal_mode_on = true;
    
    
    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:
        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};
     
      // 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)
      {
      case BLE_GAP_EVT_ADV_REPORT:
        { 
          device_to_list_add(&p_gap_evt->params.adv_report);         
        } break;
        
      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);
          if (normal_mode_on == false)
          {
            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 status\n");
                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_INFO("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_INFO("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;
        
      case BLE_GAP_EVT_TIMEOUT:
        NRF_LOG_INFO("Timeout error\n\r");
        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);
    }
    
    /**@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();
      
      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)
    {
      // Check if the Led Button Service was discovered.
      
      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 &&
              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);
         
          // 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();
      }
    }
    
    /**@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
            bool d_found = false;
            if (p_adv_report->type.connectable && connect == false )
            {
              for (idx = 0; idx <= k_count; idx++)
              {
                if (memcmp(p_adv_report->peer_addr.addr,k_device[idx].addr, sizeof(p_adv_report->peer_addr.addr)) == 0)
                {
                  NRF_LOG_INFO("device address matched\n\r");
                  d_found = true;
                }
                
              }
              if (!d_found)
              {
                connect_to_target(p_adv_report);
                /* 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.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);
      
    }
    
    
    /** @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();
      scan_init();
    }
    
    
    /**@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);
    
    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 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)
    {
      normal_mode_on = false;
      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)
    {
      normal_mode_on = true;
      scan_stop();
      nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Scan stopped.\r\n");
    }
    
    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);
    
    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_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));
    }
    
    
    /**@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 please find attached file in reply to Andy

    Thanks

  • i have checked i am getting only Timeout error. BLE_GAP_EVT_CONNECTED is not triggered

    Thanks

  • Hi,

    This is expected when the connection is unsuccessful, and you have no timeout. If you did expect the connection to succeed you need to look at the parameters you provided to sd_ble_gap_connect().

    Details: If you set the timeout field in the ble_gap_scan_params_t instance passed to sd_ble_gap_connect() this is BLE_GAP_SCAN_TIMEOUT_UNLIMITED, which indicate "Continue to scan forever". So in this case you will never get any other event then BLE_GAP_EVT_CONNECTED, and scanning will continue until a successful connection is made (and you get the event) or you call sd_ble_gap_connect_cancel().

Related