Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.c
00001 /* 00002 * Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. 00003 * 00004 * The information contained herein is confidential property of Nordic Semiconductor. The use, 00005 * copying, transfer or disclosure of such information is prohibited except by express written 00006 * agreement with Nordic Semiconductor. 00007 * 00008 */ 00009 00010 /** 00011 * @brief BLE Heart Rate Collector application main file. 00012 * 00013 * This file contains the source code for a sample heart rate collector. 00014 */ 00015 00016 #include <stdint.h> 00017 #include <stdio.h> 00018 #include <string.h> 00019 #include "nordic_common.h" 00020 #include "nrf_sdm.h" 00021 #include "ble.h" 00022 #include "ble_hci.h" 00023 #include "ble_db_discovery.h " 00024 #include "softdevice_handler.h " 00025 #include "app_util.h " 00026 #include "app_error.h " 00027 #include "boards.h" 00028 #include "nrf_gpio.h" 00029 #include "pstorage.h" 00030 #include "device_manager.h" 00031 #include "ble_hrs_c.h" 00032 #include "ble_bas_c.h" 00033 #include "app_util.h " 00034 #include "app_timer.h" 00035 #include "bsp.h" 00036 #include "bsp_btn_ble.h" 00037 #include "nrf_log.h" 00038 00039 #define CENTRAL_LINK_COUNT 1 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/ 00040 #define PERIPHERAL_LINK_COUNT 0 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/ 00041 00042 #define STRING_BUFFER_LEN 50 00043 #define BOND_DELETE_ALL_BUTTON_ID 0 /**< Button used for deleting all bonded centrals during startup. */ 00044 00045 #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ 00046 #define APP_TIMER_OP_QUEUE_SIZE 2 /**< Size of timer operation queues. */ 00047 00048 #define APPL_LOG NRF_LOG_PRINTF /**< Logger macro that will be used in this file to do logging over UART or RTT based on nrf_log configuration. */ 00049 #define APPL_LOG_DEBUG NRF_LOG_PRINTF_DEBUG /**< Debug logger macro that will be used in this file to do logging of debug information over UART or RTT based on nrf_log configuration. This will only work if DEBUG is defined*/ 00050 00051 #define SEC_PARAM_BOND 1 /**< Perform bonding. */ 00052 #define SEC_PARAM_MITM 1 /**< Man In The Middle protection not required. */ 00053 #define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ 00054 #define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ 00055 #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ 00056 #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ 00057 #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ 00058 #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ 00059 00060 #define SCAN_INTERVAL 0x00A0 /**< Determines scan interval in units of 0.625 millisecond. */ 00061 #define SCAN_WINDOW 0x0050 /**< Determines scan window in units of 0.625 millisecond. */ 00062 00063 #define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Determines minimum connection interval in millisecond. */ 00064 #define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(30, UNIT_1_25_MS) /**< Determines maximum connection interval in millisecond. */ 00065 #define SLAVE_LATENCY 0 /**< Determines slave latency in counts of connection events. */ 00066 #define SUPERVISION_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Determines supervision time-out in units of 10 millisecond. */ 00067 00068 #define TARGET_UUID 0x180D /**< Target device name that application is looking for. */ 00069 #define UUID16_SIZE 2 /**< Size of 16 bit UUID */ 00070 00071 /**@breif Macro to unpack 16bit unsigned UUID from octet stream. */ 00072 #define UUID16_EXTRACT(DST, SRC) \ 00073 do \ 00074 { \ 00075 (*(DST)) = (SRC)[1]; \ 00076 (*(DST)) <<= 8; \ 00077 (*(DST)) |= (SRC)[0]; \ 00078 } while (0) 00079 00080 /**@brief Variable length data encapsulation in terms of length and pointer to data */ 00081 typedef struct 00082 { 00083 uint8_t * p_data; /**< Pointer to data. */ 00084 uint16_t data_len; /**< Length of data. */ 00085 }data_t; 00086 00087 typedef enum 00088 { 00089 BLE_NO_SCAN, /**< No advertising running. */ 00090 BLE_WHITELIST_SCAN, /**< Advertising with whitelist. */ 00091 BLE_FAST_SCAN, /**< Fast advertising running. */ 00092 } ble_scan_mode_t; 00093 00094 static ble_db_discovery_t m_ble_db_discovery; /**< Structure used to identify the DB Discovery module. */ 00095 static ble_hrs_c_t m_ble_hrs_c; /**< Structure used to identify the heart rate client module. */ 00096 static ble_bas_c_t m_ble_bas_c; /**< Structure used to identify the Battery Service client module. */ 00097 static ble_gap_scan_params_t m_scan_param; /**< Scan parameters requested for scanning and connection. */ 00098 static dm_application_instance_t m_dm_app_id; /**< Application identifier. */ 00099 static dm_handle_t m_dm_device_handle; /**< Device Identifier identifier. */ 00100 static uint8_t m_peer_count = 0; /**< Number of peer's connected. */ 00101 static ble_scan_mode_t m_scan_mode = BLE_FAST_SCAN; /**< Scan mode used by application. */ 00102 static uint16_t m_conn_handle; /**< Current connection handle. */ 00103 static volatile bool m_whitelist_temporarily_disabled = false; /**< True if whitelist has been temporarily disabled. */ 00104 00105 static bool m_memory_access_in_progress = false; /**< Flag to keep track of ongoing operations on persistent memory. */ 00106 00107 /** 00108 * @brief Connection parameters requested for connection. 00109 */ 00110 static const ble_gap_conn_params_t m_connection_param = 00111 { 00112 (uint16_t)MIN_CONNECTION_INTERVAL, // Minimum connection 00113 (uint16_t)MAX_CONNECTION_INTERVAL, // Maximum connection 00114 0, // Slave latency 00115 (uint16_t)SUPERVISION_TIMEOUT // Supervision time-out 00116 }; 00117 00118 static void scan_start(void); 00119 00120 00121 /**@brief Function for asserts in the SoftDevice. 00122 * 00123 * @details This function will be called in case of an assert in the SoftDevice. 00124 * 00125 * @warning This handler is an example only and does not fit a final product. You need to analyze 00126 * how your product is supposed to react in case of Assert. 00127 * @warning On assert from the SoftDevice, the system can only recover on reset. 00128 * 00129 * @param[in] line_num Line number of the failing ASSERT call. 00130 * @param[in] p_file_name File name of the failing ASSERT call. 00131 */ 00132 void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) 00133 { 00134 app_error_handler(0xDEADBEEF, line_num, p_file_name); 00135 } 00136 00137 void uart_error_handle(app_uart_evt_t * p_event) 00138 { 00139 if (p_event->evt_type == APP_UART_COMMUNICATION_ERROR) 00140 { 00141 APP_ERROR_HANDLER(p_event->data.error_communication); 00142 } 00143 else if (p_event->evt_type == APP_UART_FIFO_ERROR) 00144 { 00145 APP_ERROR_HANDLER(p_event->data.error_code); 00146 } 00147 } 00148 00149 00150 /**@brief Function for handling database discovery events. 00151 * 00152 * @details This function is callback function to handle events from the database discovery module. 00153 * Depending on the UUIDs that are discovered, this function should forward the events 00154 * to their respective services. 00155 * 00156 * @param[in] p_event Pointer to the database discovery event. 00157 */ 00158 static void db_disc_handler(ble_db_discovery_evt_t * p_evt) 00159 { 00160 ble_hrs_on_db_disc_evt(&m_ble_hrs_c, p_evt); 00161 ble_bas_on_db_disc_evt(&m_ble_bas_c, p_evt); 00162 } 00163 00164 00165 /**@brief Callback handling device manager events. 00166 * 00167 * @details This function is called to notify the application of device manager events. 00168 * 00169 * @param[in] p_handle Device Manager Handle. For link related events, this parameter 00170 * identifies the peer. 00171 * @param[in] p_event Pointer to the device manager event. 00172 * @param[in] event_status Status of the event. 00173 */ 00174 static ret_code_t device_manager_event_handler(const dm_handle_t * p_handle, 00175 const dm_event_t * p_event, 00176 const ret_code_t event_result) 00177 { 00178 uint32_t err_code; 00179 00180 switch (p_event->event_id) 00181 { 00182 case DM_EVT_CONNECTION: 00183 { 00184 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_CONNECTION\r\n"); 00185 #ifdef ENABLE_DEBUG_LOG_SUPPORT 00186 ble_gap_addr_t * peer_addr; 00187 peer_addr = &p_event->event_param.p_gap_param->params.connected.peer_addr; 00188 APPL_LOG_DEBUG("[APPL]:[%02X %02X %02X %02X %02X %02X]: Connection Established\r\n", 00189 peer_addr->addr[0], peer_addr->addr[1], peer_addr->addr[2], 00190 peer_addr->addr[3], peer_addr->addr[4], peer_addr->addr[5]); 00191 #endif // ENABLE_DEBUG_LOG_SUPPORT 00192 00193 err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); 00194 APP_ERROR_CHECK(err_code); 00195 00196 m_conn_handle = p_event->event_param.p_gap_param->conn_handle; 00197 00198 m_dm_device_handle = (*p_handle); 00199 00200 // Initiate bonding. 00201 err_code = dm_security_setup_req(&m_dm_device_handle); 00202 APP_ERROR_CHECK(err_code); 00203 00204 m_peer_count++; 00205 00206 if (m_peer_count < CENTRAL_LINK_COUNT) 00207 { 00208 scan_start(); 00209 } 00210 APPL_LOG_DEBUG("[APPL]: << DM_EVT_CONNECTION\r\n"); 00211 break; 00212 } 00213 00214 case DM_EVT_DISCONNECTION: 00215 { 00216 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DISCONNECTION\r\n"); 00217 memset(&m_ble_db_discovery, 0 , sizeof (m_ble_db_discovery)); 00218 00219 err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00220 APP_ERROR_CHECK(err_code); 00221 00222 if (m_peer_count == CENTRAL_LINK_COUNT) 00223 { 00224 scan_start(); 00225 } 00226 m_peer_count--; 00227 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DISCONNECTION\r\n"); 00228 break; 00229 } 00230 00231 case DM_EVT_SECURITY_SETUP: 00232 { 00233 APPL_LOG_DEBUG("[APPL]:[0x%02X] >> DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); 00234 // Slave securtiy request received from peer, if from a non bonded device, 00235 // initiate security setup, else, wait for encryption to complete. 00236 err_code = dm_security_setup_req(&m_dm_device_handle); 00237 APP_ERROR_CHECK(err_code); 00238 APPL_LOG_DEBUG("[APPL]:[0x%02X] << DM_EVT_SECURITY_SETUP\r\n", p_handle->connection_id); 00239 break; 00240 } 00241 00242 case DM_EVT_SECURITY_SETUP_COMPLETE: 00243 { 00244 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); 00245 APPL_LOG_DEBUG("[APPL]: << DM_EVT_SECURITY_SETUP_COMPLETE\r\n"); 00246 break; 00247 } 00248 00249 case DM_EVT_LINK_SECURED: 00250 APPL_LOG_DEBUG("[APPL]: >> DM_LINK_SECURED_IND\r\n"); 00251 // Discover peer's services. 00252 err_code = ble_db_discovery_start(&m_ble_db_discovery, 00253 p_event->event_param.p_gap_param->conn_handle); 00254 APP_ERROR_CHECK(err_code); 00255 APPL_LOG_DEBUG("[APPL]: << DM_LINK_SECURED_IND\r\n"); 00256 break; 00257 00258 case DM_EVT_DEVICE_CONTEXT_LOADED: 00259 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_LINK_SECURED\r\n"); 00260 APP_ERROR_CHECK(event_result); 00261 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_LOADED\r\n"); 00262 break; 00263 00264 case DM_EVT_DEVICE_CONTEXT_STORED: 00265 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_STORED\r\n"); 00266 APP_ERROR_CHECK(event_result); 00267 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_STORED\r\n"); 00268 break; 00269 00270 case DM_EVT_DEVICE_CONTEXT_DELETED: 00271 APPL_LOG_DEBUG("[APPL]: >> DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); 00272 APP_ERROR_CHECK(event_result); 00273 APPL_LOG_DEBUG("[APPL]: << DM_EVT_DEVICE_CONTEXT_DELETED\r\n"); 00274 break; 00275 00276 default: 00277 break; 00278 } 00279 00280 return NRF_SUCCESS; 00281 } 00282 00283 00284 /** 00285 * @brief Parses advertisement data, providing length and location of the field in case 00286 * matching data is found. 00287 * 00288 * @param[in] Type of data to be looked for in advertisement data. 00289 * @param[in] Advertisement report length and pointer to report. 00290 * @param[out] If data type requested is found in the data report, type data length and 00291 * pointer to data will be populated here. 00292 * 00293 * @retval NRF_SUCCESS if the data type is found in the report. 00294 * @retval NRF_ERROR_NOT_FOUND if the data type could not be found. 00295 */ 00296 static uint32_t adv_report_parse(uint8_t type, data_t * p_advdata, data_t * p_typedata) 00297 { 00298 uint32_t index = 0; 00299 uint8_t * p_data; 00300 00301 p_data = p_advdata->p_data; 00302 00303 while (index < p_advdata->data_len) 00304 { 00305 uint8_t field_length = p_data[index]; 00306 uint8_t field_type = p_data[index+1]; 00307 00308 if (field_type == type) 00309 { 00310 p_typedata->p_data = &p_data[index+2]; 00311 p_typedata->data_len = field_length-1; 00312 return NRF_SUCCESS; 00313 } 00314 index += field_length + 1; 00315 } 00316 return NRF_ERROR_NOT_FOUND; 00317 } 00318 00319 00320 /**@brief Function for putting the chip into sleep mode. 00321 * 00322 * @note This function will not return. 00323 */ 00324 static void sleep_mode_enter(void) 00325 { 00326 uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00327 APP_ERROR_CHECK(err_code); 00328 00329 // Prepare wakeup buttons. 00330 err_code = bsp_btn_ble_sleep_mode_prepare(); 00331 APP_ERROR_CHECK(err_code); 00332 00333 // Go to system-off mode (this function will not return; wakeup will cause a reset). 00334 err_code = sd_power_system_off(); 00335 APP_ERROR_CHECK(err_code); 00336 } 00337 00338 00339 /**@brief Function for handling the Application's BLE Stack events. 00340 * 00341 * @param[in] p_ble_evt Bluetooth stack event. 00342 */ 00343 static void on_ble_evt(ble_evt_t * p_ble_evt) 00344 { 00345 uint32_t err_code; 00346 const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt; 00347 00348 switch (p_ble_evt->header.evt_id) 00349 { 00350 case BLE_GAP_EVT_ADV_REPORT: 00351 { 00352 data_t adv_data; 00353 data_t type_data; 00354 00355 // Initialize advertisement report for parsing. 00356 adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data; 00357 adv_data.data_len = p_gap_evt->params.adv_report.dlen; 00358 00359 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, 00360 &adv_data, 00361 &type_data); 00362 00363 if (err_code != NRF_SUCCESS) 00364 { 00365 // Compare short local name in case complete name does not match. 00366 err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, 00367 &adv_data, 00368 &type_data); 00369 } 00370 00371 // Verify if short or complete name matches target. 00372 if (err_code == NRF_SUCCESS) 00373 { 00374 uint16_t extracted_uuid; 00375 00376 // UUIDs found, look for matching UUID 00377 for (uint32_t u_index = 0; u_index < (type_data.data_len/UUID16_SIZE); u_index++) 00378 { 00379 UUID16_EXTRACT(&extracted_uuid,&type_data.p_data[u_index * UUID16_SIZE]); 00380 00381 APPL_LOG_DEBUG("\t[APPL]: %x\r\n",extracted_uuid); 00382 00383 if(extracted_uuid == TARGET_UUID) 00384 { 00385 // Stop scanning. 00386 err_code = sd_ble_gap_scan_stop(); 00387 00388 if (err_code != NRF_SUCCESS) 00389 { 00390 APPL_LOG_DEBUG("[APPL]: Scan stop failed, reason %d\r\n", err_code); 00391 } 00392 err_code = bsp_indication_set(BSP_INDICATE_IDLE); 00393 APP_ERROR_CHECK(err_code); 00394 00395 m_scan_param.selective = 0; 00396 m_scan_param.p_whitelist = NULL; 00397 00398 // Initiate connection. 00399 err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.peer_addr, 00400 &m_scan_param, 00401 &m_connection_param); 00402 00403 m_whitelist_temporarily_disabled = false; 00404 00405 if (err_code != NRF_SUCCESS) 00406 { 00407 APPL_LOG_DEBUG("[APPL]: Connection Request Failed, reason %d\r\n", err_code); 00408 } 00409 break; 00410 } 00411 } 00412 } 00413 break; 00414 } 00415 00416 case BLE_GAP_EVT_TIMEOUT: 00417 if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) 00418 { 00419 APPL_LOG_DEBUG("[APPL]: Scan timed out.\r\n"); 00420 scan_start(); 00421 } 00422 else if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) 00423 { 00424 APPL_LOG_DEBUG("[APPL]: Connection Request timed out.\r\n"); 00425 } 00426 break; 00427 case BLE_GAP_EVT_CONNECTED: 00428 { 00429 err_code = ble_hrs_c_handles_assign(&m_ble_hrs_c, p_gap_evt->conn_handle, NULL); 00430 APP_ERROR_CHECK(err_code); 00431 err_code = ble_bas_c_handles_assign(&m_ble_bas_c, p_gap_evt->conn_handle, NULL); 00432 APP_ERROR_CHECK(err_code); 00433 break; 00434 } 00435 case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: 00436 // Accepting parameters requested by peer. 00437 err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle, 00438 &p_gap_evt->params.conn_param_update_request.conn_params); 00439 APP_ERROR_CHECK(err_code); 00440 break; 00441 00442 default: 00443 break; 00444 } 00445 } 00446 00447 00448 /**@brief Function for handling the Application's system events. 00449 * 00450 * @param[in] sys_evt system event. 00451 */ 00452 static void on_sys_evt(uint32_t sys_evt) 00453 { 00454 switch (sys_evt) 00455 { 00456 case NRF_EVT_FLASH_OPERATION_SUCCESS: 00457 /* fall through */ 00458 case NRF_EVT_FLASH_OPERATION_ERROR: 00459 00460 if (m_memory_access_in_progress) 00461 { 00462 m_memory_access_in_progress = false; 00463 scan_start(); 00464 } 00465 break; 00466 00467 default: 00468 // No implementation needed. 00469 break; 00470 } 00471 } 00472 00473 00474 /**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler. 00475 * 00476 * @details This function is called from the scheduler in the main loop after a BLE stack event has 00477 * been received. 00478 * 00479 * @param[in] p_ble_evt Bluetooth stack event. 00480 */ 00481 static void ble_evt_dispatch(ble_evt_t * p_ble_evt) 00482 { 00483 dm_ble_evt_handler(p_ble_evt); 00484 ble_db_discovery_on_ble_evt(&m_ble_db_discovery, p_ble_evt); 00485 ble_hrs_c_on_ble_evt(&m_ble_hrs_c, p_ble_evt); 00486 ble_bas_c_on_ble_evt(&m_ble_bas_c, p_ble_evt); 00487 bsp_btn_ble_on_ble_evt(p_ble_evt); 00488 on_ble_evt(p_ble_evt); 00489 } 00490 00491 00492 /**@brief Function for dispatching a system event to interested modules. 00493 * 00494 * @details This function is called from the System event interrupt handler after a system 00495 * event has been received. 00496 * 00497 * @param[in] sys_evt System stack event. 00498 */ 00499 static void sys_evt_dispatch(uint32_t sys_evt) 00500 { 00501 pstorage_sys_event_handler(sys_evt); 00502 on_sys_evt(sys_evt); 00503 } 00504 00505 00506 /**@brief Function for initializing the BLE stack. 00507 * 00508 * @details Initializes the SoftDevice and the BLE event interrupt. 00509 */ 00510 static void ble_stack_init(void) 00511 { 00512 uint32_t err_code; 00513 00514 nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; 00515 00516 // Initialize the SoftDevice handler module. 00517 SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL); 00518 00519 ble_enable_params_t ble_enable_params; 00520 err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT, 00521 PERIPHERAL_LINK_COUNT, 00522 &ble_enable_params); 00523 APP_ERROR_CHECK(err_code); 00524 00525 //Check the ram settings against the used number of links 00526 CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT); 00527 00528 // Enable BLE stack. 00529 err_code = softdevice_enable(&ble_enable_params); 00530 APP_ERROR_CHECK(err_code); 00531 00532 // Register with the SoftDevice handler module for BLE events. 00533 err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); 00534 APP_ERROR_CHECK(err_code); 00535 00536 // Register with the SoftDevice handler module for System events. 00537 err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); 00538 APP_ERROR_CHECK(err_code); 00539 } 00540 00541 00542 /**@brief Function for the Device Manager initialization. 00543 * 00544 * @param[in] erase_bonds Indicates whether bonding information should be cleared from 00545 * persistent storage during initialization of the Device Manager. 00546 */ 00547 static void device_manager_init(bool erase_bonds) 00548 { 00549 uint32_t err_code; 00550 dm_init_param_t init_param = {.clear_persistent_data = erase_bonds}; 00551 dm_application_param_t register_param; 00552 00553 err_code = pstorage_init(); 00554 APP_ERROR_CHECK(err_code); 00555 00556 err_code = dm_init(&init_param); 00557 APP_ERROR_CHECK(err_code); 00558 00559 memset(®ister_param.sec_param, 0, sizeof (ble_gap_sec_params_t)); 00560 00561 // Event handler to be registered with the module. 00562 register_param.evt_handler = device_manager_event_handler; 00563 00564 // Service or protocol context for device manager to load, store and apply on behalf of application. 00565 // Here set to client as application is a GATT client. 00566 register_param.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID; 00567 00568 // Secuirty parameters to be used for security procedures. 00569 register_param.sec_param.bond = SEC_PARAM_BOND; 00570 register_param.sec_param.mitm = SEC_PARAM_MITM; 00571 register_param.sec_param.lesc = SEC_PARAM_LESC; 00572 register_param.sec_param.keypress = SEC_PARAM_KEYPRESS; 00573 register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; 00574 register_param.sec_param.oob = SEC_PARAM_OOB; 00575 register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; 00576 register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; 00577 register_param.sec_param.kdist_peer.enc = 1; 00578 register_param.sec_param.kdist_peer.id = 1; 00579 00580 err_code = dm_register(&m_dm_app_id, ®ister_param); 00581 APP_ERROR_CHECK(err_code); 00582 } 00583 00584 00585 /**@brief Function for disabling the use of whitelist for scanning. 00586 */ 00587 static void whitelist_disable(void) 00588 { 00589 uint32_t err_code; 00590 00591 if ((m_scan_mode == BLE_WHITELIST_SCAN) && !m_whitelist_temporarily_disabled) 00592 { 00593 m_whitelist_temporarily_disabled = true; 00594 00595 err_code = sd_ble_gap_scan_stop(); 00596 if (err_code == NRF_SUCCESS) 00597 { 00598 scan_start(); 00599 } 00600 else if (err_code != NRF_ERROR_INVALID_STATE) 00601 { 00602 APP_ERROR_CHECK(err_code); 00603 } 00604 } 00605 m_whitelist_temporarily_disabled = true; 00606 } 00607 00608 00609 /**@brief Function for handling events from the BSP module. 00610 * 00611 * @param[in] event Event generated by button press. 00612 */ 00613 void bsp_event_handler(bsp_event_t event) 00614 { 00615 uint32_t err_code; 00616 switch (event) 00617 { 00618 case BSP_EVENT_SLEEP: 00619 sleep_mode_enter(); 00620 break; 00621 00622 case BSP_EVENT_DISCONNECT: 00623 err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); 00624 if (err_code != NRF_ERROR_INVALID_STATE) 00625 { 00626 APP_ERROR_CHECK(err_code); 00627 } 00628 break; 00629 00630 case BSP_EVENT_WHITELIST_OFF: 00631 whitelist_disable(); 00632 break; 00633 00634 default: 00635 break; 00636 } 00637 } 00638 00639 00640 /**@brief Heart Rate Collector Handler. 00641 */ 00642 static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt) 00643 { 00644 uint32_t err_code; 00645 00646 switch (p_hrs_c_evt->evt_type) 00647 { 00648 case BLE_HRS_C_EVT_DISCOVERY_COMPLETE: 00649 00650 // Heart rate service discovered. Enable notification of Heart Rate Measurement. 00651 err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c); 00652 APP_ERROR_CHECK(err_code); 00653 00654 APPL_LOG_DEBUG("Heart rate service discovered \r\n"); 00655 break; 00656 00657 case BLE_HRS_C_EVT_HRM_NOTIFICATION: 00658 { 00659 APPL_LOG_DEBUG("[APPL]: HR Measurement received %d \r\n", p_hrs_c_evt->params.hrm.hr_value); 00660 00661 APPL_LOG("Heart Rate = %d\r\n", p_hrs_c_evt->params.hrm.hr_value); 00662 break; 00663 } 00664 00665 default: 00666 break; 00667 } 00668 } 00669 00670 00671 /**@brief Battery levelCollector Handler. 00672 */ 00673 static void bas_c_evt_handler(ble_bas_c_t * p_bas_c, ble_bas_c_evt_t * p_bas_c_evt) 00674 { 00675 uint32_t err_code; 00676 00677 switch (p_bas_c_evt->evt_type) 00678 { 00679 case BLE_BAS_C_EVT_DISCOVERY_COMPLETE: 00680 // Batttery service discovered. Enable notification of Battery Level. 00681 APPL_LOG_DEBUG("[APPL]: Battery Service discovered. \r\n"); 00682 00683 APPL_LOG_DEBUG("[APPL]: Reading battery level. \r\n"); 00684 00685 err_code = ble_bas_c_bl_read(p_bas_c); 00686 APP_ERROR_CHECK(err_code); 00687 00688 00689 APPL_LOG_DEBUG("[APPL]: Enabling Battery Level Notification. \r\n"); 00690 err_code = ble_bas_c_bl_notif_enable(p_bas_c); 00691 APP_ERROR_CHECK(err_code); 00692 00693 break; 00694 00695 case BLE_BAS_C_EVT_BATT_NOTIFICATION: 00696 { 00697 APPL_LOG_DEBUG("[APPL]: Battery Level received %d %%\r\n", p_bas_c_evt->params.battery_level); 00698 00699 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level); 00700 break; 00701 } 00702 00703 case BLE_BAS_C_EVT_BATT_READ_RESP: 00704 { 00705 APPL_LOG_DEBUG("[APPL]: Battery Level Read as %d %%\r\n", p_bas_c_evt->params.battery_level); 00706 00707 APPL_LOG_DEBUG("Battery = %d %%\r\n", p_bas_c_evt->params.battery_level); 00708 break; 00709 } 00710 00711 default: 00712 break; 00713 } 00714 } 00715 00716 00717 /** 00718 * @brief Heart rate collector initialization. 00719 */ 00720 static void hrs_c_init(void) 00721 { 00722 ble_hrs_c_init_t hrs_c_init_obj; 00723 00724 hrs_c_init_obj.evt_handler = hrs_c_evt_handler; 00725 00726 uint32_t err_code = ble_hrs_c_init(&m_ble_hrs_c, &hrs_c_init_obj); 00727 APP_ERROR_CHECK(err_code); 00728 } 00729 00730 00731 /** 00732 * @brief Battery level collector initialization. 00733 */ 00734 static void bas_c_init(void) 00735 { 00736 ble_bas_c_init_t bas_c_init_obj; 00737 00738 bas_c_init_obj.evt_handler = bas_c_evt_handler; 00739 00740 uint32_t err_code = ble_bas_c_init(&m_ble_bas_c, &bas_c_init_obj); 00741 APP_ERROR_CHECK(err_code); 00742 } 00743 00744 00745 /** 00746 * @brief Database discovery collector initialization. 00747 */ 00748 static void db_discovery_init(void) 00749 { 00750 uint32_t err_code = ble_db_discovery_init(db_disc_handler); 00751 00752 APP_ERROR_CHECK(err_code); 00753 } 00754 00755 00756 /**@brief Function to start scanning. 00757 */ 00758 static void scan_start(void) 00759 { 00760 ble_gap_whitelist_t whitelist; 00761 ble_gap_addr_t * p_whitelist_addr[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; 00762 ble_gap_irk_t * p_whitelist_irk[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; 00763 uint32_t err_code; 00764 uint32_t count; 00765 00766 // Verify if there is any flash access pending, if yes delay starting scanning until 00767 // it's complete. 00768 err_code = pstorage_access_status_get(&count); 00769 APP_ERROR_CHECK(err_code); 00770 00771 if (count != 0) 00772 { 00773 m_memory_access_in_progress = true; 00774 return; 00775 } 00776 00777 // Initialize whitelist parameters. 00778 whitelist.addr_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; 00779 whitelist.irk_count = 0; 00780 whitelist.pp_addrs = p_whitelist_addr; 00781 whitelist.pp_irks = p_whitelist_irk; 00782 00783 // Request creating of whitelist. 00784 err_code = dm_whitelist_create(&m_dm_app_id,&whitelist); 00785 APP_ERROR_CHECK(err_code); 00786 00787 if (((whitelist.addr_count == 0) && (whitelist.irk_count == 0)) || 00788 (m_scan_mode != BLE_WHITELIST_SCAN) || 00789 (m_whitelist_temporarily_disabled)) 00790 { 00791 // No devices in whitelist, hence non selective performed. 00792 m_scan_param.active = 0; // Active scanning set. 00793 m_scan_param.selective = 0; // Selective scanning not set. 00794 m_scan_param.interval = SCAN_INTERVAL;// Scan interval. 00795 m_scan_param.window = SCAN_WINDOW; // Scan window. 00796 m_scan_param.p_whitelist = NULL; // No whitelist provided. 00797 m_scan_param.timeout = 0x0000; // No timeout. 00798 } 00799 else 00800 { 00801 // Selective scanning based on whitelist first. 00802 m_scan_param.active = 0; // Active scanning set. 00803 m_scan_param.selective = 1; // Selective scanning not set. 00804 m_scan_param.interval = SCAN_INTERVAL;// Scan interval. 00805 m_scan_param.window = SCAN_WINDOW; // Scan window. 00806 m_scan_param.p_whitelist = &whitelist; // Provide whitelist. 00807 m_scan_param.timeout = 0x001E; // 30 seconds timeout. 00808 } 00809 00810 err_code = sd_ble_gap_scan_start(&m_scan_param); 00811 APP_ERROR_CHECK(err_code); 00812 00813 err_code = bsp_indication_set(BSP_INDICATE_SCANNING); 00814 APP_ERROR_CHECK(err_code); 00815 } 00816 00817 00818 /**@brief Function for initializing buttons and leds. 00819 * 00820 * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. 00821 */ 00822 static void buttons_leds_init(bool * p_erase_bonds) 00823 { 00824 bsp_event_t startup_event; 00825 00826 uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, 00827 APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), 00828 bsp_event_handler); 00829 APP_ERROR_CHECK(err_code); 00830 00831 err_code = bsp_btn_ble_init(NULL, &startup_event); 00832 APP_ERROR_CHECK(err_code); 00833 00834 *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); 00835 } 00836 00837 00838 /**@brief Function for initializing the nrf log module. 00839 */ 00840 static void nrf_log_init(void) 00841 { 00842 ret_code_t err_code = NRF_LOG_INIT(); 00843 APP_ERROR_CHECK(err_code); 00844 } 00845 00846 00847 /** @brief Function for the Power manager. 00848 */ 00849 static void power_manage(void) 00850 { 00851 uint32_t err_code = sd_app_evt_wait(); 00852 APP_ERROR_CHECK(err_code); 00853 } 00854 00855 00856 int main(void) 00857 { 00858 bool erase_bonds; 00859 00860 // Initialize. 00861 APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL); 00862 buttons_leds_init(&erase_bonds); 00863 nrf_log_init(); 00864 APPL_LOG("Heart rate collector example\r\n"); 00865 ble_stack_init(); 00866 device_manager_init(erase_bonds); 00867 db_discovery_init(); 00868 hrs_c_init(); 00869 bas_c_init(); 00870 00871 // Start scanning for peripherals and initiate connection 00872 // with devices that advertise Heart Rate UUID. 00873 scan_start(); 00874 00875 for (;; ) 00876 { 00877 power_manage(); 00878 } 00879 } 00880 00881 00882
Generated on Wed Jul 13 2022 07:07:19 by
