From 28e39e24e93d10b80916f8d9ddc937d346d7827c Mon Sep 17 00:00:00 2001 From: h2zero Date: Sun, 29 Mar 2026 12:26:54 -0600 Subject: [PATCH] [Bugfix] get remote characteristic by uuid returning the wrong instance. This fixes a bug introduced when sorting the characteristic vector where the last item on in the vector was returned but the characteristc wasn't at the end anymore. This reverts the previous sorting of the vector after retrieval and instead sorts as the characteristics are found and also provides a pointer to the characteristic from the retrieval callback. --- src/NimBLERemoteService.cpp | 49 ++++++++++++++++--------------------- src/NimBLERemoteService.h | 2 +- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 2651f5fb3..f15a9a31e 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -25,7 +25,6 @@ # include "NimBLELog.h" # include -# include static const char* LOG_TAG = "NimBLERemoteService"; @@ -77,31 +76,22 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID& uuid) const { NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str()); NimBLERemoteCharacteristic* pChar = nullptr; - size_t prev_size = m_vChars.size(); for (const auto& it : m_vChars) { if (it->getUUID() == uuid) { pChar = it; - goto Done; + NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: found in cache"); + return pChar; } } - if (retrieveCharacteristics(&uuid)) { - if (m_vChars.size() > prev_size) { - pChar = m_vChars.back(); - goto Done; - } - + if (retrieveCharacteristics(&uuid, &pChar) && pChar == nullptr) { // If the request was successful but 16/32 bit uuid not found // try again with the 128 bit uuid. if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { NimBLEUUID uuid128(uuid); uuid128.to128(); - if (retrieveCharacteristics(&uuid128)) { - if (m_vChars.size() > prev_size) { - pChar = m_vChars.back(); - } - } + retrieveCharacteristics(&uuid128, &pChar); } else { // If the request was successful but the 128 bit uuid not found // try again with the 16 bit uuid. @@ -109,16 +99,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU uuid16.to16(); // if the uuid was 128 bit but not of the BLE base type this check will fail if (uuid16.bitSize() == BLE_UUID_TYPE_16) { - if (retrieveCharacteristics(&uuid16)) { - if (m_vChars.size() > prev_size) { - pChar = m_vChars.back(); - } - } + retrieveCharacteristics(&uuid16, &pChar); } } } -Done: NIMBLE_LOGD(LOG_TAG, "<< Characteristic %sfound", pChar ? "" : "not "); return pChar; } // getCharacteristic @@ -166,7 +151,18 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, } if (error->status == 0) { - pSvc->m_vChars.push_back(new NimBLERemoteCharacteristic(pSvc, chr)); + // insert in handle order + auto pNewChar = new NimBLERemoteCharacteristic(pSvc, chr); + for (auto it = pSvc->m_vChars.begin(); it != pSvc->m_vChars.end(); ++it) { + if ((*it)->getHandle() > chr->def_handle) { + pSvc->m_vChars.insert(it, pNewChar); + pTaskData->m_pBuf = pNewChar; + return 0; + } + } + + pSvc->m_vChars.push_back(pNewChar); + pTaskData->m_pBuf = pNewChar; return 0; } @@ -180,7 +176,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, * This function will not return until we have all the characteristics. * @return True if successful. */ -bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) const { +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, NimBLERemoteCharacteristic** ppChar) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()"); int rc = 0; NimBLETaskData taskData(const_cast(this)); @@ -208,12 +204,9 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; if (rc == 0 || rc == BLE_HS_EDONE) { - // sort the characteristics vector by handle to make sure the search range for descriptors is correct - std::sort(m_vChars.begin(), - m_vChars.end(), - [](const NimBLERemoteCharacteristic* a, const NimBLERemoteCharacteristic* b) { - return a->getHandle() < b->getHandle(); - }); + if (ppChar != nullptr) { + *ppChar = static_cast(taskData.m_pBuf); + } NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()"); return true; } diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index c2aa445dd..4d9534949 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -53,7 +53,7 @@ class NimBLERemoteService : public NimBLEAttribute { NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service); ~NimBLERemoteService(); - bool retrieveCharacteristics(const NimBLEUUID* uuidFilter = nullptr) const; + bool retrieveCharacteristics(const NimBLEUUID* uuidFilter = nullptr, NimBLERemoteCharacteristic** ppChar = nullptr) const; static int characteristicDiscCB(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_chr* chr,