Breaking: Use std::vector instead of std::map in client classes (#46)

* Exchange map for vector, saving 1,076 bytes of program memory and 5,024 bytes of heap for a small device (LYWSD03MMC)

* Removing m_characteristicMapByHandle (using the handles form m_characteristicVector instead) saving in total (compared to the current master) 1,508 bytes of program memory and 6,500 bytes of heap for a small device (LYWSD03MMC)

* Change NimBLEScan container from std::map to std::vector

* Add function to get advertised device by address

* Update documentation
This commit is contained in:
h2zero 2020-05-17 20:21:35 -06:00
parent fc1022a46d
commit 6f4ee4b498
10 changed files with 169 additions and 142 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
return &m_servicesMap;
std::vector<NimBLERemoteService*>* 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<std::string, NimBLERemoteService*>(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;

View file

@ -24,7 +24,7 @@
#include "NimBLEAdvertisedDevice.h"
#include "NimBLERemoteService.h"
#include <map>
#include <vector>
#include <string>
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<std::string, NimBLERemoteService*>* 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<NimBLERemoteService*>* 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<std::string, NimBLERemoteService*> m_servicesMap;
std::vector<NimBLERemoteService*> m_servicesVector;
private:
friend class NimBLEClientCallbacks;

View file

@ -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<std::string, NimBLERemoteDescriptor*>(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.
* @brief Retrieve the vector of descriptors.
*/
std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
return &m_descriptorMap;
std::vector<NimBLERemoteDescriptor*>* 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);

View file

@ -26,7 +26,7 @@
#include "NimBLERemoteDescriptor.h"
//#include <string>
#include <map>
#include <vector>
class NimBLERemoteService;
class NimBLERemoteDescriptor;
@ -49,7 +49,7 @@ public:
bool canWrite();
bool canWriteNoResponse();
NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid);
std::map<std::string, NimBLERemoteDescriptor*>* getDescriptors();
std::vector<NimBLERemoteDescriptor*>* 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<std::string, NimBLERemoteDescriptor*> m_descriptorMap;
// We maintain a vector of descriptors owned by this characteristic.
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
}; // BLERemoteCharacteristic
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)

View file

@ -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<std::string, NimBLERemoteCharacteristic*>(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic));
service->m_characteristicMapByHandle.insert(std::pair<uint16_t, NimBLERemoteCharacteristic*>(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<std::string, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics() {
return &m_characteristicMap;
std::vector<NimBLERemoteCharacteristic*>* 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<uint16_t, NimBLERemoteCharacteristic*>* 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);
}

View file

@ -25,7 +25,7 @@
#include "FreeRTOS.h"
#include "NimBLERemoteCharacteristic.h"
#include <map>
#include <vector>
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<std::string, NimBLERemoteCharacteristic*>* getCharacteristics();
std::map<uint16_t, NimBLERemoteCharacteristic*>* getCharacteristicsByHandle(); // Get the characteristics map.
std::vector<NimBLERemoteCharacteristic*>* getCharacteristics();
// void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* 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<std::string, NimBLERemoteCharacteristic*> m_characteristicMap;
// We maintain a map of characteristics owned by this service keyed by a handle.
std::map<uint16_t, NimBLERemoteCharacteristic*> m_characteristicMapByHandle;
// We maintain a vector of characteristics owned by this service.
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
NimBLEClient* m_pClient;

View file

@ -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<std::string, NimBLEAdvertisedDevice*>(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)

View file

@ -24,12 +24,13 @@
#include "host/ble_gap.h"
#include <map>
#include <vector>
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<std::string, NimBLEAdvertisedDevice*> m_advertisedDevicesMap;
std::vector<NimBLEAdvertisedDevice*> m_advertisedDevicesVector;
};
/**