-
-
Notifications
You must be signed in to change notification settings - Fork 86
Properly set attribute handles and improve dynamic service changes #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,6 +39,11 @@ | |||||||||
| static const char* LOG_TAG = "NimBLEServer"; | ||||||||||
| static NimBLEServerCallbacks defaultCallbacks; | ||||||||||
|
|
||||||||||
| struct gattRegisterCallbackArgs { | ||||||||||
| NimBLEService* pSvc{nullptr}; | ||||||||||
| NimBLECharacteristic* pChar{nullptr}; | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * @brief Construct a BLE Server | ||||||||||
| * | ||||||||||
|
|
@@ -188,16 +193,96 @@ void NimBLEServer::serviceChanged() { | |||||||||
| } | ||||||||||
| } // serviceChanged | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * @brief Callback for GATT registration events, | ||||||||||
| * used to obtain the assigned handles for services, characteristics, and descriptors. | ||||||||||
| * @param [in] ctxt The context of the registration event. | ||||||||||
| * @param [in] arg Unused. | ||||||||||
| */ | ||||||||||
| void NimBLEServer::gattRegisterCallback(ble_gatt_register_ctxt* ctxt, void* arg) { | ||||||||||
| gattRegisterCallbackArgs* args = static_cast<gattRegisterCallbackArgs*>(arg); | ||||||||||
|
|
||||||||||
| if (ctxt->op == BLE_GATT_REGISTER_OP_SVC) { | ||||||||||
| NimBLEUUID uuid(ctxt->svc.svc_def->uuid); | ||||||||||
| for (auto i = 0; i < NimBLEDevice::getServer()->m_svcVec.size(); i++) { | ||||||||||
| auto pSvc = NimBLEDevice::getServer()->getServiceByUUID(uuid, i); | ||||||||||
| if (pSvc != nullptr && pSvc->m_handle == 0) { | ||||||||||
| pSvc->m_handle = ctxt->svc.handle; | ||||||||||
| NIMBLE_LOGD(LOG_TAG, "Service registered: %s, handle=%d", uuid.toString().c_str(), ctxt->svc.handle); | ||||||||||
| // Set the arg to the service so we know that the following | ||||||||||
| // characteristics and descriptors belong to this service | ||||||||||
| args->pSvc = pSvc; | ||||||||||
| break; | ||||||||||
| } | ||||||||||
|
Comment on lines
+202
to
+216
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (args->pSvc == nullptr) { | ||||||||||
| // If the service is not found then this is likely a characteristic or descriptor that was registered as | ||||||||||
| // part of the GATT server setup and not found in the service vector | ||||||||||
| NIMBLE_LOGD(LOG_TAG, "Skipping characteristic or descriptor registered with unknown service"); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) { | ||||||||||
| NimBLEUUID uuid(ctxt->chr.chr_def->uuid); | ||||||||||
| for (auto i = 0; i < args->pSvc->m_vChars.size(); i++) { | ||||||||||
| auto pChr = args->pSvc->getCharacteristic(uuid, i); | ||||||||||
| if (pChr != nullptr && pChr->m_handle == 0) { | ||||||||||
| pChr->m_handle = ctxt->chr.val_handle; | ||||||||||
| // Set the arg to the characteristic so we know that the following descriptors belong to this characteristic | ||||||||||
| args->pChar = pChr; | ||||||||||
| NIMBLE_LOGD(LOG_TAG, | ||||||||||
| "Characteristic registered: %s, def_handle=%d, val_handle=%d", | ||||||||||
| uuid.toString().c_str(), | ||||||||||
| ctxt->chr.def_handle, | ||||||||||
| ctxt->chr.val_handle); | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (ctxt->op == BLE_GATT_REGISTER_OP_DSC) { | ||||||||||
| if (args->pChar == nullptr) { | ||||||||||
| NIMBLE_LOGE(LOG_TAG, "Descriptor registered with unknown characteristic, skipping"); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| NimBLEUUID uuid(ctxt->dsc.dsc_def->uuid); | ||||||||||
| for (auto i = 0; i < args->pChar->m_vDescriptors.size(); i++) { | ||||||||||
| auto pDsc = args->pChar->getDescriptorByUUID(uuid, i); | ||||||||||
| if (pDsc != nullptr && pDsc->m_handle == 0) { | ||||||||||
| pDsc->m_handle = ctxt->dsc.handle; | ||||||||||
| NIMBLE_LOGD(LOG_TAG, "Descriptor registered: %s, handle=%d", uuid.toString().c_str(), ctxt->dsc.handle); | ||||||||||
| return; | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * @brief Start the GATT server. | ||||||||||
| * @details Required to be called after setup of all services and characteristics / descriptors | ||||||||||
| * for the NimBLE host to register them. | ||||||||||
| */ | ||||||||||
| void NimBLEServer::start() { | ||||||||||
| if (m_svcChanged && !getConnectedCount()) { | ||||||||||
| NIMBLE_LOGD(LOG_TAG, "Services have changed since last start, resetting GATT server"); | ||||||||||
| resetGATT(); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (m_gattsStarted) { | ||||||||||
| return; // already started | ||||||||||
| } | ||||||||||
|
|
||||||||||
| ble_hs_cfg.gatts_register_cb = NimBLEServer::gattRegisterCallback; | ||||||||||
| gattRegisterCallbackArgs args{}; | ||||||||||
| ble_hs_cfg.gatts_register_arg = &args; | ||||||||||
|
Comment on lines
+283
to
+284
|
||||||||||
| gattRegisterCallbackArgs args{}; | |
| ble_hs_cfg.gatts_register_arg = &args; | |
| static gattRegisterCallbackArgs s_args{}; | |
| ble_hs_cfg.gatts_register_arg = &s_args; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -89,7 +89,14 @@ void NimBLEService::dump() const { | |||||
| * @return bool success/failure . | ||||||
| */ | ||||||
| bool NimBLEService::start() { | ||||||
| NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str()); | ||||||
| NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: UUID: %s", getUUID().toString().c_str()); | ||||||
| // If the server has started before then we need to reset the GATT server | ||||||
| // to update the service/characteristic/descriptor definitions. If characteristics or descriptors | ||||||
| // have been added/removed since the last server start then this service will be started on gatt reset. | ||||||
| if (getServer()->m_svcChanged) { | ||||||
| NIMBLE_LOGW(LOG_TAG, "<< start(): GATT server already started, cannot start service"); | ||||||
|
||||||
| NIMBLE_LOGW(LOG_TAG, "<< start(): GATT server already started, cannot start service"); | |
| NIMBLE_LOGW(LOG_TAG, "<< start(): GATT services changed after start; GATT reset/restart required before adding this service"); |
Copilot
AI
Mar 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
numChrs is a size_t, but this log uses %d. This can trigger format warnings (or errors under -Werror) on some toolchains. Use the correct format specifier or cast to an int explicitly if the value is known to fit.
| NIMBLE_LOGD(LOG_TAG, "Adding %d characteristics for service %s", numChrs, getUUID().toString().c_str()); | |
| NIMBLE_LOGD(LOG_TAG, "Adding %zu characteristics for service %s", numChrs, getUUID().toString().c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These
for (auto i = 0; i < ...size(); i++)loops deduceiasintand compare to.size()(size_t), which can trigger signed/unsigned comparison warnings. Prefersize_t i = 0(or a range-based loop) for the index variable.