Hello,
Hello,
Hi,
The s132 v3.x.0 softdevice should support up to 8 concurrent connections from a central to peripherals, but the driver/example you are using might not be configured to support this.
The latest release of pc-ble-driver (C\C++ version) support sd_api_v2, sd_api_v3, sd_api_v5, and sd_api_v6. Can you share your code you are using, and which versions of pc-ble-driver/connectivity firmware you are using?
Best regards,
Jørgen
Hi,
The s132 v3.x.0 softdevice should support up to 8 concurrent connections from a central to peripherals, but the driver/example you are using might not be configured to support this.
The latest release of pc-ble-driver (C\C++ version) support sd_api_v2, sd_api_v3, sd_api_v5, and sd_api_v6. Can you share your code you are using, and which versions of pc-ble-driver/connectivity firmware you are using?
Best regards,
Jørgen
Hi
I am using sd_api_3. I have 2 devices which I collect when receiving BLE_GAP_EVT_ADV_REPORT.
Then, I try to connect to both. The first one went well. It is connected, found its services, characteristics, descriptors, and then getting the data. Then, and only when I am getting the data, I tries to connect to the second one, and I get :
Connection Request Failed, reason 18 (NRF_ERROR_CONN_COUNT) .
I tried to change ble_enable_params.gap_enable_params.periph_conn_count = 1,
from 1 to 2.
But then for the sd_ble_enable(m_adapter, &ble_enable_params, app_ram_base)
I get again error 18.
Maybe after all sd_api_3 doesn't support multi devices ?
In addition, I also found out that if I do not call connect device the same thread of the Dispatch function it doesn't work. And that is true also fro one connection.
I#include "stdafx.h"
#include "BleManager.h"
#include "BleDevice.h"
using namespace Mudra::Ble::Windows::NordicExternal;
using namespace Mudra::Ble;
using namespace std;
using namespace Mudra::Computation;
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME)*1000) / (RESOLUTION))
#define MIN_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
#define MAX_CONNECTION_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
#define SLAVE_LATENCY 0
#define CONNECTION_SUPERVISION_TIMEOUT MSEC_TO_UNITS(20000, UNIT_10_MS)
adapter_t* m_adapter = NULL;
static uint16_t m_service_start_handle = 0;
static uint16_t m_service_end_handle = 0;
static uint16_t m_SNC_char_start_handle = 0;
static uint16_t m_IMU_char_start_handle = 0;
static uint16_t m_cccd_handle = 0;
static shared_ptr<Logger> m_logger;
std::map<HandleType, shared_ptr<BleDevice>> m_devices;
shared_ptr<BleDevice> m_connectedDevice;
std::vector<std::string> m_advDevices;
static Mudra::Ble::OnSncDataReadyCallbackType m_onSncDataReadyCallback = nullptr;
static Mudra::Ble::OnImuDataReadyCallbackType m_onImuDataReadyCallback = nullptr;
static Mudra::Ble::OnDeviceDiscoveredCallbackType m_onDeviceDiscoveredCallback = nullptr;
const unsigned STRING_BUFFER_SIZE = 50;
const int DEFAULT_BAUD_RATE = 1000000; /**< The baud rate to be used for serial communication with nRF5 device. */
const int GATT_MUDRA_SIZE = 247; /**< The baud rate to be used for serial communication with nRF5 device. */
const uint16_t SCAN_INTERVAL = 0x00A0; /**< Determines scan interval in units of 0.625 milliseconds. */
const uint16_t SCAN_WINDOW = 0x0050; /**< Determines scan window in units of 0.625 milliseconds. */
const uint16_t SCAN_TIMEOUT = 0x05; /**< Scan timeout between 0x01 and 0xFFFF in seconds, 0x0 disables timeout. */
const uint16_t MUDRA_DATA_SERVICE_UUID = 0xfff0;
const uint16_t SNC_CHARACT_UUID = 0xfff4;
const uint16_t IMU_CHARACT_UUID = 0xfff5;
const uint16_t BLE_UUID_CCCD = 0x2902;
const uint16_t BLE_CCCD_NOTIFY = 0x01;
const ble_gap_scan_params_t m_scanParam = {
0, // Set if active scanning.
0, // Set if selective scanning.
0, // Set adv_dir_report.
SCAN_INTERVAL,
SCAN_WINDOW,
SCAN_TIMEOUT
};
typedef struct
{
uint8_t* p_data; /**< Pointer to data. */
uint16_t data_len; /**< Length of data. */
} data_t;
enum {
UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */
UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */
UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */
};
enum State {
None,
SettingSncDescriprors,
SettingImuDescriprors,
};
State m_state = State::None;
static const ble_gap_conn_params_t m_connection_param = {
(uint16_t)MIN_CONNECTION_INTERVAL, (uint16_t)MAX_CONNECTION_INTERVAL, (uint16_t)SLAVE_LATENCY,
(uint16_t)CONNECTION_SUPERVISION_TIMEOUT };
static adapter_t* AdapterInit(const char* serial_port, uint32_t baud_rate);
static uint32_t StackInit();
static uint32_t OptionsSet();
static uint32_t ScanStart();
static void Dispatch(adapter_t* adapter, ble_evt_t* p_ble_evt);
static bool ServiceDiscoveryStart();
static void OnServiceDiscoveryResponse(const ble_gattc_evt_t* const p_ble_gattc_evt);
static uint32_t CharDiscoveryStart();
static void OnCharacteristicDiscoveryResponse(const ble_gattc_evt_t* const p_ble_gattc_evt);
static uint32_t DescrDiscoveryStart(uint16_t charStartHandle);
static void OnDescriptorDiscoveryResponse(const ble_gattc_evt_t* const p_ble_gattc_evt);
static uint32_t SetNotify(uint16_t handle);
static void ble_address_to_string_convert(ble_gap_addr_t address, char* string_buffer)
{
const int address_length = 6;
char temp_str[3];
for (int i = address_length - 1; i >= 0; --i)
{
sprintf(temp_str, "%02X", address.addr[i]);
strcat((char*)string_buffer, temp_str);
}
}
static uint32_t adv_report_parse(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->data_len)
{
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->data_len = field_length - 1;
return NRF_SUCCESS;
}
index += field_length + 1;
}
return NRF_ERROR_NOT_FOUND;
}
static bool find_adv_name(const ble_gap_evt_adv_report_t* p_adv_report, const char* name_to_find)
{
data_t adv_data;
data_t dev_name;
adv_data.p_data = (uint8_t*)p_adv_report->data;
adv_data.data_len = p_adv_report->dlen;
auto err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, &adv_data, &dev_name);
if (err_code == NRF_SUCCESS)
{
return (memcmp(name_to_find, dev_name.p_data, dev_name.data_len) == 0);
}
return false;
}
void OnAdvReport(const ble_gap_evt_t * const p_ble_gap_evt)
{
char str[STRING_BUFFER_SIZE] = { 0 };
// Log the Blue tooth device address of advertisement packet received.
ble_address_to_string_convert(p_ble_gap_evt->params.adv_report.peer_addr, str);
printf(".");
fflush(stdout);
if (strcmp(str, "CA62BA4C71E3") != 0 &&
strcmp(str, "CF6C069FC6D2") != 0)
{
return;
}
if (find_adv_name(&p_ble_gap_evt->params.adv_report, "WLD Mudra"))
{
bool found = std::find(m_advDevices.begin(), m_advDevices.end(), str) != m_advDevices.end();
if (!found)
{
m_advDevices.push_back(str);
auto d = make_shared<BleDevice>(&(p_ble_gap_evt->params.adv_report.peer_addr), std::string(str));
printf("\nReceived advertisement report with device address: 0x%s", str);
m_onDeviceDiscoveredCallback(d);
}
}
}
static void OnTimeout(const ble_gap_evt_t * const p_ble_gap_evt)
{
if (p_ble_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
{
m_connectedDevice = nullptr;
}
else if (p_ble_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_SCAN)
{
ScanStart();
}
}
static void OnConnected(const ble_gap_evt_t * const p_ble_gap_evt)
{
printf("\nConnection established\n");
fflush(stdout);
m_connectedDevice->SetConnectionHandle(p_ble_gap_evt->conn_handle);
m_devices[p_ble_gap_evt->conn_handle] = m_connectedDevice;
ServiceDiscoveryStart();
}
static bool ServiceDiscoveryStart()
{
uint32_t err_code;
uint16_t start_handle = 20;
ble_uuid_t srvc_uuid;
srvc_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN;
ble_uuid128_t srvc_128_uuid = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
err_code = sd_ble_uuid_vs_add(m_adapter, &srvc_128_uuid, &srvc_uuid.type);
if (err_code != NRF_SUCCESS)
{
printf("Failed to add the Mudra service.\n");
fflush(stdout);
return false;
}
printf("Discovering primary services\n");
fflush(stdout);
err_code =
sd_ble_gattc_primary_services_discover(m_adapter, m_connectedDevice->GetConnectionHandle(), start_handle, NULL);
return true;
}
static void OnServiceDiscoveryResponse(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
int count;
const ble_gattc_service_t* service;
printf("Received service discovery response\n");
fflush(stdout);
if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
{
printf("Service discovery failed. Error code 0x%X\n", p_ble_gattc_evt->gatt_status);
fflush(stdout);
return;
}
count = p_ble_gattc_evt->params.prim_srvc_disc_rsp.count;
if (count == 0)
{
printf("Service not found\n");
fflush(stdout);
return;
}
for (int service_index = 0; service_index < count; service_index++)
{
service = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp.services[service_index]);
if (service->uuid.uuid == MUDRA_DATA_SERVICE_UUID)
{
m_service_start_handle = service->handle_range.start_handle;
m_service_end_handle = service->handle_range.end_handle;
printf("Found Mudra data service start=0x%04X end=0x%04X\n", m_service_start_handle, m_service_end_handle);
fflush(stdout);
CharDiscoveryStart();
}
}
}
static uint32_t CharDiscoveryStart()
{
ble_gattc_handle_range_t handle_range;
printf("Discovering characteristics\n");
fflush(stdout);
handle_range.start_handle = m_service_start_handle;
handle_range.end_handle = m_service_end_handle;
return sd_ble_gattc_characteristics_discover(m_adapter, m_connectedDevice->GetConnectionHandle(), &handle_range);
}
static uint32_t DescrDiscoveryStart(uint16_t charStartHandle)
{
ble_gattc_handle_range_t handle_range;
printf("Discovering characteristic's descriptors 0x%04X - 0x%04X\n", charStartHandle,
charStartHandle + 2);
fflush(stdout);
if (charStartHandle == 0)
{
printf("No heart rate measurement characteristic handle found\n");
fflush(stdout);
return NRF_ERROR_INVALID_STATE;
}
handle_range.start_handle = charStartHandle;
handle_range.end_handle = charStartHandle + 2;
return sd_ble_gattc_descriptors_discover(m_adapter, m_connectedDevice->GetConnectionHandle(), &handle_range);
}
static void OnCharacteristicDiscoveryResponse(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
int count = p_ble_gattc_evt->params.char_disc_rsp.count;
if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
{
printf("Characteristic discovery failed. Error code 0x%X\n", p_ble_gattc_evt->gatt_status);
fflush(stdout);
return;
}
printf("Received characteristic discovery resp , characteristics count: %d\n", count);
fflush(stdout);
for (int i = 0; i < count; i++)
{
printf("Characteristic handle: 0x%04X, UUID: 0x%04X",
p_ble_gattc_evt->params.char_disc_rsp.chars[i].handle_decl,
p_ble_gattc_evt->params.char_disc_rsp.chars[i].uuid.uuid);
fflush(stdout);
switch (p_ble_gattc_evt->params.char_disc_rsp.chars[i].uuid.uuid)
{
case SNC_CHARACT_UUID:
printf(" SNC char");
fflush(stdout);
m_state = SettingSncDescriprors;
m_SNC_char_start_handle = p_ble_gattc_evt->params.char_disc_rsp.chars[i].handle_decl;
break;
case IMU_CHARACT_UUID:
printf(" IMU char");
fflush(stdout);
m_IMU_char_start_handle = p_ble_gattc_evt->params.char_disc_rsp.chars[i].handle_decl;
break;
}
printf("\n");
fflush(stdout);
}
DescrDiscoveryStart(m_SNC_char_start_handle);
}
static void OnDescriptorDiscoveryResponse(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
int count = p_ble_gattc_evt->params.desc_disc_rsp.count;
if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
{
printf("Descriptor discovery failed. Error code 0x%X\n", p_ble_gattc_evt->gatt_status);
fflush(stdout);
return;
}
printf("Received descriptor discovery response, descriptor count: %d\n", count);
fflush(stdout);
for (int i = 0; i < count; i++)
{
printf("Descriptor handle: 0x%04X, UUID: 0x%04X\n",
p_ble_gattc_evt->params.desc_disc_rsp.descs[i].handle,
p_ble_gattc_evt->params.desc_disc_rsp.descs[i].uuid.uuid);
fflush(stdout);
if (p_ble_gattc_evt->params.desc_disc_rsp.descs[i].uuid.uuid == BLE_UUID_CCCD)
{
m_cccd_handle = p_ble_gattc_evt->params.desc_disc_rsp.descs[i].handle;
printf("Set notify to 0x%04X\n", m_cccd_handle);
fflush(stdout);
SetNotify(m_cccd_handle);
}
}
}
static uint32_t SetNotify(uint16_t handle)
{
uint8_t value = 0;
value ^= BLE_CCCD_NOTIFY;
ble_gattc_write_params_t write_params;
uint8_t cccd_value[2] = { value, 0 };
printf("Setting notify CCCD\n");
fflush(stdout);
if (m_cccd_handle == 0)
{
printf("Error. No CCCD handle has been found\n");
fflush(stdout);
return NRF_ERROR_INVALID_STATE;
}
write_params.handle = handle;
write_params.len = 2;
write_params.p_value = cccd_value;
write_params.write_op = BLE_GATT_OP_WRITE_REQ;
write_params.offset = 0;
return sd_ble_gattc_write(m_adapter, m_connectedDevice->GetConnectionHandle(), &write_params);
}
static void on_write_response(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
printf("Received write response 0x%04X\n", p_ble_gattc_evt->params.write_rsp.handle);
fflush(stdout);
if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
{
printf("Error. Write operation failed. Error code 0x%X\n", p_ble_gattc_evt->gatt_status);
fflush(stdout);
}
switch (m_state)
{
case State::SettingSncDescriprors:
m_state = SettingImuDescriprors;
DescrDiscoveryStart(m_IMU_char_start_handle);
break;
case State::SettingImuDescriprors:
m_state = State::None;
m_connectedDevice = nullptr;
break;
}
}
enum class DataType
{
None,
SncRecieved,
ImuRecieved
};
static void on_hvx(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
auto& handle = p_ble_gattc_evt->params.hvx.handle;
auto& connectionHandle = p_ble_gattc_evt->conn_handle;
DataType dataType = DataType::None;
BufferType buffer;
// printf("0x%04X ", p_ble_gattc_evt->params.hvx.handle);
if (handle >= m_SNC_char_start_handle && handle <= m_SNC_char_start_handle + 2) // Heart rate measurement.
{
// DebugMessage(m_logger) << "\nReceived SNC data, size=" << p_ble_gattc_evt->params.hvx.len;
dataType = DataType::SncRecieved;
}
else if (handle >= m_IMU_char_start_handle && handle <= m_IMU_char_start_handle + 2) // Heart rate measurement.
{
// DebugMessage(m_logger) << "\nReceived IMU data, size=" << p_ble_gattc_evt->params.hvx.len;
dataType = DataType::ImuRecieved;
}
if (dataType != DataType::None)
{
buffer.reserve(p_ble_gattc_evt->params.hvx.len);
for (int i = 0; i < p_ble_gattc_evt->params.hvx.len; i++)
{
buffer.push_back(p_ble_gattc_evt->params.hvx.data[i]);
//
}
if (dataType == DataType::SncRecieved && m_onSncDataReadyCallback)
{
m_onSncDataReadyCallback(m_devices[connectionHandle], buffer);
}
else if (dataType == DataType::ImuRecieved && m_onImuDataReadyCallback)
{
m_onImuDataReadyCallback(m_devices[connectionHandle], buffer);
}
// We know the heart rate reading is encoded as 2 bytes [flag, value].
}
else // Unknown data.
{
printf("Un-parsed data received on handle: %04X\n", handle);
}
fflush(stdout);
}
static void on_exchange_mtu_request(const ble_gatts_evt_t * const p_ble_gatts_evt)
{
printf("on_exchange_mtu_request\n");
fflush(stdout);
uint32_t err_code = sd_ble_gatts_exchange_mtu_reply(m_adapter, m_connectedDevice->GetConnectionHandle(), GATT_MUDRA_SIZE);
if (err_code != NRF_SUCCESS)
{
printf("MTU exchange request reply failed, err_code %d\n", err_code);
fflush(stdout);
}
}
static void Dispatch(adapter_t * adapter, ble_evt_t * p_ble_evt)
{
if (p_ble_evt == NULL)
{
printf("Received an empty BLE event\n");
fflush(stdout);
return;
}
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
OnConnected(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_DISCONNECTED:
printf("Disconnected, reason: 0x%02X\n", p_ble_evt->evt.gap_evt.params.disconnected.reason);
fflush(stdout);
// m_connected_devices--;
// m_connection_handle = 0;
break;
case BLE_GAP_EVT_ADV_REPORT:
OnAdvReport(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_TIMEOUT:
OnTimeout(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
OnServiceDiscoveryResponse(&(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_CHAR_DISC_RSP:
OnCharacteristicDiscoveryResponse(&(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_DESC_DISC_RSP:
OnDescriptorDiscoveryResponse(&(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_WRITE_RSP:
on_write_response(&(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_HVX:
on_hvx(&(p_ble_evt->evt.gattc_evt));
break;
case BLE_GAP_EVT_SEC_REQUEST:
// on_conn_params_update_request(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
// on_conn_params_update_request(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
on_exchange_mtu_request(&(p_ble_evt->evt.gatts_evt));
break;
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
// on_exchange_mtu_response(&(p_ble_evt->evt.gattc_evt));
break;
default:
printf("Received an un-handled event with ID: %d\n", p_ble_evt->header.evt_id);
fflush(stdout);
break;
}
}
/**@brief Function for handling error message events from sd_rpc.
*
* @param[in] adapter The transport adapter.
* @param[in] code Error code that the error message is associated with.
* @param[in] message The error message that the callback is associated with.
*/
static void status_handler(adapter_t * adapter, sd_rpc_app_status_t code, const char* message)
{
printf("Status: %d, message: %s\n", (uint32_t)code, message);
fflush(stdout);
}
/**@brief Function for handling the log message events from sd_rpc.
*
* @param[in] adapter The transport adapter.
* @param[in] severity Level of severity that the log message is associated with.
* @param[in] message The log message that the callback is associated with.
*/
static void log_handler(adapter_t * adapter, sd_rpc_log_severity_t severity, const char* message)
{
switch (severity)
{
case SD_RPC_LOG_ERROR:
printf("Error: %s\n", message);
fflush(stdout);
break;
case SD_RPC_LOG_WARNING:
printf("Warning: %s\n", message);
fflush(stdout);
break;
case SD_RPC_LOG_INFO:
printf("Info: %s\n", message);
fflush(stdout);
break;
default:
printf("Log: %s\n", message);
fflush(stdout);
break;
}
}
bool scan(const std::string & port)
{
const char* s = port.c_str();
m_adapter = AdapterInit(s, DEFAULT_BAUD_RATE);
sd_rpc_log_handler_severity_filter_set(m_adapter, SD_RPC_LOG_INFO);
auto error_code = sd_rpc_open(m_adapter, status_handler, Dispatch, log_handler);
if (error_code != NRF_SUCCESS)
{
printf("Failed to open nRF BLE Driver. Error code: 0x%02X\n", error_code);
fflush(stdout);
return error_code;
}
error_code = StackInit();
if (error_code != NRF_SUCCESS)
{
return error_code;
}
error_code = OptionsSet();
if (error_code != NRF_SUCCESS)
{
return error_code;
}
error_code = ScanStart();
if (error_code != NRF_SUCCESS)
{
return error_code;
}
return true;
}
bool connect(std::shared_ptr<IBleDevice> device)
{
if (m_connectedDevice != nullptr)
{
return false;
}
m_connectedDevice = dynamic_pointer_cast<BleDevice>(device);
auto err_code = sd_ble_gap_connect(m_adapter, m_connectedDevice->GetAddress(), &m_scanParam, &m_connection_param);
if (err_code != NRF_SUCCESS)
{
printf("\nConnection Request Failed, device %s reason %d", device->GetName().c_str(), err_code);
fflush(stdout);
return false;
}
printf("\nConnection Request Succeeded, device %s\n", device->GetName().c_str());
fflush(stdout);
return true;
}
adapter_t* AdapterInit(const char* serial_port, uint32_t baud_rate)
{
physical_layer_t* phy;
data_link_layer_t* data_link_layer;
transport_layer_t* transport_layer;
phy = sd_rpc_physical_layer_create_uart(serial_port, baud_rate, SD_RPC_FLOW_CONTROL_NONE, SD_RPC_PARITY_NONE);
data_link_layer = sd_rpc_data_link_layer_create_bt_three_wire(phy, 100);
transport_layer = sd_rpc_transport_layer_create(data_link_layer, 100);
return sd_rpc_adapter_create(transport_layer);
}
uint32_t StackInit()
{
uint32_t err_code;
uint32_t* app_ram_base = NULL;
ble_enable_params_t ble_enable_params;
memset(&ble_enable_params, 0, sizeof(ble_enable_params));
ble_enable_params.gatt_enable_params.att_mtu = GATT_MUDRA_SIZE;
ble_enable_params.gap_enable_params.periph_conn_count = 2;
ble_enable_params.gap_enable_params.central_conn_count = 1;
ble_enable_params.gap_enable_params.central_sec_count = 1;
err_code = sd_ble_enable(m_adapter, &ble_enable_params, app_ram_base);
switch (err_code)
{
case NRF_SUCCESS:
break;
case NRF_ERROR_INVALID_STATE:
printf("BLE stack already enabled\n");
fflush(stdout);
break;
default:
printf("Failed to enable BLE stack. Error code: %d\n", err_code);
fflush(stdout);
break;
}
return err_code;
}
uint32_t OptionsSet()
{
ble_opt_t opt;
ble_common_opt_t common_opt;
common_opt.conn_bw.role = BLE_GAP_ROLE_CENTRAL;
common_opt.conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
common_opt.conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
opt.common_opt = common_opt;
return sd_ble_opt_set(m_adapter, BLE_COMMON_OPT_CONN_BW, &opt);
}
uint32_t ScanStart()
{
uint32_t error_code = sd_ble_gap_scan_start(m_adapter, &m_scanParam);
if (error_code != NRF_SUCCESS)
{
printf("\nScan start failed with error code: %d", error_code);
fflush(stdout);
}
else
{
printf("\nScan started");
fflush(stdout);
}
return error_code;
}
BleManager::BleManager(shared_ptr<Logger> logger)
{
m_logger = logger;
}
bool BleManager::Scan(const std::string & serialPort)
{
return scan(serialPort);
}
bool BleManager::Connect(std::shared_ptr<IBleDevice> device)
{
return connect(device);
}
BleManager::~BleManager()
{
}
void BleManager::SetOnDeviceDiscoveredCallback(OnDeviceDiscoveredCallbackType callback) { m_onDeviceDiscoveredCallback = callback; }
void BleManager::SetOnSncDataReadyCallback(OnSncDataReadyCallbackType callback) { m_onSncDataReadyCallback = callback; }
void BleManager::SetOnImuDataReadyCallback(OnImuDataReadyCallbackType callback) { m_onImuDataReadyCallback = callback; };
Best regards
Liav Adi
You need to increase central_conn_count, periph_conn_count configures how many connections as a peripheral the softdevice can support. I sd_api_v3 this is limited to 1.