Hi
Am new to the nrf52382 , Am trying to establish connection between nrf52382 DK as peripheral and nrf connect app as central,
Am unable to connect it .Please debug the issue
* 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 <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_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_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_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#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 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 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_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 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
#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()). */
*
* @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))
typedef void (*app_sched_event_handler_t)(void * p_event_data, uint16_t event_size);
*
* @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)
// *
// * @details It must be called before entering the main loop.
// *
// * @param[in] max_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).
// * @param[in] p_evt_buffer Pointer to memory buffer for holding the scheduler queue. It must
// * be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer
// * must be aligned to a 4 byte boundary.
// *
// * @note Normally initialization should be done using the APP_SCHED_INIT() macro, as that will both
// * allocate the scheduler buffer, and also align the buffer correctly.
// *
// * @retval NRF_SUCCESS Successful initialization.
// * @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte
// * boundary).
// */
//uint32_t app_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer);
*
* @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);
*
* @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);
*
* @{ */
/** Initialization of buffer list */
#define BUFFER_LIST_INIT() \
do \
{ \
buffer_list.rp = 0; \
buffer_list.wp = 0; \
buffer_list.count = 0; \
} while (0)
#define BUFFER_LIST_FULL() \
((MAX_BUFFER_ENTRIES == buffer_list.count - 1) ? true : false)
#define BUFFER_LIST_EMPTY() \
((0 == buffer_list.count) ? true : false)
do \
{ \
buffer_list.buffer[(i)].p_data = NULL; \
} while (0)
//Tabs end
{
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. */
// uint8_t uuid_buffer_2[UUID16_SIZE]; /**< Buffer for storing an UUID16. */
// uint8_t uuid_buffer_3[UUID128_SIZE]; /**< Buffer for storing an UUID128. */
// uint8_t uuid_buffer_4[UUID128_SIZE]; /**< Buffer for storing an UUID128. */
// uint8_t uuid_buffer_5[UUID128_SIZE]; /**< Buffer for storing an UUID128. */
uint16_t uuid_len;
uint8_t uuid_type;
}scanned_device_t;
{
uint8_t * p_data; /**< Pointer to data. */
uint16_t data_len; /**< Length of data. */
} data_t;
{
return m_device;
}
{
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);
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. */
#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);
void print_uuid(char * p_result, uint8_t result_len, uint8_t const * const p_uuid, uint8_t size);
{
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)
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} ;// //{{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}}; /**< Used vendor specific UUID. */
//NONIN UUID = {0x1B, 0xC5, 0xD5, 0xA5, 0x02, 0x00, 0x5E, 0x8B, 0xE2, 0x11, 0x5F, 0x0D, 0x00, 0x00, 0xA9, 0x46}
//static ble_uuid128_t m_uuid128[] = {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E}, {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_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. */
{
.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
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;
//BLE_HTS_DEF(m_hts);
//static void on_hts_evt(ble_hts_t * p_hts, ble_hts_evt_t * p_evt);
//#define TEMP_TYPE_AS_CHARACTERISTIC 0 /**< Determines if temperature type is given as characteristic (1) or as a field of measurement (0). */
//static bool m_hts_meas_ind_conf_pending = false; /**< Flag to keep track of when an indication confirmation is pending. */
//static sensorsim_cfg_t m_temp_celcius_sim_cfg; /**< Temperature simulator configuration. */
//static sensorsim_state_t m_temp_celcius_sim_state; /**< Temperature simulator state. */
//static void temperature_measurement_send(void);
//static void hts_sim_measurement(ble_hts_meas_t * p_meas);
//#define BLE_UUID_NONIN_SENSOR_SERVICE_BASE {{0x1B, 0xC5, 0xD5, 0xA5, 0x02, 0x00, 0x5E, 0x8B, 0xE2, 0x11, 0x5F, 0x0D, 0xE0, 0x70, 0xA9, 0x46}} //NONIN UUID
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_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);
{
{BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_BLE},
{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE},
};
*
* @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;
}
}
*
* @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);
}
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 = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_hts->service_handle);
// if (err_code != NRF_SUCCESS)
// {
// APP_ERROR_CHECK(err_code);
// }
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");
}
// ble_add_char_params_t add_char_params;
// 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");
}
// Add the Custom Service
// err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_cus->service_handle);
// if (err_code != NRF_SUCCESS)
// {
//
// return err_code;
// }
//// // Initialize CUS Service init structure to zero.
// memset(&cus_init, 0, sizeof(cus_init));
// cus_init.evt_handler = on_cus_evt;
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.cccd_write_perm);
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.read_perm);
// BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cus_init.custom_value_char_attr_md.write_perm);
// err_code = ble_cus_init(&m_cus, &cus_init);
// APP_ERROR_CHECK(err_code);
//
// APP_ERROR_CHECK(err_code);
// // Initialize Health Thermometer Service
// memset(&hts_init, 0, sizeof(hts_init));
//
// hts_init.evt_handler = on_hts_evt;
// hts_init.temp_type_as_characteristic = TEMP_TYPE_AS_CHARACTERISTIC;
// hts_init.temp_type = BLE_HTS_TEMP_TYPE_BODY;
//
// // Here the sec level for the Health Thermometer Service can be changed/increased.
// hts_init.ht_meas_cccd_wr_sec = SEC_JUST_WORKS;
// hts_init.ht_type_rd_sec = SEC_OPEN;
//
// err_code = ble_hts_init(&m_hts, &hts_init);
// APP_ERROR_CHECK(err_code);
//
}
*
* @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;
// nrf_ble_scan_t * p_scan_ctx = (nrf_ble_scan_t *)p_context;
// ble_gap_evt_adv_report_t const * p_adv_report = &p_ble_evt->evt.gap_evt.params.adv_report;
//ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context;
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;
// case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
// {
// //NRF_LOG_INFO("Discovered service for: %x %x %x\n",p_gap_evt->params.adv_report.peer_addr.addr[0], p_gap_evt->params.adv_report.peer_addr.addr[1], p_gap_evt->params.adv_report.peer_addr.addr[5] );
// // on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
// }
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;
// case BLE_DB_DISCOVERY_COMPLETE:
// {
//
// /* service available indication to known list*/
// memcpy(k_device[k_idx].addr,p_adv_report->peer_addr.addr,sizeof(p_adv_report->peer_addr.addr));
// k_device[k_idx].is_not_empty = true;
// k_idx++;
// 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("I Disconnected it\n\r");
// }
// }
// }
// break;
//
default:
// No implementation needed.
break;
}
}
*
* @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);
}
{
// 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);
}
*
* @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;
}
}
{
// Check if the Led Button Service was discovered.
// if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
// p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE)
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)
{
// NRF_LOG_INFO("call to ble_serv_on_db_disc_evt for instance %d and link 0x%x!",
// p_evt->conn_handle,
// p_evt->conn_handle);
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);
}
{
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();
}
}
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)
{
// memcpy(k_device[0].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; //Validating the list record
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;
// NRF_LOG_INFO("matched id = %x %x\n", raw_uuid->uuid128[0], m_device[idx].uuid_buffer_1[0] );
// if (m_device[idx].uuid_buffer_1[0] == raw_uuid->uuid128[0])
// {
// NRF_LOG_INFO("matched id = %.2x\n", m_device[idx].uuid_buffer_1[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;
// raw_uuid = (uint8_t *)m_uuid128;
// }
// 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;
// raw_uuid = (uint8_t *)m_uuid16;
// }
// for (uint16_t list_offset = 0; list_offset < parsed_uuid_len; list_offset += raw_uuid_len)
// {
//
// if ( memcmp(p_parsed_uuid, raw_uuid, raw_uuid_len))
// {
// NRF_LOG_INFO("matched uuid);
// }
// }
//
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
*/
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;
}
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;
}
{
ret_code_t ret;
nrf_ble_scan_stop();
ret = bsp_indication_set(BSP_INDICATE_SCANNING);
APP_ERROR_CHECK(ret);
m_scanning = false;
}
{
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, ":");
}
}
}
{
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, "-");
}
}
}
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);
// switch (p_device[i].uuid_type)
// {
// case BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE:
// {
// nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Complete list of 128 bit UUID: %s \r\n\n", ubuffer);
// }break;
//
// case BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE:
// {
// nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Incomplete list of 128 bit UUID: %s \r\n\n", ubuffer);
//
// }break;
//
// case BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE:
// {
// nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Complete list of 16 bit UUID: %s \r\n\n", ubuffer);
//
// }break;
//
// case BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE:
// {
// nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Incomplete list of 16 bit UUID: %s \r\n", ubuffer);
//
// }break;
// default:
// {
// // nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "UUID Not found\r\n");
// }break;
//
// }//End switch
}
}
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);
}
}
{
scan_start();
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Scanning...\r\n");
}
{
scan_stop();
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Scan stopped.\r\n");
}
{
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;
}
}
}
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
{
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();
}
}
{
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 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 initializing the nrf log module.
//*/
//static void log_init(void)
//{
// ret_code_t err_code = NRF_LOG_INIT(NULL);
// APP_ERROR_CHECK(err_code);
//
// NRF_LOG_DEFAULT_BACKENDS_INIT();
//}
///**@brief Function for the Timer initialization.
// *
// * @details Initializes the timer module.
// */
//static void timers_init(void)
//{
// ret_code_t err_code;
//
// err_code = app_timer_init();
// APP_ERROR_CHECK(err_code);
//
// // Create battery timer.
// err_code = app_timer_create(&m_battery_timer_id,
// APP_TIMER_MODE_REPEATED,
// battery_level_meas_timeout_handler);
// APP_ERROR_CHECK(err_code);
//}
// */
//static void power_management_init(void)
//{
// ret_code_t err_code;
// err_code = nrf_pwr_mgmt_init();
// APP_ERROR_CHECK(err_code);
//}
// */
//static void scheduler_init(void)
//{
// APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
//}
/**@brief Function for application main entry.
*/
int main(void)
bool erase_bonds;
core_init();
// log_init();
//timers_init();
// power_management_init();
//scheduler_init();
// buffer_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);
}
}

