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