Hello Nordic Team,
For my application, I am using two nRF54L15 chips with one configured as a master and the other a slave. For the remainder of this post, I will be discussing my Bluetooth Master code. I setup the discovery process to search through all characteristics of the slave device and subscribe to the characteristics that I want notifying.
static struct bt_gatt_subscribe_params notifyStruct[NUM_OF_NOTIFY_CHARS] = {0};
// For initially subscribing to a notification
static void collectNotifyHandle(struct bt_conn *conn, const struct bt_gatt_attr *attr) {
int err;
//volatile struct bt_gatt_attr* attrTemp = attr;
printk(" - - Descriptor Discovered. Val = 0x%x, Handle = %d\n", BT_UUID_16(attr->uuid)->val, attr->handle);
// Check if Next Notify Characteristic is Set
switch(nextNotifyChar) {
//// Femur Sensor Notifies
case NOTIFY_FS_STATUS:
notifyStruct[NOTIFY_FS_STATUS].notify = notifyFSStatusCb;
break;
case NOTIFY_FS_QUAT:
notifyStruct[NOTIFY_FS_QUAT].notify = notifyFSQuatCb;
break;
case NOTIFY_FS_LOG:
notifyStruct[NOTIFY_FS_LOG].notify = notifyFSLogCb;
break;
case NOTIFY_FS_RAW:
notifyStruct[NOTIFY_FS_RAW].notify = notifyFSRawCb;
break;
//// Glasses Notifies
case NOTIFY_GL_VALUE:
notifyStruct[NOTIFY_GL_VALUE].notify = notifyGLValueCb;
break;
//// Tablet Notifies
case NOTIFY_TB_CMD:
notifyStruct[NOTIFY_TB_CMD].notify = notifyTBCmdCb;
break;
case NOTIFY_FWU_INFO:
notifyStruct[NOTIFY_FWU_INFO].notify = notifyFWUInfoCb;
break;
case NOTIFY_FWU_DATA:
notifyStruct[NOTIFY_FWU_DATA].notify = notifyFWUDataCb;
break;
case NUM_OF_NOTIFY_CHARS:
default:
// Do Nothing
break;
}
// If Next Notify Characteristic is Set, Grab Generic Subscribe Data
if (nextNotifyChar < NUM_OF_NOTIFY_CHARS) {
notifyStruct[nextNotifyChar].value = BT_GATT_CCC_NOTIFY;
if (attr->uuid->type == BT_UUID_TYPE_128){
notifyStruct[nextNotifyChar].ccc_handle = attr->handle + 1;
}else{
notifyStruct[nextNotifyChar].ccc_handle = attr->handle;
}
// Attempt Subscription
err = bt_gatt_subscribe(conn, ¬ifyStruct[nextNotifyChar]);
if (err && err != -EALREADY) {
printk("[BLE] FAILURE: Subscribe failed (err %d)\n", err);
} else {
printk(" - - Subscribed to Handle = %d, Notify = %d\n", attr->handle, nextNotifyChar);
}
// Reset Notify Structure
nextNotifyChar = NUM_OF_NOTIFY_CHARS;
}
}
// For receiving a subscribed notification
uint8_t genericNotifyCollect(volatile uint8_t* storageArr, volatile bool* storageFlag, void (*codeInject)(uint8_t*),
struct bt_gatt_subscribe_params *params, const void *data) {
int result = BT_GATT_ITER_STOP;
if ((uint8_t*)data) {
uint8_t* myData = (uint8_t*)data;
// Optionally Collect the Data
if (storageArr != NULL && storageFlag != NULL) {
*storageFlag = true;
oa_memcpy((uint8_t*)storageArr, myData, VND_MAX_LEN);
}
// Optionally, Perform Code Injection
// This drastically reduces the code for some files
if (codeInject != NULL) {
codeInject(myData);
}
// Continue Receiving Notification
result = BT_GATT_ITER_CONTINUE;
} else {
printk("[BLE] UNSUBSCRIBING: Notify Returned Null: %d\n", params->value_handle);
params->value_handle = 0U;
}
return result;
}
// For re-subscribing to stored handles on re-pair
void subscribeToStoredHandles(struct bt_conn *conn) {
bool subscribe;
for (NOTIFY_CHAR_HANDLES_T handle = NOTIFY_FS_STATUS; handle < NUM_OF_NOTIFY_CHARS; handle++) {
// Reset Subscribe Status
subscribe = false;
// Check if Handle is Valid
if (notifyStruct[handle].ccc_handle != 0) {
// Determine if Current Connection Matches Handle
switch(handle) {
case NOTIFY_FS_STATUS:
case NOTIFY_FS_QUAT:
case NOTIFY_FS_LOG:
case NOTIFY_FS_RAW:
if (conn == *ptrFSConn) {
subscribe = true;
}
break;
case NOTIFY_GL_VALUE:
if (conn == *ptrGLConn) {
subscribe = true;
}
break;
case NOTIFY_TB_CMD:
case NOTIFY_FWU_INFO:
case NOTIFY_FWU_DATA:
if (conn == *ptrTBConn) {
subscribe = true;
}
break;
default:
break;
}
// Perform Subscribe
if (subscribe) {
int err = bt_gatt_subscribe(conn, ¬ifyStruct[handle]);
if (err) {
printk("[BLE] FAILURE: Subscribe failed (err %d)\n", err);
} else {
printk(" - - Subscribed to Handle = %d, Notify = %d\n", notifyStruct[handle].ccc_handle, handle);
}
}
}
}
}
It is common for my application that the two devices lose connection and have to re-pair. To skip the discover process, I maintain the structures used to write/read/subscribe with the my device and re-use them. Both of my devices will not be software updated during this disconnection, so I am assuming this is safe to do.
Unfortunately, this tactic is not completely working. I have not thoroughly tested the write/read, but the notifies do not seem to re-subscribe correctly. Currently, two of them are failing to re-subscribe. It seems when the notifications unsubscribe during the disconnect, some of the notify structure variables are changed. I printed out the entire notify structure and found the node member is being set to 0 for the values that are failing to subscribe. My custom logs are shown below that hopefully provide some context. Is there a more proper way to accomplish what I am doing? Or am I missing a step to reset the connection/notifications properly?
[BLE] Primary Service Discovered. Val = 0x1855, Handle = 41, End Handle = 55
- - Subscribed to value=1, value_handle=45, ccc_handle=46, notify=174433, subscribe=0, node=0, flags=536904816, handle=0
- - Subscribed to value=1, value_handle=48, ccc_handle=49, notify=174469, subscribe=0, node=536904820, flags=536904840, handle=1
- - Subscribed to value=1, value_handle=51, ccc_handle=52, notify=174505, subscribe=0, node=536904844, flags=536904864, handle=2
- - Subscribed to value=1, value_handle=54, ccc_handle=55, notify=174537, subscribe=0, node=536904868, flags=536904888, handle=3
[BLE] Bluetooth Discovery: Complete
[BLE] UNSUBSCRIBING: Notify Returned Null: 54
[BLE] UNSUBSCRIBING: Notify Returned Null: 51
[BLE] UNSUBSCRIBING: Notify Returned Null: 48
[BLE] UNSUBSCRIBING: Notify Returned Null: 45
[BLE] FS Status: Disconnected 0x8
[BLE] Device Status: Connected
[BLE] Using Cached Handles
- - Subscribed to value=1, value_handle=45, ccc_handle=46, notify=174433, subscribe=0, node=0, flags=536904816, handle=0
- - Subscribed to value=1, value_handle=48, ccc_handle=49, notify=174469, subscribe=0, node=536904820, flags=536904840, handle=1
- - Failed Subscribing value=1, value_handle=51, ccc_handle=52, notify=174505, subscribe=0, node=0, flags=536904864, handle=2
- - Failed Subscribing value=1, value_handle=54, ccc_handle=55, notify=174537, subscribe=0, node=0, flags=536904888, handle=3
Thanks,
Levi