diff --git a/API_DIFFERENCES.md b/API_DIFFERENCES.md index d503569..26ad02c 100644 --- a/API_DIFFERENCES.md +++ b/API_DIFFERENCES.md @@ -100,7 +100,7 @@ The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a poin Defined as: ``` bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true); -bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true); +bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true); ``` If set to false the client will use the services database it retrieved from the peripheral last time it connected. This allows for faster connections and power saving if the devices just dropped connection and want to reconnect. @@ -111,6 +111,17 @@ NimBLERemoteCharacteristic::registerForNotify(); ``` Now return true or false to indicate success or failure so you can choose to disconnect or try again. +``` +NimBLEClient::getServices() +NimBLERemoteService::getCharacteristics() +``` +Now return a pointer to a `std::vector` of the respective object database instead of `std::map`. + +`NimBLERemoteService::getCharacteristicsByHandle()` +Has been removed from the API as it is no longer maintained in the library. + +The last two above changes reduce the heap usage significantly with minimal application code adjustments. + #### Client Security: The client will automatically initiate security when the peripheral responds that it's required. The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below. diff --git a/README.md b/README.md index f7ea898..d25cfa4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,14 @@ # *** UPDATE *** -Client long read/write characteristics/descriptors now working. -We are now nearing 100% replacement of the original cpp_utils BLE library :smile: +**Breaking change:** Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database. + +This change will affect your application code if you use `NimBLEClient::getServices()` or `NimBLERemoteService::getCharacteristics()` +in your application as they now return a pointer to `std::vector` of the respective attributes. +In addition `NimBLERemoteService::getCharacteristicsByHandle()` has been removed as it is no longer maintained in the library. + +These changes were necessary due to the amount of resources required to use `std::map`, it was not justifed by any benfit it provided. + +It is expected that there will be minimal impact on most applications, if you need help adjusting your code please create an issue. # esp-nimble-cpp NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the @nkolban cpp_uitls API. diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 9e24298..a72b4e3 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -43,8 +43,8 @@ static NimBLEClientCallbacks defaultCallbacks; * Since there is a hierarchical relationship here, we will have the idea that from a NimBLERemoteService will own * zero or more remote characteristics and a NimBLERemoteCharacteristic will own zero or more remote NimBLEDescriptors. * - * We will assume that a NimBLERemoteService contains a map that maps NimBLEUUIDs to the set of owned characteristics - * and that a NimBLECharacteristic contains a map that maps NimBLEUUIDs to the set of owned descriptors. + * We will assume that a NimBLERemoteService contains a vector of owned characteristics + * and that a NimBLECharacteristic contains a vector of owned descriptors. * * */ @@ -90,10 +90,11 @@ NimBLEClient::~NimBLEClient() { void NimBLEClient::clearServices() { NIMBLE_LOGD(LOG_TAG, ">> clearServices"); // Delete all the services. - for (auto &myPair : m_servicesMap) { - delete myPair.second; + for(auto &it: m_servicesVector) { + delete it; } - m_servicesMap.clear(); + m_servicesVector.clear(); + m_haveServices = false; NIMBLE_LOGD(LOG_TAG, "<< clearServices"); } // clearServices @@ -368,23 +369,24 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) { if (!m_haveServices) { return nullptr; } - std::string uuidStr = uuid.toString(); - for (auto &myPair : m_servicesMap) { - if (myPair.first == uuidStr) { + + for(auto &it: m_servicesVector) { + if(it->getUUID() == uuid) { NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); - return myPair.second; + return it; } } + NIMBLE_LOGD(LOG_TAG, "<< getService: not found"); return nullptr; } // getService /** - * @Get a pointer to the map of found services. + * @Get a pointer to the vector of found services. */ -std::map* NimBLEClient::getServices() { - return &m_servicesMap; +std::vector* NimBLEClient::getServices() { + return &m_servicesVector; } @@ -425,8 +427,8 @@ bool NimBLEClient::retrieveServices() { // If sucessful, remember that we now have services. m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0); if(m_haveServices){ - for (auto &myPair : m_servicesMap) { - if(!m_isConnected || !myPair.second->retrieveCharacteristics()) { + for (auto &it: m_servicesVector) { + if(!m_isConnected || !it->retrieveCharacteristics()) { NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting"); return false; } @@ -463,9 +465,9 @@ int NimBLEClient::serviceDiscoveredCB( switch (error->status) { case 0: { - // Found a service - add it to the map + // Found a service - add it to the vector NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service); - peer->m_servicesMap.insert(std::pair(pRemoteService->getUUID().toString(), pRemoteService)); + peer->m_servicesVector.push_back(pRemoteService); break; } case BLE_HS_EDONE:{ @@ -662,20 +664,25 @@ uint16_t NimBLEClient::getMTU() { if(!client->m_haveServices) return 0; - for(auto &sPair : client->m_servicesMap){ + for(auto &it: client->m_servicesVector) { // Dont waste cycles searching services without this handle in their range - if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) { + if(it->getEndHandle() < event->notify_rx.attr_handle) { continue; } - auto cMap = sPair.second->getCharacteristicsByHandle(); - NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", sPair.second->getUUID().toString().c_str(),event->notify_rx.attr_handle); - auto characteristic = cMap->find(event->notify_rx.attr_handle); - if(characteristic != cMap->end()) { - NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str()); - if (characteristic->second->m_notifyCallback != nullptr) { - NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str()); - characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication); + auto cVector = it->getCharacteristics(); + NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", it->getUUID().toString().c_str(),event->notify_rx.attr_handle); + auto characteristic = cVector->cbegin(); + for(; characteristic != cVector->cend(); ++characteristic) { + if((*characteristic)->m_handle == event->notify_rx.attr_handle) break; + } + + if(characteristic != cVector->cend()) { + NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str()); + + if ((*characteristic)->m_notifyCallback != nullptr) { + NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", (*characteristic)->toString().c_str()); + (*characteristic)->m_notifyCallback(*characteristic, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication); } break; @@ -851,8 +858,9 @@ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, b std::string NimBLEClient::toString() { std::string res = "peer address: " + m_peerAddress.toString(); res += "\nServices:\n"; - for (auto &myPair : m_servicesMap) { - res += myPair.second->toString() + "\n"; + + for(auto &it: m_servicesVector) { + res += it->toString() + "\n"; } return res; diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index b140d95..97a7ab8 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -24,7 +24,7 @@ #include "NimBLEAdvertisedDevice.h" #include "NimBLERemoteService.h" -#include +#include #include class NimBLERemoteService; @@ -41,9 +41,10 @@ public: int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // Disconnect from the remote BLE Server NimBLEAddress getPeerAddress(); // Get the address of the remote BLE Server int getRssi(); // Get the RSSI of the remote BLE Server - std::map* getServices(); // Get a map of the services offered by the remote BLE Server - NimBLERemoteService* getService(const char* uuid); // Get a reference to a specified service offered by the remote BLE server. - NimBLERemoteService* getService(const NimBLEUUID &uuid); // Get a reference to a specified service offered by the remote BLE server. + + std::vector* getServices(); // Get a vector of the services offered by the remote BLE Server + NimBLERemoteService* getService(const char* uuid); // Get a reference to a specified service offered by the remote BLE server. + NimBLERemoteService* getService(const NimBLEUUID &uuid); // Get a reference to a specified service offered by the remote BLE server. std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID); // Get the value of a given characteristic at a given service. bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, const std::string &value); // Set the value of a given characteristic at a given service. bool isConnected(); // Return true if we are connected. @@ -87,7 +88,7 @@ private: FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt"); FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security"); - std::map m_servicesMap; + std::vector m_servicesVector; private: friend class NimBLEClientCallbacks; diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 86bf7ee..52b98f2 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -157,10 +157,9 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle, switch (error->status) { case 0: { - // Found a descriptor - add it to the map + // Found a descriptor - add it to the vector NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc); - characteristic->m_descriptorMap.insert(std::pair(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor)); - + characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor); break; } case BLE_HS_EDONE:{ @@ -212,15 +211,15 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) { } return true; - NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size()); + NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size()); } // getDescriptors /** - * @brief Retrieve the map of descriptors keyed by UUID. - */ -std::map* NimBLERemoteCharacteristic::getDescriptors() { - return &m_descriptorMap; + * @brief Retrieve the vector of descriptors. + */ +std::vector* NimBLERemoteCharacteristic::getDescriptors() { + return &m_descriptorVector; } // getDescriptors @@ -248,12 +247,12 @@ uint16_t NimBLERemoteCharacteristic::getDefHandle() { */ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) { NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str()); - std::string v = uuid.toString(); - for (auto &myPair : m_descriptorMap) { - if (myPair.first == v) { - NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found"); - return myPair.second; - } + + for(auto &it: m_descriptorVector) { + if(it->getUUID() == uuid) { + NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found"); + return it; + } } NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found"); return nullptr; @@ -444,19 +443,18 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac /** - * @brief Delete the descriptors in the descriptor map. - * We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors - * object references. Since we allocated these in this class, we are also responsible for deleteing - * them. This method does just that. + * @brief Delete the descriptors in the descriptor vector. + * We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors + * object references. Since we allocated these in this class, we are also responsible for deleteing + * them. This method does just that. * @return N/A. */ void NimBLERemoteCharacteristic::removeDescriptors() { - // Iterate through all the descriptors releasing their storage and erasing them from the map. - for (auto &myPair : m_descriptorMap) { - m_descriptorMap.erase(myPair.first); - delete myPair.second; + // Iterate through all the descriptors releasing their storage and erasing them from the vector. + for(auto &it: m_descriptorVector) { + delete it; } - m_descriptorMap.clear(); // Technically not neeeded, but just to be sure. + m_descriptorVector.clear(); } // removeCharacteristics @@ -478,8 +476,8 @@ std::string NimBLERemoteCharacteristic::toString() { snprintf(val, sizeof(val), "%02x", m_charProp); res += val; - for (auto &myPair : m_descriptorMap) { - res += "\n" + myPair.second->toString(); + for(auto &it: m_descriptorVector) { + res += "\n" + it->toString(); } return res; @@ -645,8 +643,8 @@ size_t NimBLERemoteCharacteristic::getDataLength() { void NimBLERemoteCharacteristic::releaseSemaphores() { - for (auto &dPair : m_descriptorMap) { - dPair.second->releaseSemaphores(); + for (auto &it: m_descriptorVector) { + it->releaseSemaphores(); } m_semaphoreWriteCharEvt.give(1); m_semaphoreGetDescEvt.give(1); diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 2c9cdb3..b4748fe 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -26,7 +26,7 @@ #include "NimBLERemoteDescriptor.h" //#include -#include +#include class NimBLERemoteService; class NimBLERemoteDescriptor; @@ -49,7 +49,7 @@ public: bool canWrite(); bool canWriteNoResponse(); NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid); - std::map* getDescriptors(); + std::vector* getDescriptors(); uint16_t getHandle(); uint16_t getDefHandle(); NimBLEUUID getUUID(); @@ -98,8 +98,8 @@ private: size_t m_dataLen; notify_callback m_notifyCallback; - // We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID. - std::map m_descriptorMap; + // We maintain a vector of descriptors owned by this characteristic. + std::vector m_descriptorVector; }; // BLERemoteCharacteristic #endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index 1832793..624de63 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -81,10 +81,9 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u */ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) { if (m_haveCharacteristics) { - std::string v = uuid.toString(); - for (auto &myPair : m_characteristicMap) { - if (myPair.first == v) { - return myPair.second; + for(auto &it: m_characteristicVector) { + if(it->getUUID() == uuid) { + return it; } } } @@ -112,10 +111,9 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, switch (error->status) { case 0: { - // Found a service - add it to the map + // Found a service - add it to the vector NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr); - service->m_characteristicMap.insert(std::pair(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic)); - service->m_characteristicMapByHandle.insert(std::pair(chr->val_handle, pRemoteCharacteristic)); + service->m_characteristicVector.push_back(pRemoteCharacteristic); break; } case BLE_HS_EDONE:{ @@ -171,17 +169,18 @@ bool NimBLERemoteService::retrieveCharacteristics() { m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0); if(m_haveCharacteristics){ uint16_t endHdl = 0xFFFF; - NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics", m_characteristicMapByHandle.size()); - for (auto it = m_characteristicMapByHandle.cbegin(); it != m_characteristicMapByHandle.cend(); ++it) { - NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle()); + + NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics", m_characteristicVector.size()); + for(auto it = m_characteristicVector.cbegin(); it != m_characteristicVector.cend(); ++it) { + NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it)->getUUID().toString().c_str(), (*it)->getHandle(), (*it)->getDefHandle()); // The descriptor handle is between this characteristic val_handle and the next ones def_handle // so make the end of the scan at the handle before the next characteristic def_handle // Make sure we don't go past the service end handle - if(++it != m_characteristicMapByHandle.cend()){ - NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(),(*it).second->getDefHandle()); + if(++it != m_characteristicVector.cend()){ + NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it)->getUUID().toString().c_str(), (*it)->getHandle(),(*it)->getDefHandle()); - endHdl = (*it).second->getDefHandle()-1; + endHdl = (*it)->getDefHandle()-1; } else{ NIMBLE_LOGD(LOG_TAG, "END CHARS"); @@ -190,8 +189,8 @@ bool NimBLERemoteService::retrieveCharacteristics() { --it; //If there is no handles between this characteristic and the next there is no descriptor so skip to the next - if((*it).second->getHandle() != endHdl){ - if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) { + if((*it)->getHandle() != endHdl){ + if(!m_pClient->m_isConnected || !(*it)->retrieveDescriptors(endHdl)) { return false; } } @@ -209,23 +208,14 @@ bool NimBLERemoteService::retrieveCharacteristics() { /** - * @brief Retrieve a map of all the characteristics of this service. - * @return A map of all the characteristics of this service. + * @brief Retrieve a vector of all the characteristics of this service. + * @return A vector of all the characteristics of this service. */ -std::map* NimBLERemoteService::getCharacteristics() { - return &m_characteristicMap; +std::vector* NimBLERemoteService::getCharacteristics() { + return &m_characteristicVector; } // getCharacteristics -/** - * @brief Retrieve a map of all the characteristics of this service. - * @return A map of all the characteristics of this service. - */ -std::map* NimBLERemoteService::getCharacteristicsByHandle() { - return &m_characteristicMapByHandle; -} // getCharacteristicsByHandle - - /** * @brief Get the client associated with this service. * @return A reference to the client associated with this service. @@ -301,20 +291,17 @@ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const s /** - * @brief Delete the characteristics in the characteristics map. - * We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic - * object references. Since we allocated these in this class, we are also responsible for deleteing - * them. This method does just that. + * @brief Delete the characteristics in the characteristics vector. + * We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic + * object references. Since we allocated these in this class, we are also responsible for deleting + * them. This method does just that. * @return N/A. */ void NimBLERemoteService::removeCharacteristics() { - m_characteristicMap.clear(); // Clear the map - - for (auto &myPair : m_characteristicMapByHandle) { - delete myPair.second; + for(auto &it: m_characteristicVector) { + delete it; } - m_characteristicMapByHandle.clear(); // Clear the map - + m_characteristicVector.clear(); // Clear the vector } // removeCharacteristics @@ -338,8 +325,8 @@ std::string NimBLERemoteService::toString() { res += " 0x"; res += val; - for (auto &myPair : m_characteristicMap) { - res += "\n" + myPair.second->toString(); + for (auto &it: m_characteristicVector) { + res += "\n" + it->toString(); } return res; @@ -351,8 +338,8 @@ std::string NimBLERemoteService::toString() { * Will release all characteristic and subsequently all descriptor semaphores for this service. */ void NimBLERemoteService::releaseSemaphores() { - for (auto &cPair : m_characteristicMapByHandle) { - cPair.second->releaseSemaphores(); + for(auto &it: m_characteristicVector) { + it->releaseSemaphores(); } m_semaphoreGetCharEvt.give(1); } diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index c893e07..c13dfb2 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -25,7 +25,7 @@ #include "FreeRTOS.h" #include "NimBLERemoteCharacteristic.h" -#include +#include class NimBLEClient; class NimBLERemoteCharacteristic; @@ -42,8 +42,7 @@ public: NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference. NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID &uuid); // Get the specified characteristic reference. // BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference. - std::map* getCharacteristics(); - std::map* getCharacteristicsByHandle(); // Get the characteristics map. + std::vector* getCharacteristics(); // void getCharacteristics(std::map* pCharacteristicMap); NimBLEClient* getClient(void); // Get a reference to the client associated with this service. @@ -74,11 +73,8 @@ private: // Properties - // We maintain a map of characteristics owned by this service keyed by a string representation of the UUID. - std::map m_characteristicMap; - - // We maintain a map of characteristics owned by this service keyed by a handle. - std::map m_characteristicMapByHandle; + // We maintain a vector of characteristics owned by this service. + std::vector m_characteristicVector; bool m_haveCharacteristics; // Have we previously obtained the characteristics. NimBLEClient* m_pClient; diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index 49d94da..84cb62e 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -117,13 +117,15 @@ NimBLEScan::NimBLEScan() { NimBLEAdvertisedDevice* advertisedDevice = nullptr; - // If we've seen this device before get a pointer to it from the map - auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString()); - if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) { - advertisedDevice = (*it).second; + // If we've seen this device before get a pointer to it from the vector + for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) { + if(it->getAddress() == advertisedAddress) { + advertisedDevice = it; + break; + } } - // If we haven't seen this device before; create a new instance and insert it in the map. + // If we haven't seen this device before; create a new instance and insert it in the vector. // Otherwise just update the relevant parameters of the already known device. if(advertisedDevice == nullptr){ advertisedDevice = new NimBLEAdvertisedDevice(); @@ -131,7 +133,7 @@ NimBLEScan::NimBLEScan() { advertisedDevice->setAddress(advertisedAddress); //NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type)); advertisedDevice->setAdvType(event->disc.event_type); - pScan->m_scanResults.m_advertisedDevicesMap.insert(std::pair(advertisedAddress.toString(), advertisedDevice)); + pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice); NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str()); } else{ @@ -262,7 +264,7 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul } // if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals - // then we should not clear map or we will connect the same device few times + // then we should not clear vector or we will connect the same device few times if(!is_continue) { clearResults(); } @@ -330,9 +332,14 @@ void NimBLEScan::stop() { // delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address void NimBLEScan::erase(const NimBLEAddress &address) { NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str()); - NimBLEAdvertisedDevice *advertisedDevice = m_scanResults.m_advertisedDevicesMap.find(address.toString())->second; - m_scanResults.m_advertisedDevicesMap.erase(address.toString()); - delete advertisedDevice; + + for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.begin(); ++it) { + if((*it)->getAddress() == address) { + delete *it; + m_scanResults.m_advertisedDevicesVector.erase(it); + break; + } + } } @@ -359,10 +366,10 @@ NimBLEScanResults NimBLEScan::getResults() { * @brief Clear the results of the scan. */ void NimBLEScan::clearResults() { - for(auto _dev : m_scanResults.m_advertisedDevicesMap){ - delete _dev.second; + for(auto &it: m_scanResults.m_advertisedDevicesVector) { + delete it; } - m_scanResults.m_advertisedDevicesMap.clear(); + m_scanResults.m_advertisedDevicesVector.clear(); } @@ -382,7 +389,7 @@ void NimBLEScanResults::dump() { * @return The number of devices found in the last scan. */ int NimBLEScanResults::getCount() { - return m_advertisedDevicesMap.size(); + return m_advertisedDevicesVector.size(); } // getCount @@ -393,14 +400,24 @@ int NimBLEScanResults::getCount() { * @return The device at the specified index. */ NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) { - uint32_t x = 0; - NimBLEAdvertisedDevice dev = *m_advertisedDevicesMap.begin()->second; - for (auto it = m_advertisedDevicesMap.begin(); it != m_advertisedDevicesMap.end(); it++) { - dev = *it->second; - if (x==i) break; - x++; + return *m_advertisedDevicesVector[i]; +} + + +/** + * @brief Return a pointer to the specified device at the given address. + * If the address is not found a nullptr is returned. + * @param [in] address The address of the device. + * @return A pointer to the device at the specified address. + */ +NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &address) { + for(size_t index = 0; index < m_advertisedDevicesVector.size(); index++) { + if(m_advertisedDevicesVector[index]->getAddress() == address) { + return m_advertisedDevicesVector[index]; + } } - return dev; + + return nullptr; } #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index cb453fd..a1884e4 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -24,12 +24,13 @@ #include "host/ble_gap.h" -#include +#include class NimBLEDevice; class NimBLEScan; class NimBLEAdvertisedDevice; class NimBLEAdvertisedDeviceCallbacks; +class NimBLEAddress; /** * @brief The result of having performed a scan. @@ -40,13 +41,14 @@ class NimBLEAdvertisedDeviceCallbacks; */ class NimBLEScanResults { public: - void dump(); - int getCount(); + void dump(); + int getCount(); NimBLEAdvertisedDevice getDevice(uint32_t i); + NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address); private: friend NimBLEScan; - std::map m_advertisedDevicesMap; + std::vector m_advertisedDevicesVector; }; /**