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;
}
}