I am attempting to write to multiple CCCD handles in a service as a central with no luck. I need to write to one CCCD handle to enable notifications and another handle (BLE_UUID_UPDATE_CHARACTERISTIC) to determine the notification frequency, but I am only able to enable notifications. I have been using the ble_nus_c service as a starting point. The services look like this:
In nRF Connect I am able to enable notifications by writing 0x01 to the 0xFF60 characteristic. I can then set the frequency to 5 seconds by writing 0x05 to the 0xFDA0 characteristic. This does not work in my code.
First, I discover my characteristics:
void ble_nus_c_on_db_disc_evt(ble_nus_c_t * p_ble_nus_c, ble_db_discovery_evt_t * p_evt)
{
ble_nus_c_evt_t nus_c_evt;
memset(&nus_c_evt,0,sizeof(ble_nus_c_evt_t));
ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;
// Check if the NUS was discovered.
if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE &&
p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE &&
p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->uuid_type)
{
uint32_t i;
for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
{
switch (p_chars[i].characteristic.uuid.uuid)
{
case BLE_UUID_NUS_TX_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_handle = p_chars[i].characteristic.handle_value;
break;
case BLE_UUID_UPDATE_CHARACTERISTIC:
nus_c_evt.handles.nus_update_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_update_cccd_handle = p_chars[i].cccd_handle;
break;
case BLE_UUID_NUS_RX_CHARACTERISTIC:
nus_c_evt.handles.nus_rx_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_rx_cccd_handle = p_chars[i].cccd_handle;
break;
default:
break;
}
}
if (p_ble_nus_c->evt_handler != NULL)
{
nus_c_evt.conn_handle = p_evt->conn_handle;
nus_c_evt.evt_type = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
}
}
}
I then enable notifications for the RX_CHARACTERISTIC in my main program, and attempt to set my update frequency when an HVC event is received:
void ble_nus_c_on_ble_evt(ble_nus_c_t * p_ble_nus_c, const ble_evt_t * p_ble_evt)
{
if ((p_ble_nus_c == NULL) || (p_ble_evt == NULL))
{
return;
}
if ( (p_ble_nus_c->conn_handle != BLE_CONN_HANDLE_INVALID)
&&(p_ble_nus_c->conn_handle != p_ble_evt->evt.gap_evt.conn_handle))
{
return;
}
switch (p_ble_evt->header.evt_id)
{
case BLE_GATTC_EVT_HVX:
on_hvx(p_ble_nus_c, p_ble_evt);
break;
case BLE_GATTS_EVT_HVC:
ble_nus_c_update_configure(p_ble_nus_c);
break;
case BLE_GAP_EVT_DISCONNECTED:
if (p_ble_evt->evt.gap_evt.conn_handle == p_ble_nus_c->conn_handle
&& p_ble_nus_c->evt_handler != NULL)
{
ble_nus_c_evt_t nus_c_evt;
nus_c_evt.evt_type = BLE_NUS_C_EVT_DISCONNECTED;
p_ble_nus_c->conn_handle = BLE_CONN_HANDLE_INVALID;
p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
}
break;
}
}
where ble_nus_c_update_configure looks like this:
static uint32_t cccd_configure_value(uint16_t conn_handle, uint16_t cccd_handle)
{
uint8_t buf[BLE_CCCD_VALUE_LEN];
buf[0] = 0x05; // send notification ever 5 seconds
buf[1] = 0x00;
const ble_gattc_write_params_t write_params = {
.write_op = BLE_GATT_OP_WRITE_REQ,
.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
.handle = cccd_handle,
.offset = 0,
.len = sizeof(buf),
.p_value = buf
};
return sd_ble_gattc_write(conn_handle, &write_params);
}
where the proper cccd handle is passed in through a quick handler function. This method hasn't been working for me tho. Where am I going wrong?
Thanks!