From a04ee1581524a1dfaab24fbe3854722125f953eb Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:55:10 -0500 Subject: [PATCH 01/12] refactor: Consolidate attribute get code into NimBLEUtils --- src/NimBLEClient.cpp | 186 +++++++++++------------------ src/NimBLERemoteCharacteristic.cpp | 137 ++++++++------------- src/NimBLERemoteService.cpp | 106 +++++----------- src/NimBLEUtils.h | 31 +++++ 4 files changed, 180 insertions(+), 280 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index e5b1383c..c2e53ddb 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -101,8 +101,8 @@ NimBLEClient::~NimBLEClient() { */ void NimBLEClient::deleteServices() { // Delete all the services. - for (auto& it : m_svcVec) { - delete it; + for (auto& svc : m_svcVec) { + delete svc; } std::vector().swap(m_svcVec); @@ -243,8 +243,7 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes, break; default: - NIMBLE_LOGE(LOG_TAG, - "Failed to connect to %s, rc=%d; %s", + NIMBLE_LOGE(LOG_TAG, "Failed to connect to %s, rc=%d; %s", std::string(m_peerAddress).c_str(), rc, NimBLEUtils::returnCodeToString(rc)); @@ -631,48 +630,14 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { */ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); + NimBLERemoteService *pSvc = nullptr; - for (auto& it : m_svcVec) { - if (it->getUUID() == uuid) { - NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); - return it; - } - } + NimBLEUtils::getAttr(uuid, pSvc, m_svcVec, [this](const NimBLEUUID* u, void* arg) { + return retrieveServices(u, (NimBLERemoteService*)arg); + }); - size_t prevSize = m_svcVec.size(); - if (retrieveServices(&uuid)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); - } - - // 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 (retrieveServices(&uuid128)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); - } - } - } else { - // If the request was successful but the 128 bit uuid not found - // try again with the 16 bit uuid. - NimBLEUUID uuid16(uuid); - 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 (retrieveServices(&uuid16)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); - } - } - } - } - } - - NIMBLE_LOGD(LOG_TAG, "<< getService: not found"); - return nullptr; + NIMBLE_LOGD(LOG_TAG, "<< getService: %sfound", !pSvc ? "not " : ""); + return pSvc; } // getService /** @@ -725,7 +690,7 @@ bool NimBLEClient::discoverAttributes() { * * Here we ask the server for its set of services and wait until we have received them all. * @return true on success otherwise false if an error occurred */ -bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) { +bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteService *out) { if (!isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting"); return false; @@ -735,9 +700,9 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) { NimBLETaskData taskData(this); if (uuidFilter == nullptr) { - rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscoveredCB, &taskData); + rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscCB, &taskData); } else { - rc = ble_gattc_disc_svc_by_uuid(m_connHandle, uuidFilter->getBase(), NimBLEClient::serviceDiscoveredCB, &taskData); + rc = ble_gattc_disc_svc_by_uuid(m_connHandle, uuidFilter->getBase(), NimBLEClient::serviceDiscCB, &taskData); } if (rc != 0) { @@ -748,13 +713,15 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) { NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; - if (rc == 0 || rc == BLE_HS_EDONE) { - return true; + if (rc != BLE_HS_EDONE) { + m_lastErr = rc; + NIMBLE_LOGE(LOG_TAG, "Could not retrieve services, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + return false; } - m_lastErr = rc; - NIMBLE_LOGE(LOG_TAG, "Could not retrieve services, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); - return false; + out = m_svcVec.back(); + NIMBLE_LOGD(LOG_TAG, "<< retrieveServices(): found %d services.", m_svcVec.size()); + return true; } // getServices /** @@ -762,39 +729,29 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter) { * @details When a service is found or there is none left or there was an error * the API will call this and report findings. */ -int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle, - const struct ble_gatt_error* error, - const struct ble_gatt_svc* service, - void* arg) { - NIMBLE_LOGD(LOG_TAG, - "Service Discovered >> status: %d handle: %d", - error->status, - (error->status == 0) ? service->start_handle : -1); - - NimBLETaskData* pTaskData = (NimBLETaskData*)arg; - NimBLEClient* pClient = (NimBLEClient*)pTaskData->m_pInstance; - - if (error->status == BLE_HS_ENOTCONN) { - NIMBLE_LOGE(LOG_TAG, "<< Service Discovered; Disconnected"); - NimBLEUtils::taskRelease(*pTaskData, error->status); - return error->status; - } +int NimBLEClient::serviceDiscCB(uint16_t connHandle, + const struct ble_gatt_error* error, + const struct ble_gatt_svc* service, + void* arg) { + const int rc = error->status; + auto pTaskData = (NimBLETaskData*)arg; + auto pClient = (NimBLEClient*)pTaskData->m_pInstance; + NIMBLE_LOGD(LOG_TAG, "Service Discovered >> status: %d handle: %d", rc, (rc == 0) ? service->start_handle : -1); // Make sure the service discovery is for this device if (pClient->getConnHandle() != connHandle) { return 0; } - if (error->status == 0) { - // Found a service - add it to the vector + if (rc == 0) { // Found a service - add it to the vector pClient->m_svcVec.push_back(new NimBLERemoteService(pClient, service)); return 0; } NimBLEUtils::taskRelease(*pTaskData, error->status); - NIMBLE_LOGD(LOG_TAG, "<< Service Discovered"); + NIMBLE_LOGD(LOG_TAG, "<< Service Discovered%s", (rc == BLE_HS_ENOTCONN) ? "; Disconnected" : ""); return error->status; -} // serviceDiscoveredCB +} // serviceDiscCB /** * @brief Get the value of a specific characteristic associated with a specific service. @@ -803,8 +760,7 @@ int NimBLEClient::serviceDiscoveredCB(uint16_t connHandle, * @returns characteristic value or an empty value if not found. */ NimBLEAttValue NimBLEClient::getValue(const NimBLEUUID& serviceUUID, const NimBLEUUID& characteristicUUID) { - NIMBLE_LOGD(LOG_TAG, - ">> getValue: serviceUUID: %s, characteristicUUID: %s", + NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); @@ -833,15 +789,14 @@ bool NimBLEClient::setValue(const NimBLEUUID& serviceUUID, const NimBLEUUID& characteristicUUID, const NimBLEAttValue& value, bool response) { - NIMBLE_LOGD(LOG_TAG, - ">> setValue: serviceUUID: %s, characteristicUUID: %s", + NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); bool ret = false; auto pService = getService(serviceUUID); if (pService != nullptr) { - NimBLERemoteCharacteristic* pChar = pService->getCharacteristic(characteristicUUID); + auto pChar = pService->getCharacteristic(characteristicUUID); if (pChar != nullptr) { ret = pChar->writeValue(value, response); } @@ -858,11 +813,13 @@ bool NimBLEClient::setValue(const NimBLEUUID& serviceUUID, */ NimBLERemoteCharacteristic* NimBLEClient::getCharacteristic(uint16_t handle) { for (const auto& svc : m_svcVec) { - if (svc->getStartHandle() <= handle && handle <= svc->getEndHandle()) { - for (const auto& chr : svc->m_vChars) { - if (chr->getHandle() == handle) { - return chr; - } + if (svc->getStartHandle() > handle && handle > svc->getEndHandle()) { + continue; + } + + for (const auto& chr : svc->m_vChars) { + if (chr->getHandle() == handle) { + return chr; } } } @@ -882,28 +839,28 @@ uint16_t NimBLEClient::getMTU() const { * @brief Callback for the MTU exchange API function. * @details When the MTU exchange is complete the API will call this and report the new MTU. */ -int NimBLEClient::exchangeMTUCb(uint16_t conn_handle, const ble_gatt_error* error, uint16_t mtu, void* arg) { - NIMBLE_LOGD(LOG_TAG, "exchangeMTUCb: status=%d, mtu=%d", error->status, mtu); +int NimBLEClient::exchangeMTUCB(uint16_t connHandle, const ble_gatt_error* error, uint16_t mtu, void* arg) { + NIMBLE_LOGD(LOG_TAG, "exchangeMTUCB: status=%d, mtu=%d", error->status, mtu); NimBLEClient* pClient = (NimBLEClient*)arg; - if (pClient->getConnHandle() != conn_handle) { + if (pClient->getConnHandle() != connHandle) { return 0; } if (error->status != 0) { - NIMBLE_LOGE(LOG_TAG, "exchangeMTUCb() rc=%d %s", error->status, NimBLEUtils::returnCodeToString(error->status)); + NIMBLE_LOGE(LOG_TAG, "exchangeMTUCB() rc=%d %s", error->status, NimBLEUtils::returnCodeToString(error->status)); pClient->m_lastErr = error->status; } return 0; -} // exchangeMTUCb +} // exchangeMTUCB /** * @brief Begin the MTU exchange process with the server. * @returns true if the request was sent successfully. */ bool NimBLEClient::exchangeMTU() { - int rc = ble_gattc_exchange_mtu(m_connHandle, NimBLEClient::exchangeMTUCb, this); + int rc = ble_gattc_exchange_mtu(m_connHandle, NimBLEClient::exchangeMTUCB, this); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "MTU exchange error; rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); m_lastErr = rc; @@ -989,25 +946,25 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) { pClient->m_pClientCallbacks->onConnect(pClient); } - if (pClient->m_config.exchangeMTU) { - if (!pClient->exchangeMTU()) { - rc = pClient->m_lastErr; // sets the error in the task data - break; - } - - return 0; // return as we may have a task waiting for the MTU before releasing it. + if (!pClient->m_config.exchangeMTU) { + break; } - } else { - pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE; - if (pClient->m_config.asyncConnect) { - pClient->m_pClientCallbacks->onConnectFail(pClient, rc); - if (pClient->m_config.deleteOnConnectFail) { - NimBLEDevice::deleteClient(pClient); - } + if (!pClient->exchangeMTU()) { + rc = pClient->m_lastErr; // sets the error in the task data + break; } + + return 0; // return as we may have a task waiting for the MTU before releasing it. } + pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE; + if (pClient->m_config.asyncConnect) { + pClient->m_pClientCallbacks->onConnectFail(pClient, rc); + if (pClient->m_config.deleteOnConnectFail) { + NimBLEDevice::deleteClient(pClient); + } + } break; } // BLE_GAP_EVENT_CONNECT @@ -1035,23 +992,23 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) { continue; } - NIMBLE_LOGD(LOG_TAG, - "checking service %s for handle: %d", + NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", svc->getUUID().toString().c_str(), event->notify_rx.attr_handle); for (const auto& chr : svc->m_vChars) { - if (chr->getHandle() == event->notify_rx.attr_handle) { - NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", chr->toString().c_str()); + if (chr->getHandle() != event->notify_rx.attr_handle) { + continue; + } - uint32_t data_len = OS_MBUF_PKTLEN(event->notify_rx.om); - chr->m_value.setValue(event->notify_rx.om->om_data, data_len); + NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", chr->toString().c_str()); + uint32_t data_len = OS_MBUF_PKTLEN(event->notify_rx.om); + chr->m_value.setValue(event->notify_rx.om->om_data, data_len); - if (chr->m_notifyCallback != nullptr) { - chr->m_notifyCallback(chr, event->notify_rx.om->om_data, data_len, !event->notify_rx.indication); - } - break; + if (chr->m_notifyCallback != nullptr) { + chr->m_notifyCallback(chr, event->notify_rx.om->om_data, data_len, !event->notify_rx.indication); } + break; } } @@ -1064,8 +1021,7 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) { return 0; } NIMBLE_LOGD(LOG_TAG, "Peer requesting to update connection parameters"); - NIMBLE_LOGD(LOG_TAG, - "MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d", + NIMBLE_LOGD(LOG_TAG, "MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d", event->conn_update_req.peer_params->itvl_min, event->conn_update_req.peer_params->itvl_max, event->conn_update_req.peer_params->latency, diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index bac85747..b0893951 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -27,17 +27,17 @@ # include -typedef struct { - const NimBLEUUID* uuid; - void* task_data; -} desc_filter_t; +struct desc_filter_t { + const NimBLEUUID* uuid; + void* taskData; +}; static const char* LOG_TAG = "NimBLERemoteCharacteristic"; /** * @brief Constructor. * @param [in] svc A pointer to the service this characteristic belongs to. - * @param [in] ble_gatt_chr struct defined as: + * @param [in] chr struct defined as: * struct ble_gatt_chr { * uint16_t def_handle; * uint16_t val_handle; @@ -62,57 +62,56 @@ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() { /** * @brief Callback used by the API when a descriptor is discovered or search complete. */ -int NimBLERemoteCharacteristic::descriptorDiscCB( - uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg) { - int rc = error->status; +int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle, + const ble_gatt_error* error, + uint16_t chrHandle, + const ble_gatt_dsc* dsc, + void* arg) { + int rc = error->status; + auto filter = (desc_filter_t*)arg; + auto pTaskData = (NimBLETaskData*)filter->taskData; + const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance; + const auto uuid = filter->uuid; // UUID to filter for NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1); - auto filter = (desc_filter_t*)arg; - auto pTaskData = (NimBLETaskData*)filter->task_data; - const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance; - const NimBLEUUID* uuidFilter = filter->uuid; - - if (pChr->getHandle() != chr_val_handle) { - return 0; // Descriptor not for this characteristic - } - - if (rc == 0) { - if (uuidFilter != nullptr) { - if (ble_uuid_cmp(uuidFilter->getBase(), &dsc->uuid.u) == 0) { - rc = BLE_HS_EDONE; // Found the descriptor, stop the search - } else { - return 0; // Not the descriptor we are looking for - } - } - + // Results for chrHandle added until rc != 0 + // Must find specified UUID if filter is used + if (rc == 0 && pChr->getHandle() == chrHandle + && (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) { + // Return BLE_HS_EDONE if the descriptor was found, stop the search pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc)); - return 0; + rc = !!uuid * BLE_HS_EDONE; } - NimBLEUtils::taskRelease(*pTaskData, rc); - NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery"); + if (rc != 0) { + NimBLEUtils::taskRelease(*pTaskData, rc); + NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery"); + } return rc; } /** * @brief Populate the descriptors (if any) for this characteristic. - * @param [in] the end handle of the characteristic, or the service, whichever comes first. + * @param [in] filter Structure containing pointers to descriptor, UUID, and task data. + * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const { +bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter, NimBLERemoteDescriptor* out) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); + NimBLETaskData taskData(const_cast(this)); + desc_filter_t filter = {uuidFilter, &taskData}; + const uint16_t handle = getHandle(); + const uint16_t svcHandle = getRemoteService()->getEndHandle(); + // If this is the last handle then there are no descriptors - if (getHandle() == getRemoteService()->getEndHandle()) { - NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found 0 descriptors."); - return true; + if (handle == svcHandle) { + NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found 0 descriptors."); + return true; } - NimBLETaskData taskData(const_cast(this)); - desc_filter_t filter = {uuidFilter, &taskData}; - int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(), - getHandle(), - getRemoteService()->getEndHandle(), + handle, + svcHandle, NimBLERemoteCharacteristic::descriptorDiscCB, &filter); if (rc != 0) { @@ -122,13 +121,14 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; - if (rc == 0 || rc == BLE_HS_EDONE) { - NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); - return true; + if (rc != BLE_HS_EDONE) { + NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + return false; } - NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); - return false; + out = m_vDescriptors.back(); + NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); + return true; } // retrieveDescriptors /** @@ -138,50 +138,13 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte */ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const { NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); - NimBLERemoteDescriptor* pDsc = nullptr; - size_t prev_size = m_vDescriptors.size(); + NimBLERemoteDescriptor* pDsc = nullptr; - for (const auto& it : m_vDescriptors) { - if (it->getUUID() == uuid) { - pDsc = it; - goto Done; - } - } - - if (retrieveDescriptors(&uuid)) { - if (m_vDescriptors.size() > prev_size) { - pDsc = m_vDescriptors.back(); - goto Done; - } - - // 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 (retrieveDescriptors(&uuid128)) { - if (m_vDescriptors.size() > prev_size) { - pDsc = m_vDescriptors.back(); - } - } - } else { - // If the request was successful but the 128 bit uuid not found - // try again with the 16 bit uuid. - NimBLEUUID uuid16(uuid); - 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 (retrieveDescriptors(&uuid16)) { - if (m_vDescriptors.size() > prev_size) { - pDsc = m_vDescriptors.back(); - } - } - } - } - } + NimBLEUtils::getAttr(uuid, pDsc, m_vDescriptors, [this](const NimBLEUUID* u, void* arg) { + return retrieveDescriptors(u, (NimBLERemoteDescriptor*)arg); + }); -Done: - NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", pDsc ? "" : "not "); + NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", !pDsc ? "not " : ""); return pDsc; } // getDescriptor @@ -311,7 +274,7 @@ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID& uuid) cons * @return True if supported. */ bool NimBLERemoteCharacteristic::canBroadcast() const { - return (m_properties & BLE_GATT_CHR_PROP_BROADCAST) != 0; + return (m_properties & BLE_GATT_CHR_PROP_BROADCAST); }; /** diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index c131af74..6dba0f53 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -76,50 +76,13 @@ 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(); + NimBLERemoteCharacteristic* pChar = nullptr; - for (const auto& it : m_vChars) { - if (it->getUUID() == uuid) { - pChar = it; - goto Done; - } - } + NimBLEUtils::getAttr(uuid, pChar, m_vChars, [this](const NimBLEUUID* u, void* arg) { + return retrieveCharacteristics(u, (NimBLERemoteCharacteristic*)arg); + }); - if (retrieveCharacteristics(&uuid)) { - if (m_vChars.size() > prev_size) { - pChar = m_vChars.back(); - goto Done; - } - - // 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(); - } - } - } else { - // If the request was successful but the 128 bit uuid not found - // try again with the 16 bit uuid. - NimBLEUUID uuid16(uuid); - 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(); - } - } - } - } - } - -Done: - NIMBLE_LOGD(LOG_TAG, "<< Characteristic %sfound", pChar ? "" : "not "); + NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChar ? "not " : ""); return pChar; } // getCharacteristic @@ -143,47 +106,39 @@ const std::vector& NimBLERemoteService::getCharacte * @brief Callback for Characteristic discovery. * @return success == 0 or error code. */ -int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, +int NimBLERemoteService::characteristicDiscCB(uint16_t connHandle, const ble_gatt_error* error, const ble_gatt_chr* chr, void* arg) { - NIMBLE_LOGD(LOG_TAG, - "Characteristic Discovery >> status: %d handle: %d", - error->status, - (error->status == 0) ? chr->def_handle : -1); + const int rc = error->status; auto pTaskData = (NimBLETaskData*)arg; const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance; - - if (error->status == BLE_HS_ENOTCONN) { - NIMBLE_LOGE(LOG_TAG, "<< Characteristic Discovery; Not connected"); - NimBLEUtils::taskRelease(*pTaskData, error->status); - return error->status; - } + NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >> status: %d handle: %d", rc, (rc == 0) ? chr->def_handle : -1); // Make sure the discovery is for this device - if (pSvc->getClient()->getConnHandle() != conn_handle) { + if (pSvc->getClient()->getConnHandle() != connHandle) { return 0; } - if (error->status == 0) { + if (rc == 0) { pSvc->m_vChars.push_back(new NimBLERemoteCharacteristic(pSvc, chr)); return 0; } - NimBLEUtils::taskRelease(*pTaskData, error->status); - NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery"); - return error->status; + NimBLEUtils::taskRelease(*pTaskData, rc); + NIMBLE_LOGD(LOG_TAG, "<< Characteristic Discovery%s", (rc == BLE_HS_ENOTCONN) ? "; Not connected" : ""); + return rc; } /** * @brief Retrieve all the characteristics for this service. * This function will not return until we have all the characteristics. - * @return True if successful. + * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) const { +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, NimBLERemoteCharacteristic* out) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()"); - int rc = 0; NimBLETaskData taskData(const_cast(this)); + int rc = 0; if (uuidFilter == nullptr) { rc = ble_gattc_disc_all_chrs(m_pClient->getConnHandle(), @@ -207,13 +162,14 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter) NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; - if (rc == 0 || rc == BLE_HS_EDONE) { - NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()"); - return true; + if (rc != BLE_HS_EDONE) { + NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + return false; } - NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics() rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); - return false; + out = m_vChars.back(); + NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics(): found %d characteristics.", m_vChars.size()); + return true; } // retrieveCharacteristics /** @@ -231,11 +187,8 @@ NimBLEClient* NimBLERemoteService::getClient() const { */ NimBLEAttValue NimBLERemoteService::getValue(const NimBLEUUID& uuid) const { const auto pChar = getCharacteristic(uuid); - if (pChar) { - return pChar->readValue(); - } - - return NimBLEAttValue{}; + return pChar ? pChar->readValue() + : NimBLEAttValue{}; } // readValue /** @@ -246,11 +199,8 @@ NimBLEAttValue NimBLERemoteService::getValue(const NimBLEUUID& uuid) const { */ bool NimBLERemoteService::setValue(const NimBLEUUID& uuid, const NimBLEAttValue& value) const { const auto pChar = getCharacteristic(uuid); - if (pChar) { - return pChar->writeValue(value); - } - - return false; + return pChar ? pChar->writeValue(value) + : false; } // setValue /** @@ -260,8 +210,8 @@ bool NimBLERemoteService::setValue(const NimBLEUUID& uuid, const NimBLEAttValue& * them. This method does just that. */ void NimBLERemoteService::deleteCharacteristics() const { - for (const auto& it : m_vChars) { - delete it; + for (const auto& chr : m_vChars) { + delete chr; } std::vector{}.swap(m_vChars); } // deleteCharacteristics diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index e56f568e..a8c20844 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -20,6 +20,8 @@ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) +# include "NimBLEUUID.h" +# include "functional" # include class NimBLEAddress; @@ -53,6 +55,35 @@ class NimBLEUtils { static NimBLEAddress generateAddr(bool nrpa); static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout); static void taskRelease(const NimBLETaskData& taskData, int rc = 0); + + template + static void getAttr(const NimBLEUUID& uuid, T* attr, const std::vector vec, const std::function& getter) { + // Check if already exists. + for (const auto& v : vec) { + if (v->getUUID() == uuid) { + attr = v; + return; + } + } + + // Exit if request failed or uuid was found. + if (!getter(&uuid, attr) || attr) { + return; + } + + // Try again with 128 bit uuid if request succeeded with no uuid found. + if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { + NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); + getter(&uuid128, attr); + return; + } + // Try again with 16 bit uuid if request succeeded with no uuid found. + // If the uuid was 128 bit but not of the BLE base type this check will fail. + NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); + if (uuid16.bitSize() == BLE_UUID_TYPE_16) { + getter(&uuid16, attr); + } + } }; #endif // CONFIG_BT_ENABLED From 60b4dc1cfa6cb5f291b21483ac0114bdefd2cb64 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:20:19 -0500 Subject: [PATCH 02/12] change: Static cast arg --- src/NimBLEClient.cpp | 2 +- src/NimBLERemoteCharacteristic.cpp | 2 +- src/NimBLERemoteService.cpp | 2 +- src/NimBLEUtils.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index c2e53ddb..6b66f996 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -633,7 +633,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NimBLERemoteService *pSvc = nullptr; NimBLEUtils::getAttr(uuid, pSvc, m_svcVec, [this](const NimBLEUUID* u, void* arg) { - return retrieveServices(u, (NimBLERemoteService*)arg); + return retrieveServices(u, static_cast(arg)); }); NIMBLE_LOGD(LOG_TAG, "<< getService: %sfound", !pSvc ? "not " : ""); diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index b0893951..eb5fd047 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -141,7 +141,7 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU NimBLERemoteDescriptor* pDsc = nullptr; NimBLEUtils::getAttr(uuid, pDsc, m_vDescriptors, [this](const NimBLEUUID* u, void* arg) { - return retrieveDescriptors(u, (NimBLERemoteDescriptor*)arg); + return retrieveDescriptors(u, static_cast(arg)); }); NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", !pDsc ? "not " : ""); diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 6dba0f53..f62f9021 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -79,7 +79,7 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU NimBLERemoteCharacteristic* pChar = nullptr; NimBLEUtils::getAttr(uuid, pChar, m_vChars, [this](const NimBLEUUID* u, void* arg) { - return retrieveCharacteristics(u, (NimBLERemoteCharacteristic*)arg); + return retrieveCharacteristics(u, static_cast(arg)); }); NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChar ? "not " : ""); diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index a8c20844..dfa4b9ec 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -57,7 +57,7 @@ class NimBLEUtils { static void taskRelease(const NimBLETaskData& taskData, int rc = 0); template - static void getAttr(const NimBLEUUID& uuid, T* attr, const std::vector vec, const std::function& getter) { + static void getAttr(const NimBLEUUID& uuid, T* attr, const std::vector& vec, const std::function& getter) { // Check if already exists. for (const auto& v : vec) { if (v->getUUID() == uuid) { From 05bb0774f31c259220d44f3699790fec1e6f57e6 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:15:08 -0500 Subject: [PATCH 03/12] fix: Use double pointer --- src/NimBLEClient.cpp | 8 ++++---- src/NimBLEClient.h | 12 ++++++------ src/NimBLERemoteCharacteristic.cpp | 8 ++++---- src/NimBLERemoteCharacteristic.h | 5 +++-- src/NimBLERemoteService.cpp | 8 ++++---- src/NimBLERemoteService.h | 5 +++-- src/NimBLEUtils.h | 8 ++++---- 7 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 6b66f996..ee90b27d 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -632,8 +632,8 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); NimBLERemoteService *pSvc = nullptr; - NimBLEUtils::getAttr(uuid, pSvc, m_svcVec, [this](const NimBLEUUID* u, void* arg) { - return retrieveServices(u, static_cast(arg)); + NimBLEUtils::getAttr(uuid, &pSvc, m_svcVec, [this](const NimBLEUUID* u, NimBLERemoteService** arg) { + return retrieveServices(u, arg); }); NIMBLE_LOGD(LOG_TAG, "<< getService: %sfound", !pSvc ? "not " : ""); @@ -690,7 +690,7 @@ bool NimBLEClient::discoverAttributes() { * * Here we ask the server for its set of services and wait until we have received them all. * @return true on success otherwise false if an error occurred */ -bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteService *out) { +bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteService **out) { if (!isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting"); return false; @@ -719,7 +719,7 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteSe return false; } - out = m_svcVec.back(); + *out = m_svcVec.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveServices(): found %d services.", m_svcVec.size()); return true; } // getServices diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index eba7165f..f94204da 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -116,13 +116,13 @@ class NimBLEClient { NimBLEClient(const NimBLEClient&) = delete; NimBLEClient& operator=(const NimBLEClient&) = delete; - bool retrieveServices(const NimBLEUUID* uuidFilter = nullptr); + bool retrieveServices(const NimBLEUUID* uuidFilter = nullptr, NimBLERemoteService **out = nullptr); static int handleGapEvent(struct ble_gap_event* event, void* arg); - static int exchangeMTUCb(uint16_t conn_handle, const ble_gatt_error* error, uint16_t mtu, void* arg); - static int serviceDiscoveredCB(uint16_t connHandle, - const struct ble_gatt_error* error, - const struct ble_gatt_svc* service, - void* arg); + static int exchangeMTUCB(uint16_t connHandle, const ble_gatt_error* error, uint16_t mtu, void* arg); + static int serviceDiscCB(uint16_t connHandle, + const struct ble_gatt_error* error, + const struct ble_gatt_svc* service, + void* arg); NimBLEAddress m_peerAddress; mutable int m_lastErr; diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index eb5fd047..f3a552c8 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -95,7 +95,7 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle, * @param [in] filter Structure containing pointers to descriptor, UUID, and task data. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter, NimBLERemoteDescriptor* out) const { +bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter, NimBLERemoteDescriptor** out) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); NimBLETaskData taskData(const_cast(this)); @@ -126,7 +126,7 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte return false; } - out = m_vDescriptors.back(); + *out = m_vDescriptors.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); return true; } // retrieveDescriptors @@ -140,8 +140,8 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); NimBLERemoteDescriptor* pDsc = nullptr; - NimBLEUtils::getAttr(uuid, pDsc, m_vDescriptors, [this](const NimBLEUUID* u, void* arg) { - return retrieveDescriptors(u, static_cast(arg)); + NimBLEUtils::getAttr(uuid, &pDsc, m_vDescriptors, [this](const NimBLEUUID* u, NimBLERemoteDescriptor** arg) { + return retrieveDescriptors(u, arg); }); NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", !pDsc ? "not " : ""); diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 532d814f..bc3c2941 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -65,10 +65,11 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute { ~NimBLERemoteCharacteristic(); bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const; - bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr) const; + bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr, + NimBLERemoteDescriptor** out = nullptr) const; static int descriptorDiscCB( - uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg); + uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg); const NimBLERemoteService* m_pRemoteService{nullptr}; uint8_t m_properties{0}; diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index f62f9021..3ca75edc 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -78,8 +78,8 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str()); NimBLERemoteCharacteristic* pChar = nullptr; - NimBLEUtils::getAttr(uuid, pChar, m_vChars, [this](const NimBLEUUID* u, void* arg) { - return retrieveCharacteristics(u, static_cast(arg)); + NimBLEUtils::getAttr(uuid, &pChar, m_vChars, [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** arg) { + return retrieveCharacteristics(u, arg); }); NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChar ? "not " : ""); @@ -135,7 +135,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t connHandle, * This function will not return until we have all the characteristics. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, NimBLERemoteCharacteristic* out) const { +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, NimBLERemoteCharacteristic** out) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()"); NimBLETaskData taskData(const_cast(this)); int rc = 0; @@ -167,7 +167,7 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, return false; } - out = m_vChars.back(); + *out = m_vChars.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics(): found %d characteristics.", m_vChars.size()); return true; } // retrieveCharacteristics diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index 8045788b..12333564 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -53,8 +53,9 @@ class NimBLERemoteService : public NimBLEAttribute { NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service); ~NimBLERemoteService(); - bool retrieveCharacteristics(const NimBLEUUID* uuidFilter = nullptr) const; - static int characteristicDiscCB(uint16_t conn_handle, + bool retrieveCharacteristics(const NimBLEUUID* uuidFilter = nullptr, + NimBLERemoteCharacteristic** out = nullptr) const; + static int characteristicDiscCB(uint16_t connHandle, const struct ble_gatt_error* error, const struct ble_gatt_chr* chr, void* arg); diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index dfa4b9ec..51bc3e19 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -56,18 +56,18 @@ class NimBLEUtils { static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout); static void taskRelease(const NimBLETaskData& taskData, int rc = 0); - template - static void getAttr(const NimBLEUUID& uuid, T* attr, const std::vector& vec, const std::function& getter) { + template + static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { // Check if already exists. for (const auto& v : vec) { if (v->getUUID() == uuid) { - attr = v; + *attr = v; return; } } // Exit if request failed or uuid was found. - if (!getter(&uuid, attr) || attr) { + if (!getter(&uuid, attr) || *attr) { return; } From 0fbf7103d8199b40f9304d6fb3623c8d55eb9cfa Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:21:43 -0500 Subject: [PATCH 04/12] fix(Utils): Include --- src/NimBLEUtils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index 51bc3e19..fe63a56c 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -22,6 +22,7 @@ #if defined(CONFIG_BT_ENABLED) # include "NimBLEUUID.h" # include "functional" +# include # include class NimBLEAddress; From dbd8f1e91fabed8074ef97f50777ab63841473de Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:57:01 -0500 Subject: [PATCH 05/12] change(Utils): Explicit template instantiation --- src/NimBLEUtils.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++ src/NimBLEUtils.h | 28 +------------------------ 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index 6e9f771e..b23a3fa2 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -20,6 +20,9 @@ # include "NimBLEUtils.h" # include "NimBLEAddress.h" +# include "NimBLERemoteService.h" +# include "NimBLERemoteDescriptor.h" +# include "NimBLERemoteCharacteristic.h" # include "NimBLELog.h" # if defined(CONFIG_NIMBLE_CPP_IDF) @@ -575,4 +578,51 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) { return NimBLEAddress{addr}; } // generateAddr +template +void NimBLEUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { + // Check if already exists. + for (const auto& v : vec) { + if (v->getUUID() == uuid) { + *attr = v; + return; + } + } + + // Exit if request failed or uuid was found. + if (!getter(&uuid, attr) || *attr) { + return; + } + + // Try again with 128 bit uuid if request succeeded with no uuid found. + if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { + NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); + getter(&uuid128, attr); + return; + } + // Try again with 16 bit uuid if request succeeded with no uuid found. + // If the uuid was 128 bit but not of the BLE base type this check will fail. + NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); + if (uuid16.bitSize() == BLE_UUID_TYPE_16) { + getter(&uuid16, attr); + } +} + +template void NimBLEUtils::getAttr( + const NimBLEUUID&, + NimBLERemoteService**, + const std::vector&, + const std::function&); + +template void NimBLEUtils::getAttr( + const NimBLEUUID&, + NimBLERemoteDescriptor**, + const std::vector&, + const std::function&); + +template void NimBLEUtils::getAttr( + const NimBLEUUID&, + NimBLERemoteCharacteristic**, + const std::vector&, + const std::function&); + #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index fe63a56c..bfd3e362 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -58,33 +58,7 @@ class NimBLEUtils { static void taskRelease(const NimBLETaskData& taskData, int rc = 0); template - static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { - // Check if already exists. - for (const auto& v : vec) { - if (v->getUUID() == uuid) { - *attr = v; - return; - } - } - - // Exit if request failed or uuid was found. - if (!getter(&uuid, attr) || *attr) { - return; - } - - // Try again with 128 bit uuid if request succeeded with no uuid found. - if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { - NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); - getter(&uuid128, attr); - return; - } - // Try again with 16 bit uuid if request succeeded with no uuid found. - // If the uuid was 128 bit but not of the BLE base type this check will fail. - NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); - if (uuid16.bitSize() == BLE_UUID_TYPE_16) { - getter(&uuid16, attr); - } - } + static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter); }; #endif // CONFIG_BT_ENABLED From 74c6c583d254558355eedb7c90a24d9e2c596e51 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:05:59 -0500 Subject: [PATCH 06/12] change(Utils): Compact instantiation --- src/NimBLEUtils.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index b23a3fa2..ec9817f0 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -607,22 +607,9 @@ void NimBLEUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector( - const NimBLEUUID&, - NimBLERemoteService**, - const std::vector&, - const std::function&); - -template void NimBLEUtils::getAttr( - const NimBLEUUID&, - NimBLERemoteDescriptor**, - const std::vector&, - const std::function&); - -template void NimBLEUtils::getAttr( - const NimBLEUUID&, - NimBLERemoteCharacteristic**, - const std::vector&, - const std::function&); +using svc = NimBLERemoteService; using chr = NimBLERemoteCharacteristic; using dsc = NimBLERemoteDescriptor; +template void NimBLEUtils::getAttr(const NimBLEUUID&, svc**, const std::vector&, const std::function&); +template void NimBLEUtils::getAttr(const NimBLEUUID&, chr**, const std::vector&, const std::function&); +template void NimBLEUtils::getAttr(const NimBLEUUID&, dsc**, const std::vector&, const std::function&); #endif // CONFIG_BT_ENABLED From 310a60a487933b12a51c08e60053746ad50de4c6 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Thu, 16 Jan 2025 21:40:31 -0500 Subject: [PATCH 07/12] Clean up PR --- src/NimBLEClient.cpp | 4 ++-- src/NimBLERemoteCharacteristic.cpp | 14 +++++++------- src/NimBLERemoteService.cpp | 4 ++-- src/NimBLEUtils.cpp | 9 +++++++-- src/NimBLEUtils.h | 6 +++--- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index ee90b27d..5d82e913 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -632,8 +632,8 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); NimBLERemoteService *pSvc = nullptr; - NimBLEUtils::getAttr(uuid, &pSvc, m_svcVec, [this](const NimBLEUUID* u, NimBLERemoteService** arg) { - return retrieveServices(u, arg); + NimBLEUtils::getAttr(uuid, &pSvc, m_svcVec, [this](const NimBLEUUID* u, NimBLERemoteService** svc) { + return retrieveServices(u, svc); }); NIMBLE_LOGD(LOG_TAG, "<< getService: %sfound", !pSvc ? "not " : ""); diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index f3a552c8..6b877dea 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -27,10 +27,10 @@ # include -struct desc_filter_t { - const NimBLEUUID* uuid; - void* taskData; -}; +typedef struct { + const NimBLEUUID* uuid; + void* taskData; +} desc_filter_t; static const char* LOG_TAG = "NimBLERemoteCharacteristic"; @@ -99,7 +99,7 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); NimBLETaskData taskData(const_cast(this)); - desc_filter_t filter = {uuidFilter, &taskData}; + desc_filter_t filter = {uuidFilter, &taskData}; const uint16_t handle = getHandle(); const uint16_t svcHandle = getRemoteService()->getEndHandle(); @@ -140,8 +140,8 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); NimBLERemoteDescriptor* pDsc = nullptr; - NimBLEUtils::getAttr(uuid, &pDsc, m_vDescriptors, [this](const NimBLEUUID* u, NimBLERemoteDescriptor** arg) { - return retrieveDescriptors(u, arg); + NimBLEUtils::getAttr(uuid, &pDsc, m_vDescriptors, [this](const NimBLEUUID* u, NimBLERemoteDescriptor** dsc) { + return retrieveDescriptors(u, dsc); }); NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", !pDsc ? "not " : ""); diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 3ca75edc..a19a3465 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -78,8 +78,8 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str()); NimBLERemoteCharacteristic* pChar = nullptr; - NimBLEUtils::getAttr(uuid, &pChar, m_vChars, [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** arg) { - return retrieveCharacteristics(u, arg); + NimBLEUtils::getAttr(uuid, &pChar, m_vChars, [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** chr) { + return retrieveCharacteristics(u, chr); }); NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChar ? "not " : ""); diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index ec9817f0..d5911b00 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -578,6 +578,13 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) { return NimBLEAddress{addr}; } // generateAddr +/** + * @brief Get an attribute matching a uuid. + * @param [in] uuid Search for this uuid. + * @param [in] attr Pointer to hold result. + * @param [in] vec Vector to search through before trying to get attribute. + * @param [in] getter Attribute getter function to call. + */ template void NimBLEUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { // Check if already exists. @@ -587,12 +594,10 @@ void NimBLEUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector # include # include @@ -56,9 +56,9 @@ class NimBLEUtils { static NimBLEAddress generateAddr(bool nrpa); static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout); static void taskRelease(const NimBLETaskData& taskData, int rc = 0); - template - static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter); + static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, + const std::function& getter); }; #endif // CONFIG_BT_ENABLED From 2c97bb8334a9cf8f52fc62ceeca1a0fdb522c59f Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:52:57 -0500 Subject: [PATCH 08/12] Created NimBLERemoteGattUtils and moved getAttr inside --- CMakeLists.txt | 1 + src/NimBLEClient.cpp | 4 +- src/NimBLERemoteCharacteristic.cpp | 4 +- src/NimBLERemoteGattUtils.cpp | 66 ++++++++++++++++++++++++++++++ src/NimBLERemoteGattUtils.h | 39 ++++++++++++++++++ src/NimBLERemoteService.cpp | 4 +- src/NimBLEUtils.cpp | 42 ------------------- src/NimBLEUtils.h | 6 --- 8 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 src/NimBLERemoteGattUtils.cpp create mode 100644 src/NimBLERemoteGattUtils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 60df8115..3cccafa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ idf_component_register( "src/NimBLEHIDDevice.cpp" "src/NimBLERemoteCharacteristic.cpp" "src/NimBLERemoteDescriptor.cpp" + "src/NimBLERemoteGattUtils.cpp" "src/NimBLERemoteService.cpp" "src/NimBLERemoteValueAttribute.cpp" "src/NimBLEScan.cpp" diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 5d82e913..f4ac514b 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -21,6 +21,7 @@ # include "NimBLEClient.h" # include "NimBLERemoteService.h" # include "NimBLERemoteCharacteristic.h" +# include "NimBLERemoteGattUtils.h" # include "NimBLEDevice.h" # include "NimBLELog.h" @@ -632,7 +633,8 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); NimBLERemoteService *pSvc = nullptr; - NimBLEUtils::getAttr(uuid, &pSvc, m_svcVec, [this](const NimBLEUUID* u, NimBLERemoteService** svc) { + NimBLERemoteGattUtils::getAttr(uuid, &pSvc, m_svcVec, + [this](const NimBLEUUID* u, NimBLERemoteService** svc) { return retrieveServices(u, svc); }); diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 6b877dea..46e8f86b 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -20,6 +20,7 @@ # include "NimBLERemoteCharacteristic.h" # include "NimBLERemoteDescriptor.h" +# include "NimBLERemoteGattUtils.h" # include "NimBLERemoteService.h" # include "NimBLEClient.h" # include "NimBLEUtils.h" @@ -140,7 +141,8 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); NimBLERemoteDescriptor* pDsc = nullptr; - NimBLEUtils::getAttr(uuid, &pDsc, m_vDescriptors, [this](const NimBLEUUID* u, NimBLERemoteDescriptor** dsc) { + NimBLERemoteGattUtils::getAttr(uuid, &pDsc, m_vDescriptors, + [this](const NimBLEUUID* u, NimBLERemoteDescriptor** dsc) { return retrieveDescriptors(u, dsc); }); diff --git a/src/NimBLERemoteGattUtils.cpp b/src/NimBLERemoteGattUtils.cpp new file mode 100644 index 00000000..657ffe1d --- /dev/null +++ b/src/NimBLERemoteGattUtils.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2020-2024 Ryan Powell and + * esp-nimble-cpp, NimBLE-Arduino contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nimconfig.h" +#if defined(CONFIG_BT_ENABLED) + +# include "NimBLERemoteGattUtils.h" +# include "NimBLEAddress.h" +# include "NimBLERemoteService.h" +# include "NimBLERemoteDescriptor.h" +# include "NimBLERemoteCharacteristic.h" + +/** + * @brief Get an attribute matching a uuid. + * @param [in] uuid Search for this uuid. + * @param [in] attr Pointer to hold result. + * @param [in] vec Vector to search through before trying to get attribute. + * @param [in] getter Attribute getter function to call. + */ +template +void NimBLERemoteGattUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { + // Check if already exists. + for (const auto& v : vec) { + if (v->getUUID() == uuid) { + *attr = v; + return; + } + } + // Exit if request failed or uuid was found. + if (!getter(&uuid, attr) || *attr) { + return; + } + // Try again with 128 bit uuid if request succeeded with no uuid found. + if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { + NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); + getter(&uuid128, attr); + return; + } + // Try again with 16 bit uuid if request succeeded with no uuid found. + // If the uuid was 128 bit but not of the BLE base type this check will fail. + NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); + if (uuid16.bitSize() == BLE_UUID_TYPE_16) { + getter(&uuid16, attr); + } +} + +using svc = NimBLERemoteService; using chr = NimBLERemoteCharacteristic; using dsc = NimBLERemoteDescriptor; +template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, svc**, const std::vector&, const std::function&); +template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, chr**, const std::vector&, const std::function&); +template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, dsc**, const std::vector&, const std::function&); + +#endif // CONFIG_BT_ENABLED diff --git a/src/NimBLERemoteGattUtils.h b/src/NimBLERemoteGattUtils.h new file mode 100644 index 00000000..47709d58 --- /dev/null +++ b/src/NimBLERemoteGattUtils.h @@ -0,0 +1,39 @@ +/* + * Copyright 2020-2024 Ryan Powell and + * esp-nimble-cpp, NimBLE-Arduino contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NIMBLE_CPP_GATT_UTILS_H_ +#define NIMBLE_CPP_GATT_UTILS_H_ + +#include "nimconfig.h" +#if defined(CONFIG_BT_ENABLED) +# include "NimBLEUUID.h" +# include +# include +# include + +/** + * @brief A BLE Remote GATT Utility class for getting an attribute. + */ +class NimBLERemoteGattUtils { + public: + template + static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, + const std::function& getter); +}; // NimBLERemoteGattUtils + +#endif /* CONFIG_BT_ENABLED */ +#endif /* NIMBLE_CPP_GATT_UTILS_H_ */ diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index a19a3465..7afe9a69 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -20,6 +20,7 @@ # include "NimBLERemoteService.h" # include "NimBLERemoteCharacteristic.h" +# include "NimBLERemoteGattUtils.h" # include "NimBLEClient.h" # include "NimBLEAttValue.h" # include "NimBLEUtils.h" @@ -78,7 +79,8 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str()); NimBLERemoteCharacteristic* pChar = nullptr; - NimBLEUtils::getAttr(uuid, &pChar, m_vChars, [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** chr) { + NimBLERemoteGattUtils::getAttr(uuid, &pChar, m_vChars, + [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** chr) { return retrieveCharacteristics(u, chr); }); diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index d5911b00..6e9f771e 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -20,9 +20,6 @@ # include "NimBLEUtils.h" # include "NimBLEAddress.h" -# include "NimBLERemoteService.h" -# include "NimBLERemoteDescriptor.h" -# include "NimBLERemoteCharacteristic.h" # include "NimBLELog.h" # if defined(CONFIG_NIMBLE_CPP_IDF) @@ -578,43 +575,4 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) { return NimBLEAddress{addr}; } // generateAddr -/** - * @brief Get an attribute matching a uuid. - * @param [in] uuid Search for this uuid. - * @param [in] attr Pointer to hold result. - * @param [in] vec Vector to search through before trying to get attribute. - * @param [in] getter Attribute getter function to call. - */ -template -void NimBLEUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { - // Check if already exists. - for (const auto& v : vec) { - if (v->getUUID() == uuid) { - *attr = v; - return; - } - } - // Exit if request failed or uuid was found. - if (!getter(&uuid, attr) || *attr) { - return; - } - // Try again with 128 bit uuid if request succeeded with no uuid found. - if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { - NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); - getter(&uuid128, attr); - return; - } - // Try again with 16 bit uuid if request succeeded with no uuid found. - // If the uuid was 128 bit but not of the BLE base type this check will fail. - NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); - if (uuid16.bitSize() == BLE_UUID_TYPE_16) { - getter(&uuid16, attr); - } -} - -using svc = NimBLERemoteService; using chr = NimBLERemoteCharacteristic; using dsc = NimBLERemoteDescriptor; -template void NimBLEUtils::getAttr(const NimBLEUUID&, svc**, const std::vector&, const std::function&); -template void NimBLEUtils::getAttr(const NimBLEUUID&, chr**, const std::vector&, const std::function&); -template void NimBLEUtils::getAttr(const NimBLEUUID&, dsc**, const std::vector&, const std::function&); - #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index 92637f0a..e56f568e 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -20,9 +20,6 @@ #include "nimconfig.h" #if defined(CONFIG_BT_ENABLED) -# include "NimBLEUUID.h" -# include -# include # include class NimBLEAddress; @@ -56,9 +53,6 @@ class NimBLEUtils { static NimBLEAddress generateAddr(bool nrpa); static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout); static void taskRelease(const NimBLETaskData& taskData, int rc = 0); - template - static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, - const std::function& getter); }; #endif // CONFIG_BT_ENABLED From 2e9a7dec2f0f2bd02794defcbe89f1490576f13b Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Mon, 20 Jan 2025 20:35:06 -0500 Subject: [PATCH 09/12] fail-fast: false --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b8994636..5a32875a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,7 @@ jobs: name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: # The version names here correspond to the versions of espressif/idf Docker image. # See https://hub.docker.com/r/espressif/idf/tags and From 013eccdf799ba1fa0364c9d8878872ccbf33da38 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Sun, 26 Jan 2025 15:02:22 -0500 Subject: [PATCH 10/12] Clean up --- .github/workflows/build.yml | 1 - src/NimBLERemoteCharacteristic.cpp | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a32875a..b8994636 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,6 @@ jobs: name: Build with ESP-IDF ${{ matrix.idf_ver }} for ${{ matrix.idf_target }} runs-on: ubuntu-latest strategy: - fail-fast: false matrix: # The version names here correspond to the versions of espressif/idf Docker image. # See https://hub.docker.com/r/espressif/idf/tags and diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 46e8f86b..ff9b03a8 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -103,18 +103,15 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte desc_filter_t filter = {uuidFilter, &taskData}; const uint16_t handle = getHandle(); const uint16_t svcHandle = getRemoteService()->getEndHandle(); + const uint16_t cltHandle = getClient()->getConnHandle(); - // If this is the last handle then there are no descriptors + // If this is the last handle then there are no more descriptors if (handle == svcHandle) { - NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found 0 descriptors."); + NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); return true; } - int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(), - handle, - svcHandle, - NimBLERemoteCharacteristic::descriptorDiscCB, - &filter); + int rc = ble_gattc_disc_all_dscs(cltHandle, handle, svcHandle, descriptorDiscCB, &filter); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; From ca0565beed9195f17c9ed149dcffa7388c6f0da0 Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Mon, 27 Jan 2025 02:25:59 -0500 Subject: [PATCH 11/12] Update --- src/NimBLEClient.cpp | 25 +++++++++----------- src/NimBLEClient.h | 12 +++++----- src/NimBLERemoteCharacteristic.cpp | 27 ++++++++++----------- src/NimBLERemoteCharacteristic.h | 2 +- src/NimBLERemoteService.cpp | 38 +++++++++++++----------------- src/NimBLERemoteService.h | 10 ++++---- 6 files changed, 53 insertions(+), 61 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index f4ac514b..b2e0ed9c 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -692,20 +692,17 @@ bool NimBLEClient::discoverAttributes() { * * Here we ask the server for its set of services and wait until we have received them all. * @return true on success otherwise false if an error occurred */ -bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteService **out) { +bool NimBLEClient::retrieveServices(const NimBLEUUID* uuid, NimBLERemoteService **out) { + NIMBLE_LOGD(LOG_TAG, ">> retrieveServices()"); + NimBLETaskData taskData(this); if (!isConnected()) { NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting"); return false; } - int rc = 0; - NimBLETaskData taskData(this); - - if (uuidFilter == nullptr) { - rc = ble_gattc_disc_all_svcs(m_connHandle, NimBLEClient::serviceDiscCB, &taskData); - } else { - rc = ble_gattc_disc_svc_by_uuid(m_connHandle, uuidFilter->getBase(), NimBLEClient::serviceDiscCB, &taskData); - } + int rc = (uuid == nullptr) + ? ble_gattc_disc_all_svcs(m_connHandle, svcDiscCB, &taskData) + : ble_gattc_disc_svc_by_uuid(m_connHandle, uuid->getBase(), svcDiscCB, &taskData); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); @@ -731,10 +728,10 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuidFilter, NimBLERemoteSe * @details When a service is found or there is none left or there was an error * the API will call this and report findings. */ -int NimBLEClient::serviceDiscCB(uint16_t connHandle, - const struct ble_gatt_error* error, - const struct ble_gatt_svc* service, - void* arg) { +int NimBLEClient::svcDiscCB(uint16_t connHandle, + const struct ble_gatt_error* error, + const struct ble_gatt_svc* service, + void* arg) { const int rc = error->status; auto pTaskData = (NimBLETaskData*)arg; auto pClient = (NimBLEClient*)pTaskData->m_pInstance; @@ -751,7 +748,7 @@ int NimBLEClient::serviceDiscCB(uint16_t connHandle, } NimBLEUtils::taskRelease(*pTaskData, error->status); - NIMBLE_LOGD(LOG_TAG, "<< Service Discovered%s", (rc == BLE_HS_ENOTCONN) ? "; Disconnected" : ""); + NIMBLE_LOGD(LOG_TAG, "<< Service Discovered%s", (rc == BLE_HS_ENOTCONN) ? "; Not connected" : ""); return error->status; } // serviceDiscCB diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index f94204da..3373e76a 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -116,13 +116,13 @@ class NimBLEClient { NimBLEClient(const NimBLEClient&) = delete; NimBLEClient& operator=(const NimBLEClient&) = delete; - bool retrieveServices(const NimBLEUUID* uuidFilter = nullptr, NimBLERemoteService **out = nullptr); - static int handleGapEvent(struct ble_gap_event* event, void* arg); + bool retrieveServices(const NimBLEUUID* uuid = nullptr, NimBLERemoteService **out = nullptr); static int exchangeMTUCB(uint16_t connHandle, const ble_gatt_error* error, uint16_t mtu, void* arg); - static int serviceDiscCB(uint16_t connHandle, - const struct ble_gatt_error* error, - const struct ble_gatt_svc* service, - void* arg); + static int handleGapEvent(struct ble_gap_event* event, void* arg); + static int svcDiscCB(uint16_t connHandle, + const struct ble_gatt_error* error, + const struct ble_gatt_svc* service, + void* arg); NimBLEAddress m_peerAddress; mutable int m_lastErr; diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index ff9b03a8..b75b8dd1 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -63,11 +63,11 @@ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() { /** * @brief Callback used by the API when a descriptor is discovered or search complete. */ -int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle, - const ble_gatt_error* error, - uint16_t chrHandle, - const ble_gatt_dsc* dsc, - void* arg) { +int NimBLERemoteCharacteristic::dscDiscCB(uint16_t connHandle, + const ble_gatt_error* error, + uint16_t chrHandle, + const ble_gatt_dsc* dsc, + void* arg) { int rc = error->status; auto filter = (desc_filter_t*)arg; auto pTaskData = (NimBLETaskData*)filter->taskData; @@ -94,24 +94,23 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t connHandle, /** * @brief Populate the descriptors (if any) for this characteristic. * @param [in] filter Structure containing pointers to descriptor, UUID, and task data. + * @param out Pointer to hold result. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter, NimBLERemoteDescriptor** out) const { +bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuid, NimBLERemoteDescriptor** out) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); - NimBLETaskData taskData(const_cast(this)); - desc_filter_t filter = {uuidFilter, &taskData}; - const uint16_t handle = getHandle(); - const uint16_t svcHandle = getRemoteService()->getEndHandle(); - const uint16_t cltHandle = getClient()->getConnHandle(); - + desc_filter_t filter = {uuid, &taskData}; + const uint16_t endHandle = getRemoteService()->getEndHandle(); + const uint16_t connHandle = getClient()->getConnHandle(); + const uint16_t starthandle = getHandle(); // If this is the last handle then there are no more descriptors - if (handle == svcHandle) { + if (starthandle == endHandle) { NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); return true; } - int rc = ble_gattc_disc_all_dscs(cltHandle, handle, svcHandle, descriptorDiscCB, &filter); + int rc = ble_gattc_disc_all_dscs(connHandle, starthandle, endHandle, dscDiscCB, &filter); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index bc3c2941..2f69e020 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -68,7 +68,7 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute { bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr, NimBLERemoteDescriptor** out = nullptr) const; - static int descriptorDiscCB( + static int dscDiscCB( uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg); const NimBLERemoteService* m_pRemoteService{nullptr}; diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 7afe9a69..36a9cd2b 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -108,10 +108,10 @@ const std::vector& NimBLERemoteService::getCharacte * @brief Callback for Characteristic discovery. * @return success == 0 or error code. */ -int NimBLERemoteService::characteristicDiscCB(uint16_t connHandle, - const ble_gatt_error* error, - const ble_gatt_chr* chr, - void* arg) { +int NimBLERemoteService::chrDiscCB(uint16_t connHandle, + const ble_gatt_error* error, + const ble_gatt_chr* chr, + void* arg) { const int rc = error->status; auto pTaskData = (NimBLETaskData*)arg; const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance; @@ -137,26 +137,22 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t connHandle, * This function will not return until we have all the characteristics. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuidFilter, NimBLERemoteCharacteristic** out) const { - NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics()"); +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuid, NimBLERemoteCharacteristic** out) const { + NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); NimBLETaskData taskData(const_cast(this)); - int rc = 0; - - if (uuidFilter == nullptr) { - rc = ble_gattc_disc_all_chrs(m_pClient->getConnHandle(), - getHandle(), - getEndHandle(), - NimBLERemoteService::characteristicDiscCB, - &taskData); - } else { - rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnHandle(), - getHandle(), - getEndHandle(), - uuidFilter->getBase(), - NimBLERemoteService::characteristicDiscCB, - &taskData); + const uint16_t hdlConn = m_pClient->getConnHandle(); + const uint16_t hdlEnd = getEndHandle(); + const uint16_t hdlStart = getHandle(); + // If this is the last handle then there are no more characteristics + if (hdlStart == hdlEnd) { + NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics(): found %d characteristics.", m_vChars.size()); + return true; } + int rc = (uuid == nullptr) + ? ble_gattc_disc_all_chrs(hdlConn, hdlStart, hdlEnd, chrDiscCB, &taskData) + : ble_gattc_disc_chrs_by_uuid(hdlConn, hdlStart, hdlEnd, uuid->getBase(), chrDiscCB, &taskData); + if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_chrs rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index 12333564..d5c5f5f6 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -53,12 +53,12 @@ class NimBLERemoteService : public NimBLEAttribute { NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service); ~NimBLERemoteService(); - bool retrieveCharacteristics(const NimBLEUUID* uuidFilter = nullptr, + bool retrieveCharacteristics(const NimBLEUUID* uuid = nullptr, NimBLERemoteCharacteristic** out = nullptr) const; - static int characteristicDiscCB(uint16_t connHandle, - const struct ble_gatt_error* error, - const struct ble_gatt_chr* chr, - void* arg); + static int chrDiscCB(uint16_t connHandle, + const struct ble_gatt_error* error, + const struct ble_gatt_chr* chr, + void* arg); mutable std::vector m_vChars{}; NimBLEClient* m_pClient{nullptr}; From f46d665b81f95afec3e29c95b20ed91c4c3bac7a Mon Sep 17 00:00:00 2001 From: thekurtovic <40248206+thekurtovic@users.noreply.github.com> Date: Tue, 28 Jan 2025 16:55:56 -0500 Subject: [PATCH 12/12] Refactor template --- src/NimBLEClient.cpp | 20 +++++++------------- src/NimBLEClient.h | 2 +- src/NimBLERemoteCharacteristic.cpp | 14 ++++++-------- src/NimBLERemoteCharacteristic.h | 3 +-- src/NimBLERemoteGattUtils.cpp | 25 +++++++++++++------------ src/NimBLERemoteGattUtils.h | 4 ++-- src/NimBLERemoteService.cpp | 18 ++++++++---------- src/NimBLERemoteService.h | 3 +-- 8 files changed, 39 insertions(+), 50 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index b2e0ed9c..a3700dbc 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -631,11 +631,10 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { */ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); - NimBLERemoteService *pSvc = nullptr; - NimBLERemoteGattUtils::getAttr(uuid, &pSvc, m_svcVec, - [this](const NimBLEUUID* u, NimBLERemoteService** svc) { - return retrieveServices(u, svc); + auto pSvc = NimBLERemoteGattUtils::getAttr + (uuid, m_svcVec, [this](const NimBLEUUID* u) { + return retrieveServices(u); }); NIMBLE_LOGD(LOG_TAG, "<< getService: %sfound", !pSvc ? "not " : ""); @@ -652,11 +651,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { const std::vector& NimBLEClient::getServices(bool refresh) { if (refresh) { deleteServices(); - if (!retrieveServices()) { - NIMBLE_LOGE(LOG_TAG, "Error: Failed to get services"); - } else { - NIMBLE_LOGI(LOG_TAG, "Found %d services", m_svcVec.size()); - } + retrieveServices(); } return m_svcVec; @@ -692,7 +687,7 @@ bool NimBLEClient::discoverAttributes() { * * Here we ask the server for its set of services and wait until we have received them all. * @return true on success otherwise false if an error occurred */ -bool NimBLEClient::retrieveServices(const NimBLEUUID* uuid, NimBLERemoteService **out) { +bool NimBLEClient::retrieveServices(const NimBLEUUID* uuid) { NIMBLE_LOGD(LOG_TAG, ">> retrieveServices()"); NimBLETaskData taskData(this); if (!isConnected()) { @@ -705,7 +700,7 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuid, NimBLERemoteService : ble_gattc_disc_svc_by_uuid(m_connHandle, uuid->getBase(), svcDiscCB, &taskData); if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + NIMBLE_LOGE_RC(rc, LOG_TAG, "ble_gattc_disc_all_svcs"); m_lastErr = rc; return false; } @@ -713,12 +708,11 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID* uuid, NimBLERemoteService NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; if (rc != BLE_HS_EDONE) { + NIMBLE_LOGE_RC(rc, LOG_TAG, "Could not retrieve services"); m_lastErr = rc; - NIMBLE_LOGE(LOG_TAG, "Could not retrieve services, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); return false; } - *out = m_svcVec.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveServices(): found %d services.", m_svcVec.size()); return true; } // getServices diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index 3373e76a..66967922 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -116,7 +116,7 @@ class NimBLEClient { NimBLEClient(const NimBLEClient&) = delete; NimBLEClient& operator=(const NimBLEClient&) = delete; - bool retrieveServices(const NimBLEUUID* uuid = nullptr, NimBLERemoteService **out = nullptr); + bool retrieveServices(const NimBLEUUID* uuid = nullptr); static int exchangeMTUCB(uint16_t connHandle, const ble_gatt_error* error, uint16_t mtu, void* arg); static int handleGapEvent(struct ble_gap_event* event, void* arg); static int svcDiscCB(uint16_t connHandle, diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index b75b8dd1..d3b20d1e 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -97,7 +97,7 @@ int NimBLERemoteCharacteristic::dscDiscCB(uint16_t connHandle, * @param out Pointer to hold result. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuid, NimBLERemoteDescriptor** out) const { +bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuid) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str()); NimBLETaskData taskData(const_cast(this)); desc_filter_t filter = {uuid, &taskData}; @@ -112,18 +112,17 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuid, Nim int rc = ble_gattc_disc_all_dscs(connHandle, starthandle, endHandle, dscDiscCB, &filter); if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + NIMBLE_LOGE_RC(rc, LOG_TAG, "ble_gattc_disc_all_dscs"); return false; } NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; if (rc != BLE_HS_EDONE) { - NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + NIMBLE_LOGE_RC(rc, LOG_TAG, "<< retrieveDescriptors(): failed"); return false; } - *out = m_vDescriptors.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size()); return true; } // retrieveDescriptors @@ -135,11 +134,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuid, Nim */ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const { NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); - NimBLERemoteDescriptor* pDsc = nullptr; - NimBLERemoteGattUtils::getAttr(uuid, &pDsc, m_vDescriptors, - [this](const NimBLEUUID* u, NimBLERemoteDescriptor** dsc) { - return retrieveDescriptors(u, dsc); + auto pDsc = NimBLERemoteGattUtils::getAttr + (uuid, m_vDescriptors, [this](const NimBLEUUID* u) { + return retrieveDescriptors(u); }); NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", !pDsc ? "not " : ""); diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 2f69e020..6f86bb22 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -65,8 +65,7 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute { ~NimBLERemoteCharacteristic(); bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const; - bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr, - NimBLERemoteDescriptor** out = nullptr) const; + bool retrieveDescriptors(const NimBLEUUID* uuid = nullptr) const; static int dscDiscCB( uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg); diff --git a/src/NimBLERemoteGattUtils.cpp b/src/NimBLERemoteGattUtils.cpp index 657ffe1d..041da11a 100644 --- a/src/NimBLERemoteGattUtils.cpp +++ b/src/NimBLERemoteGattUtils.cpp @@ -27,40 +27,41 @@ /** * @brief Get an attribute matching a uuid. * @param [in] uuid Search for this uuid. - * @param [in] attr Pointer to hold result. * @param [in] vec Vector to search through before trying to get attribute. * @param [in] getter Attribute getter function to call. */ template -void NimBLERemoteGattUtils::getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, const std::function& getter) { +T* NimBLERemoteGattUtils::getAttr(const NimBLEUUID& uuid, const std::vector& vec, const std::function& getter) { // Check if already exists. for (const auto& v : vec) { if (v->getUUID() == uuid) { - *attr = v; - return; + return v; } } // Exit if request failed or uuid was found. - if (!getter(&uuid, attr) || *attr) { - return; + if (!getter(&uuid)) { + return nullptr; } // Try again with 128 bit uuid if request succeeded with no uuid found. if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) { NimBLEUUID uuid128 = NimBLEUUID(uuid).to128(); - getter(&uuid128, attr); - return; + bool found = getter(&uuid128); + return found ? vec.back() : nullptr; } // Try again with 16 bit uuid if request succeeded with no uuid found. // If the uuid was 128 bit but not of the BLE base type this check will fail. NimBLEUUID uuid16 = NimBLEUUID(uuid).to16(); if (uuid16.bitSize() == BLE_UUID_TYPE_16) { - getter(&uuid16, attr); + bool found = getter(&uuid16); + return found ? vec.back() : nullptr; } + + return nullptr; } using svc = NimBLERemoteService; using chr = NimBLERemoteCharacteristic; using dsc = NimBLERemoteDescriptor; -template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, svc**, const std::vector&, const std::function&); -template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, chr**, const std::vector&, const std::function&); -template void NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, dsc**, const std::vector&, const std::function&); +template svc* NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, const std::vector&, const std::function&); +template chr* NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, const std::vector&, const std::function&); +template dsc* NimBLERemoteGattUtils::getAttr(const NimBLEUUID&, const std::vector&, const std::function&); #endif // CONFIG_BT_ENABLED diff --git a/src/NimBLERemoteGattUtils.h b/src/NimBLERemoteGattUtils.h index 47709d58..285929f3 100644 --- a/src/NimBLERemoteGattUtils.h +++ b/src/NimBLERemoteGattUtils.h @@ -31,8 +31,8 @@ class NimBLERemoteGattUtils { public: template - static void getAttr(const NimBLEUUID& uuid, T** attr, const std::vector& vec, - const std::function& getter); + static T* getAttr(const NimBLEUUID& uuid, const std::vector& vec, + const std::function& getter); }; // NimBLERemoteGattUtils #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 36a9cd2b..422cfdda 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -77,15 +77,14 @@ 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; - NimBLERemoteGattUtils::getAttr(uuid, &pChar, m_vChars, - [this](const NimBLEUUID* u, NimBLERemoteCharacteristic** chr) { - return retrieveCharacteristics(u, chr); + auto pChr = NimBLERemoteGattUtils::getAttr + (uuid, m_vChars, [this](const NimBLEUUID* u) { + return retrieveCharacteristics(u); }); - NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChar ? "not " : ""); - return pChar; + NIMBLE_LOGD(LOG_TAG, "<< getCharacteristic: %sfound", !pChr ? "not " : ""); + return pChr; } // getCharacteristic /** @@ -137,7 +136,7 @@ int NimBLERemoteService::chrDiscCB(uint16_t connHandle, * This function will not return until we have all the characteristics. * @return True if successfully retrieved, success = BLE_HS_EDONE. */ -bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuid, NimBLERemoteCharacteristic** out) const { +bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuid) const { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); NimBLETaskData taskData(const_cast(this)); const uint16_t hdlConn = m_pClient->getConnHandle(); @@ -154,18 +153,17 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID* uuid, NimBLE : ble_gattc_disc_chrs_by_uuid(hdlConn, hdlStart, hdlEnd, uuid->getBase(), chrDiscCB, &taskData); if (rc != 0) { - NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_chrs rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + NIMBLE_LOGE_RC(rc, LOG_TAG, "ble_gattc_disc_chrs rc"); return false; } NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER); rc = taskData.m_flags; if (rc != BLE_HS_EDONE) { - NIMBLE_LOGE(LOG_TAG, "<< retrieveCharacteristics(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); + NIMBLE_LOGE_RC(rc, LOG_TAG, "<< retrieveCharacteristics(): failed"); return false; } - *out = m_vChars.back(); NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics(): found %d characteristics.", m_vChars.size()); return true; } // retrieveCharacteristics diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index d5c5f5f6..605a6d52 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -53,8 +53,7 @@ class NimBLERemoteService : public NimBLEAttribute { NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service); ~NimBLERemoteService(); - bool retrieveCharacteristics(const NimBLEUUID* uuid = nullptr, - NimBLERemoteCharacteristic** out = nullptr) const; + bool retrieveCharacteristics(const NimBLEUUID* uuid = nullptr) const; static int chrDiscCB(uint16_t connHandle, const struct ble_gatt_error* error, const struct ble_gatt_chr* chr,