I try to modify one of the pc-ble-driver examples to work together with my PCA10040 and the Nordic UART Service example in my Qt application, but the application doesn´t discover two characteristics and receive an event with the ID 0x23 and 0x12:
Open softdevice... Log: 2 - Successfully opened COM5. Baud rate: 1000000. Flow control: none. Parity: none. Status: 6 - Target Reset performed Status: 7 - Connection active Enable softdevice... Start scanning... Scan started Received advertisement report with device address: 0x453e4ff9a8 Connection established Discovering primary service Received an unhandled event with ID: 0x 23 Received service discovery response Found 1 services Discovered service with UUID: 0x 1 , start handle: 0x ffff , end handle: 0x ffff Discovering characteristics Received characteristic discovery response, characteristics count: 1 Characteristic handle: 0x c , UUID: 0x 2 Discovering characteristic's descriptors No characteristic handle found Received an unhandled event with ID: 0x 12 Disconnected, reason: 0x 22
How do I have to modify the code to use both characteristics of the service?
#include "qt_ble.h" #define BLE_UUID_CCCD 0x2902 #define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) #define BLE_UUID_NUS_SERVICE 0x0001 #define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} //static uint32_t _mDeviceServiceUUID = 0; static uint32_t _mDeviceCharUUID = 0; static uint32_t _mErrorCode = 0; static uint32_t _mConfigID = 0; static uint16_t _mCCCDHandle = 0; static uint16_t _mCharHandle = 0; static uint16_t _mConnectionHandle = 0; static uint16_t _mServiceStartHandle = 0; static uint16_t _mServiceEndHandle = 0; static uint8_t _mConnectedDevices = 0; static bool _mConnectionInProgress; static ble_uuid_t UUID; static ble_cfg_t _mBLE_Config; static adapter_t* _mAdapter; static physical_layer_t* _mPhy; static data_link_layer_t* _mData_link_layer; static transport_layer_t* _mTransport_layer; static const ble_gap_scan_params_t Scan_Params = { 0, // Set if active scanning. 0, // Set if selective scanning. 0, (uint16_t)0x00A0, (uint16_t)0x0050, (uint16_t)0x00 }; static const ble_gap_conn_params_t Connection_Params = { (uint16_t)MSEC_TO_UNITS(7.5, 1250), (uint16_t)MSEC_TO_UNITS(7.5, 1250), (uint16_t)0, (uint16_t)MSEC_TO_UNITS(4000, 10000) }; uint32_t Qt_BLE::Open(QString Port, uint32_t ServiceUUID, uint32_t CharacteristicUUID) { const uint32_t RAM_Start = 0; uint32_t* App_RAM_Base = NULL; /* _mDeviceServiceUUID = ServiceUUID; _mDeviceCharUUID = CharacteristicUUID;*/ _mConfigID = 1; _mConnectedDevices = 0; _mConnectionHandle = 0; _mConnectionInProgress = false; _mPhy = sd_rpc_physical_layer_create_uart(Port.toLocal8Bit().data(), 1000000, SD_RPC_FLOW_CONTROL_NONE, SD_RPC_PARITY_NONE); _mData_link_layer = sd_rpc_data_link_layer_create_bt_three_wire(_mPhy, 250); _mTransport_layer = sd_rpc_transport_layer_create(_mData_link_layer, 1500); _mAdapter = sd_rpc_adapter_create(_mTransport_layer); sd_rpc_log_handler_severity_filter_set(_mAdapter, SD_RPC_LOG_INFO); DEBUG << "Open softdevice..."; _mErrorCode = sd_rpc_open(_mAdapter, Qt_BLE::StatusHandler, Qt_BLE::on_Event, Qt_BLE::LogHandler); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Failed to open nRF BLE Driver. Error code: 0x" << hex << _mErrorCode; } _mBLE_Config.gap_cfg.role_count_cfg.periph_role_count = 0; _mBLE_Config.gap_cfg.role_count_cfg.central_role_count = 1; _mBLE_Config.gap_cfg.role_count_cfg.central_sec_count = 0; _mErrorCode = sd_ble_cfg_set(_mAdapter, BLE_GAP_CFG_ROLE_COUNT, &_mBLE_Config, RAM_Start); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "sd_ble_cfg_set() failed when attempting to set BLE_GAP_CFG_ROLE_COUNT. Error code: 0x" << hex << _mErrorCode; } memset(&_mBLE_Config, 0x00, sizeof(ble_cfg_t)); _mBLE_Config.conn_cfg.conn_cfg_tag = _mConfigID; _mBLE_Config.conn_cfg.params.gatt_conn_cfg.att_mtu = 150; _mErrorCode = sd_ble_cfg_set(_mAdapter, BLE_CONN_CFG_GATT, &_mBLE_Config, RAM_Start); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "sd_ble_cfg_set() failed when attempting to set BLE_CONN_CFG_GATT. Error code: 0x" << hex << _mErrorCode; } DEBUG << "Enable softdevice..."; _mErrorCode = sd_ble_enable(_mAdapter, App_RAM_Base); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Failed to enable nRF BLE Driver. Error code: 0x" << hex << _mErrorCode; } return _mErrorCode; } uint32_t Qt_BLE::StartScan(void) { DEBUG << "Start scanning..."; _mErrorCode = sd_ble_gap_scan_start(_mAdapter, &Scan_Params); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Scan start failed with error code: 0x" << hex << _mErrorCode; } else { DEBUG << "Scan started"; } return _mErrorCode; } uint32_t Qt_BLE::Close(void) { return sd_rpc_close(_mAdapter); } void Qt_BLE::StatusHandler(adapter_t* p_Adapter, sd_rpc_app_status_t Code, const char* p_Message) { DEBUG << "Status: " << Code << "-" << p_Message; } void Qt_BLE::LogHandler(adapter_t* p_Adapter, sd_rpc_log_severity_t Severity, const char* p_Message) { DEBUG << "Log: " << Severity << "-" << p_Message; } void Qt_BLE::AddressToString(ble_gap_addr_t Address, rsize_t Size, uint8_t* p_Buffer) { char Temp[3]; for(int i = 5; i >= 0; --i) { sprintf(Temp, "%02X", Address.addr[i]); strcat_s((char*)p_Buffer, Size, Temp); } } bool Qt_BLE::Find_Adv_Name(const ble_gap_evt_adv_report_t* p_Adv_Report, const char* p_Name) { uint32_t ErrorCode; data_t adv_data; data_t dev_name; adv_data.p_Data = (uint8_t*)p_Adv_Report->data; adv_data.Length = p_Adv_Report->dlen; // Search for advertising names ErrorCode = Parse_Adv_Report(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, &adv_data, &dev_name); if(ErrorCode == NRF_SUCCESS) { if(memcmp(p_Name, dev_name.p_Data, dev_name.Length) == 0) { return true; } } else { // Look for the short local name if it was not found as complete ErrorCode = Parse_Adv_Report(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, &adv_data, &dev_name); if(ErrorCode != NRF_SUCCESS) { return false; } if(memcmp(p_Name, dev_name.p_Data, dev_name.Length) == 0) { return true; } } return false; } uint32_t Qt_BLE::Parse_Adv_Report(uint8_t type, data_t* p_AdvData, data_t* p_TypeData) { uint32_t Index = 0; uint8_t* p_Data; p_Data = p_AdvData->p_Data; while(Index < p_AdvData->Length) { uint8_t field_length = p_Data[Index]; uint8_t field_type = p_Data[Index + 1]; if(field_type == type) { p_TypeData->p_Data = &p_Data[Index + 2]; p_TypeData->Length = field_length - 1; return NRF_SUCCESS; } Index += field_length + 1; } return NRF_ERROR_NOT_FOUND; } uint32_t Qt_BLE::Start_ServiceDiscovery(adapter_t* p_Adapter) { uint16_t Start_Handle = 0x01; DEBUG << "Discovering primary service"; ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; _mErrorCode = sd_ble_uuid_vs_add(p_Adapter, &nus_base_uuid, &UUID.type); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Failed to get UUID with error code: 0x" << hex << _mErrorCode; } UUID.uuid = BLE_UUID_NUS_SERVICE; // Initiate procedure to find the primary BLE_UUID_HEART_RATE_SERVICE. _mErrorCode = sd_ble_gattc_primary_services_discover(p_Adapter, _mConnectionHandle, Start_Handle, &UUID); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Failed to initiate or continue a GATT Primary Service Discovery procedure with error code: 0x" << hex << _mErrorCode; } return _mErrorCode; } void Qt_BLE::on_Event(adapter_t* p_Adapter, ble_evt_t* p_Event) { switch(p_Event->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { Qt_BLE::on_Connected(p_Adapter, &(p_Event->evt.gap_evt)); break; } case BLE_GAP_EVT_DISCONNECTED: { DEBUG << "Disconnected, reason: 0x" << hex << p_Event->evt.gap_evt.params.disconnected.reason; _mConnectedDevices--; _mConnectionHandle = 0; break; } case BLE_GAP_EVT_ADV_REPORT: { Qt_BLE::on_Adv_Report(p_Adapter, &(p_Event->evt.gap_evt)); break; } case BLE_GAP_EVT_TIMEOUT: { Qt_BLE::on_Timeout(&(p_Event->evt.gap_evt)); break; } case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: { on_Service_Discovery_Response(&(p_Event->evt.gattc_evt)); break; } case BLE_GATTC_EVT_CHAR_DISC_RSP: { on_Characteristic_Discovery_Response(&(p_Event->evt.gattc_evt)); break; } case BLE_GATTC_EVT_DESC_DISC_RSP: { on_Descriptor_Discovery_Response(&(p_Event->evt.gattc_evt)); break; } case BLE_GATTC_EVT_WRITE_RSP: { on_Write_Response(&(p_Event->evt.gattc_evt)); break; } case BLE_GATTC_EVT_HVX: { DEBUG << "BLE_GATTC_EVT_HVX"; //on_hvx(&(p_ble_evt->evt.gattc_evt)); break; } case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { on_Conn_Params_Update_Request(&(p_Event->evt.gap_evt)); break; } case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: { on_Exchange_MTU_Request(&(p_Event->evt.gatts_evt)); break; } case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: { DEBUG << "BLE_GATTC_EVT_EXCHANGE_MTU_RSP"; //on_exchange_mtu_response(&(p_ble_evt->evt.gattc_evt)); break; } default: { DEBUG << "Received an unhandled event with ID: 0x" << hex << p_Event->header.evt_id; break; } } } void Qt_BLE::on_Adv_Report(adapter_t* p_Adapter, const ble_gap_evt_t* const p_Event) { uint32_t ErrorCode; uint8_t Buffer[50] = {0}; AddressToString(p_Event->params.adv_report.peer_addr, sizeof(Buffer), Buffer); DEBUG << "Received advertisement report with device address: " << Buffer; if(Find_Adv_Name(&p_Event->params.adv_report, "Nordic_UART")) { ErrorCode = sd_ble_gap_connect(p_Adapter, &(p_Event->params.adv_report.peer_addr), &Scan_Params, &Connection_Params, _mConfigID); if(ErrorCode != NRF_SUCCESS) { DEBUG << "Connection Request Failed, reason %d\n" << ErrorCode; return; } } } void Qt_BLE::on_Connected(adapter_t* p_Adapter, const ble_gap_evt_t* const p_Event) { DEBUG << "Connection established"; _mConnectedDevices++; _mConnectionHandle = p_Event->conn_handle; _mConnectionInProgress = false; Start_ServiceDiscovery(p_Adapter); } void Qt_BLE::on_Timeout(const ble_gap_evt_t* const p_Event) { if(p_Event->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN) { _mConnectionInProgress = false; } else if(p_Event->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN) { StartScan(); } } void Qt_BLE::on_Service_Discovery_Response(const ble_gattc_evt_t* const p_Event) { uint32_t ServiceIndex; const ble_gattc_service_t* Service; ble_gattc_handle_range_t HandleRange; DEBUG << "Received service discovery response"; if(p_Event->gatt_status != NRF_SUCCESS) { DEBUG << "Service discovery failed. Error code 0x" << hex << p_Event->gatt_status; return; } if(p_Event->params.prim_srvc_disc_rsp.count == 0) { DEBUG << "Service not found"; } else { DEBUG << "Found " << p_Event->params.prim_srvc_disc_rsp.count << " services"; } ServiceIndex = 0; /* We expect to discover only the Heart Rate service as requested. */ Service = &(p_Event->params.prim_srvc_disc_rsp.services[ServiceIndex]); if(Service->uuid.uuid != UUID.uuid) { DEBUG << "Unknown service discovered with UUID: 0x" << hex << Service->uuid.uuid; return; } _mServiceStartHandle = Service->handle_range.start_handle; _mServiceEndHandle = Service->handle_range.end_handle; DEBUG << "Discovered service with UUID: 0x" << hex << Service->uuid.uuid << ", start handle: 0x" << hex << _mServiceEndHandle << ", end handle: 0x" << hex << _mServiceEndHandle; DEBUG << "Discovering characteristics"; HandleRange.start_handle = _mServiceStartHandle; HandleRange.end_handle = _mServiceEndHandle; _mErrorCode = sd_ble_gattc_characteristics_discover(_mAdapter, _mConnectionHandle, &HandleRange); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "sd_ble_gattc_characteristics_discover() failed, reason: " << hex << _mErrorCode; return; } } void Qt_BLE::on_Characteristic_Discovery_Response(const ble_gattc_evt_t* const p_Event) { ble_gattc_handle_range_t HandleRange; if(p_Event->gatt_status != NRF_SUCCESS) { DEBUG << "Characteristic discovery failed. Error code 0x" << p_Event->gatt_status; return; } DEBUG << "Received characteristic discovery response, characteristics count: " << p_Event->params.char_disc_rsp.count; for(int i = 0; i < p_Event->params.char_disc_rsp.count; i++) { DEBUG << "Characteristic handle: 0x" << hex <<p_Event->params.char_disc_rsp.chars[i].handle_decl << ", UUID: 0x" << hex << p_Event->params.char_disc_rsp.chars[i].uuid.uuid; if(p_Event->params.char_disc_rsp.chars[i].uuid.uuid == _mDeviceCharUUID) { _mCharHandle = p_Event->params.char_disc_rsp.chars[i].handle_decl; } } DEBUG << "Discovering characteristic's descriptors"; if(_mCharHandle == 0) { DEBUG << "No characteristic handle found"; return; } HandleRange.start_handle = _mCharHandle; HandleRange.end_handle = _mServiceEndHandle; _mErrorCode = sd_ble_gattc_descriptors_discover(_mAdapter, _mConnectionHandle, &HandleRange); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "sd_ble_gattc_descriptors_discover() failed, reason: " << hex << _mErrorCode; } } void Qt_BLE::on_Descriptor_Discovery_Response(const ble_gattc_evt_t* const p_Event) { if(p_Event->gatt_status != NRF_SUCCESS) { DEBUG << "Descriptor discovery failed. Error code 0x" << hex << p_Event->gatt_status; } DEBUG << "Received descriptor discovery response, descriptor count: " << p_Event->params.desc_disc_rsp.count; for(int i = 0; i < p_Event->params.desc_disc_rsp.count; i++) { DEBUG << "Descriptor handle: 0x" << hex << p_Event->params.desc_disc_rsp.descs[i].handle << ", UUID: 0x" << hex << p_Event->params.desc_disc_rsp.descs[i].uuid.uuid; if(p_Event->params.desc_disc_rsp.descs[i].uuid.uuid == BLE_UUID_CCCD) { _mCCCDHandle = p_Event->params.desc_disc_rsp.descs[i].handle; ble_gattc_write_params_t write_params; uint8_t cccd_value[2] = {0x01, 0}; DEBUG << "Setting HRM CCCD"; if(_mCCCDHandle == 0) { DEBUG << "Error. No CCCD handle has been found"; } write_params.handle = _mCCCDHandle; write_params.len = 2; write_params.p_value = cccd_value; write_params.write_op = BLE_GATT_OP_WRITE_REQ; write_params.offset = 0; sd_ble_gattc_write(_mAdapter, _mConnectionHandle, &write_params); } } } void Qt_BLE::on_Write_Response(const ble_gattc_evt_t* const p_Event) { DEBUG << "Received write response."; if(p_Event->gatt_status != NRF_SUCCESS) { DEBUG << "Error. Write operation failed. Error code: 0x" << hex << p_Event->gatt_status; } } void Qt_BLE::on_Conn_Params_Update_Request(const ble_gap_evt_t* const p_Event) { _mErrorCode = sd_ble_gap_conn_param_update(_mAdapter, _mConnectionHandle, &(p_Event->params.conn_param_update_request.conn_params)); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "Conn params update failed, Error code: " << hex << _mErrorCode; } } void Qt_BLE::on_Exchange_MTU_Request(const ble_gatts_evt_t* const) { _mErrorCode = sd_ble_gatts_exchange_mtu_reply(_mAdapter, _mConnectionHandle, BLE_GATT_ATT_MTU_DEFAULT); if(_mErrorCode != NRF_SUCCESS) { DEBUG << "MTU exchange request reply failed, err_code: 0x" << hex << _mErrorCode; } }