/****************************************Copyright (c)************************************************ ** **--------------File Info----------------------------------------------------------------------------- ** File name:ble_nus.c ** Last modified Date: ** Last Version: ** Descriptions :串口透传服务文件 **---------------------------------------------------------------------------------------------------*/ #include "sdk_common.h" //这里设置了串口透传服务程序模块的“编译开关”,所以要在sdk_config.h中启用BLE_NUS #if NRF_MODULE_ENABLED(BLE_NUS) #include "ble.h" #include "ble_nus.h" #include "ble_srv_common.h" #include "nrf_log.h" #if 0 #define NRF_LOG_MODULE_NAME ble_nus #if BLE_NUS_CONFIG_LOG_ENABLED #define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL #define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR #define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR #else // BLE_NUS_CONFIG_LOG_ENABLED #define NRF_LOG_LEVEL 0 #endif // BLE_NUS_CONFIG_LOG_ENABLED NRF_LOG_MODULE_REGISTER(); #endif #define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN //RX特征最大长度(字节数) #define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN //TX特征最大长度(字节数) //SoftDevice提交的“Write”事件处理函数 static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) { //定义一个串口透传事件结构体变量,用于执行回调时传递参数 ble_nus_evt_t evt; //定义write事件结构体指针并指向GATT事件的write ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; //清空evt结构体 memset(&evt, 0, sizeof(ble_nus_evt_t)); //指向串口透传实例 evt.p_nus = p_nus; //设置连接句柄 evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; //写RX特征值 if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && (p_nus->data_handler != NULL)) { //设置事件类型 evt.type = BLE_NUS_EVT_RX_DATA; //设置数据 evt.params.rx_data.p_data = p_evt_write->data; //设置数据长度 evt.params.rx_data.length = p_evt_write->len; //执行回调 p_nus->data_handler(&evt); } else { // Do Nothing. This event is not relevant for this service. } } //SoftDevice提交的“BLE_GATTS_EVT_HVN_TX_COMPLETE”事件处理函数 static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) { //定义一个串口透传事件结构体变量evt,用于执行回调时传递参数 ble_nus_evt_t evt; //清零evt memset(&evt, 0, sizeof(ble_nus_evt_t)); //设置事件类型 evt.type = BLE_NUS_EVT_TX_RDY; //指向串口透传服务实例 evt.p_nus = p_nus; //设置连接句柄 evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; //执行回调 p_nus->data_handler(&evt); } //串口透传服务BLE事件监视者的事件回调函数 void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) { //检查参数是否有效 if ((p_context == NULL) || (p_ble_evt == NULL)) { return; } //定义一个串口透传结构体指针并指向串口透传结构体 ble_nus_t * p_nus = (ble_nus_t *)p_context; //判断事件类型 switch (p_ble_evt->header.evt_id) { //写事件 case BLE_GATTS_EVT_WRITE: on_write(p_nus, p_ble_evt); break; //TX就绪事件 case BLE_GATTS_EVT_HVN_TX_COMPLETE: on_hvx_tx_complete(p_nus, p_ble_evt); break; default: // No implementation needed. break; } } //初始化串口透传服务 uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { ret_code_t err_code; //定义16位UUID结构体变量 ble_uuid_t ble_uuid; //定义128位UUID结构体变量,并初始化为串口透传服务UUID基数 ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; //定义特征参数结构体变量 ble_add_char_params_t add_char_params; //检查指针是否为NULL VERIFY_PARAM_NOT_NULL(p_nus); VERIFY_PARAM_NOT_NULL(p_nus_init); //拷贝串口透传服务初始化结构体中的事件句柄 p_nus->data_handler = p_nus_init->data_handler; //将自定义UUID基数添加到SoftDevice err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); VERIFY_SUCCESS(err_code); //UUID类型和数值赋值给ble_uuid变量 ble_uuid.type = BLE_UUID_TYPE_BLE; ble_uuid.uuid = BLE_UUID_NUS_SERVICE; //添加串口透传服务 err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); VERIFY_SUCCESS(err_code); /*---------------------以下代码添加RX特征--------------------*/ //添加RX特征 //配置参数之前先清零add_char_params memset(&add_char_params, 0, sizeof(add_char_params)); //RX特征的UUID add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; //RX特征的UUID类型 add_char_params.uuid_type = p_nus->uuid_type; //设置RX特征值的最大长度 add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN; //设置RX特征值的初始长度 add_char_params.init_len = sizeof(uint8_t); //设置RX的特征值长度为可变长度 add_char_params.is_var_len = true; //设置RX特征的性质支持写 add_char_params.char_props.write = 1; //设置RX特性的性质支持读 add_char_params.char_props.read = 1; //设置RX特征的性质支持无响应写 add_char_params.char_props.write_wo_resp = 1; //设置读/写RX特征值的安全需求:无安全性 add_char_params.read_access = SEC_OPEN; add_char_params.write_access = SEC_OPEN; //为串口透传服务添加RX特征 err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); if (err_code != NRF_SUCCESS) { return err_code; } /*---------------------添加RX特征-END------------------------*/ /*---------------------以下代码添加TX特征--------------------*/ //添加TX特征 //配置参数之前先清零add_char_params memset(&add_char_params, 0, sizeof(add_char_params)); //TX特征的UUID add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; //TX特征的UUID类型 add_char_params.uuid_type = p_nus->uuid_type; //设置TX特征值的最大长度 add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN; //设置TX特征值的初始长度 add_char_params.init_len = sizeof(uint8_t); //设置TX的特征值长度为可变长度 add_char_params.is_var_len = true; //设置TX特征的性质:支持通知 add_char_params.char_props.notify = 1; //设置TX特性的性质:支持读 add_char_params.char_props.read = 1; //设置读/写RX特征值的安全需求:无安全性 add_char_params.read_access = SEC_OPEN; add_char_params.write_access = SEC_OPEN; add_char_params.cccd_write_access = SEC_OPEN; //为串口透传服务添加TX特征 return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); /*---------------------添加TX特征-END------------------------*/ } //蓝牙数据上传发送,并进行反馈 uint32_t ble_nus_data_send(ble_nus_t * p_nus, uint8_t * p_data, uint16_t * p_length, uint16_t conn_handle) { ble_gatts_hvx_params_t hvx_params; //验证p_uarts没有指向NULL VERIFY_PARAM_NOT_NULL(p_nus); //如果连接句柄无效,表示没有和主机建立连接,返回NRF_ERROR_NOT_FOUND if (conn_handle == BLE_CONN_HANDLE_INVALID) { return NRF_ERROR_NOT_FOUND; } if (*p_length > BLE_NUS_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } //设置之前先清零hvx_params memset(&hvx_params, 0, sizeof(hvx_params)); //TX特征值句柄 hvx_params.handle = p_nus->tx_handles.value_handle; //发送的数据 hvx_params.p_data = p_data; //发送的数据长度 hvx_params.p_len = p_length; //类型为通知 hvx_params.type = BLE_GATT_HVX_NOTIFICATION; //发送TX特征值通知 return sd_ble_gatts_hvx(conn_handle, &hvx_params); } #endif // NRF_MODULE_ENABLED(BLE_NUS)