mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-24 14:10:55 +01:00
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:
parent
fc1022a46d
commit
6f4ee4b498
10 changed files with 169 additions and 142 deletions
|
@ -100,7 +100,7 @@ The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a poin
|
||||||
Defined as:
|
Defined as:
|
||||||
```
|
```
|
||||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
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.
|
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.
|
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.
|
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:
|
#### Client Security:
|
||||||
The client will automatically initiate security when the peripheral responds that it's required.
|
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.
|
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||||
|
|
11
README.md
11
README.md
|
@ -1,7 +1,14 @@
|
||||||
# *** UPDATE ***
|
# *** UPDATE ***
|
||||||
Client long read/write characteristics/descriptors now working.
|
**Breaking change:** Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database.
|
||||||
We are now nearing 100% replacement of the original cpp_utils BLE library :smile:
|
|
||||||
|
|
||||||
|
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
|
# esp-nimble-cpp
|
||||||
NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the @nkolban cpp_uitls API.
|
NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the @nkolban cpp_uitls API.
|
||||||
|
|
|
@ -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
|
* 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.
|
* 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
|
* We will assume that a NimBLERemoteService contains a vector of owned characteristics
|
||||||
* and that a NimBLECharacteristic contains a map that maps NimBLEUUIDs to the set of owned descriptors.
|
* and that a NimBLECharacteristic contains a vector of owned descriptors.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -90,10 +90,11 @@ NimBLEClient::~NimBLEClient() {
|
||||||
void NimBLEClient::clearServices() {
|
void NimBLEClient::clearServices() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> clearServices");
|
NIMBLE_LOGD(LOG_TAG, ">> clearServices");
|
||||||
// Delete all the services.
|
// Delete all the services.
|
||||||
for (auto &myPair : m_servicesMap) {
|
for(auto &it: m_servicesVector) {
|
||||||
delete myPair.second;
|
delete it;
|
||||||
}
|
}
|
||||||
m_servicesMap.clear();
|
m_servicesVector.clear();
|
||||||
|
|
||||||
m_haveServices = false;
|
m_haveServices = false;
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< clearServices");
|
NIMBLE_LOGD(LOG_TAG, "<< clearServices");
|
||||||
} // clearServices
|
} // clearServices
|
||||||
|
@ -368,23 +369,24 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||||
if (!m_haveServices) {
|
if (!m_haveServices) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::string uuidStr = uuid.toString();
|
|
||||||
for (auto &myPair : m_servicesMap) {
|
for(auto &it: m_servicesVector) {
|
||||||
if (myPair.first == uuidStr) {
|
if(it->getUUID() == uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
|
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");
|
NIMBLE_LOGD(LOG_TAG, "<< getService: not found");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getService
|
} // 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() {
|
std::vector<NimBLERemoteService*>* NimBLEClient::getServices() {
|
||||||
return &m_servicesMap;
|
return &m_servicesVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,8 +427,8 @@ bool NimBLEClient::retrieveServices() {
|
||||||
// If sucessful, remember that we now have services.
|
// If sucessful, remember that we now have services.
|
||||||
m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0);
|
m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0);
|
||||||
if(m_haveServices){
|
if(m_haveServices){
|
||||||
for (auto &myPair : m_servicesMap) {
|
for (auto &it: m_servicesVector) {
|
||||||
if(!m_isConnected || !myPair.second->retrieveCharacteristics()) {
|
if(!m_isConnected || !it->retrieveCharacteristics()) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting");
|
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -463,9 +465,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a service - add it to the map
|
// Found a service - add it to the vector
|
||||||
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
case BLE_HS_EDONE:{
|
||||||
|
@ -662,20 +664,25 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
if(!client->m_haveServices)
|
if(!client->m_haveServices)
|
||||||
return 0;
|
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
|
// 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;
|
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) {
|
auto cVector = it->getCharacteristics();
|
||||||
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", it->getUUID().toString().c_str(),event->notify_rx.attr_handle);
|
||||||
characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication);
|
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;
|
break;
|
||||||
|
@ -851,8 +858,9 @@ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, b
|
||||||
std::string NimBLEClient::toString() {
|
std::string NimBLEClient::toString() {
|
||||||
std::string res = "peer address: " + m_peerAddress.toString();
|
std::string res = "peer address: " + m_peerAddress.toString();
|
||||||
res += "\nServices:\n";
|
res += "\nServices:\n";
|
||||||
for (auto &myPair : m_servicesMap) {
|
|
||||||
res += myPair.second->toString() + "\n";
|
for(auto &it: m_servicesVector) {
|
||||||
|
res += it->toString() + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "NimBLERemoteService.h"
|
#include "NimBLERemoteService.h"
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class NimBLERemoteService;
|
class NimBLERemoteService;
|
||||||
|
@ -41,7 +41,8 @@ public:
|
||||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // Disconnect from the remote BLE Server
|
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
|
NimBLEAddress getPeerAddress(); // Get the address of the remote BLE Server
|
||||||
int getRssi(); // Get the RSSI 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
|
|
||||||
|
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 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.
|
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.
|
std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID); // Get the value of a given characteristic at a given service.
|
||||||
|
@ -87,7 +88,7 @@ private:
|
||||||
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
||||||
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
||||||
|
|
||||||
std::map<std::string, NimBLERemoteService*> m_servicesMap;
|
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEClientCallbacks;
|
friend class NimBLEClientCallbacks;
|
||||||
|
|
|
@ -157,10 +157,9 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a descriptor - add it to the map
|
// Found a descriptor - add it to the vector
|
||||||
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
case BLE_HS_EDONE:{
|
||||||
|
@ -212,15 +211,15 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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
|
} // getDescriptors
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the map of descriptors keyed by UUID.
|
* @brief Retrieve the vector of descriptors.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
|
std::vector<NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
|
||||||
return &m_descriptorMap;
|
return &m_descriptorVector;
|
||||||
} // getDescriptors
|
} // getDescriptors
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,11 +247,11 @@ uint16_t NimBLERemoteCharacteristic::getDefHandle() {
|
||||||
*/
|
*/
|
||||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) {
|
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||||
std::string v = uuid.toString();
|
|
||||||
for (auto &myPair : m_descriptorMap) {
|
for(auto &it: m_descriptorVector) {
|
||||||
if (myPair.first == v) {
|
if(it->getUUID() == uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
||||||
return myPair.second;
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
||||||
|
@ -444,19 +443,18 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete the descriptors in the descriptor map.
|
* @brief Delete the descriptors in the descriptor vector.
|
||||||
* We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors
|
* 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
|
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
||||||
* them. This method does just that.
|
* them. This method does just that.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteCharacteristic::removeDescriptors() {
|
void NimBLERemoteCharacteristic::removeDescriptors() {
|
||||||
// Iterate through all the descriptors releasing their storage and erasing them from the map.
|
// Iterate through all the descriptors releasing their storage and erasing them from the vector.
|
||||||
for (auto &myPair : m_descriptorMap) {
|
for(auto &it: m_descriptorVector) {
|
||||||
m_descriptorMap.erase(myPair.first);
|
delete it;
|
||||||
delete myPair.second;
|
|
||||||
}
|
}
|
||||||
m_descriptorMap.clear(); // Technically not neeeded, but just to be sure.
|
m_descriptorVector.clear();
|
||||||
} // removeCharacteristics
|
} // removeCharacteristics
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,8 +476,8 @@ std::string NimBLERemoteCharacteristic::toString() {
|
||||||
snprintf(val, sizeof(val), "%02x", m_charProp);
|
snprintf(val, sizeof(val), "%02x", m_charProp);
|
||||||
res += val;
|
res += val;
|
||||||
|
|
||||||
for (auto &myPair : m_descriptorMap) {
|
for(auto &it: m_descriptorVector) {
|
||||||
res += "\n" + myPair.second->toString();
|
res += "\n" + it->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -645,8 +643,8 @@ size_t NimBLERemoteCharacteristic::getDataLength() {
|
||||||
|
|
||||||
|
|
||||||
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
||||||
for (auto &dPair : m_descriptorMap) {
|
for (auto &it: m_descriptorVector) {
|
||||||
dPair.second->releaseSemaphores();
|
it->releaseSemaphores();
|
||||||
}
|
}
|
||||||
m_semaphoreWriteCharEvt.give(1);
|
m_semaphoreWriteCharEvt.give(1);
|
||||||
m_semaphoreGetDescEvt.give(1);
|
m_semaphoreGetDescEvt.give(1);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "NimBLERemoteDescriptor.h"
|
#include "NimBLERemoteDescriptor.h"
|
||||||
|
|
||||||
//#include <string>
|
//#include <string>
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class NimBLERemoteService;
|
class NimBLERemoteService;
|
||||||
class NimBLERemoteDescriptor;
|
class NimBLERemoteDescriptor;
|
||||||
|
@ -49,7 +49,7 @@ public:
|
||||||
bool canWrite();
|
bool canWrite();
|
||||||
bool canWriteNoResponse();
|
bool canWriteNoResponse();
|
||||||
NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid);
|
NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid);
|
||||||
std::map<std::string, NimBLERemoteDescriptor*>* getDescriptors();
|
std::vector<NimBLERemoteDescriptor*>* getDescriptors();
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
uint16_t getDefHandle();
|
uint16_t getDefHandle();
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
|
@ -98,8 +98,8 @@ private:
|
||||||
size_t m_dataLen;
|
size_t m_dataLen;
|
||||||
notify_callback m_notifyCallback;
|
notify_callback m_notifyCallback;
|
||||||
|
|
||||||
// We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID.
|
// We maintain a vector of descriptors owned by this characteristic.
|
||||||
std::map<std::string, NimBLERemoteDescriptor*> m_descriptorMap;
|
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
|
||||||
}; // BLERemoteCharacteristic
|
}; // BLERemoteCharacteristic
|
||||||
|
|
||||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
|
@ -81,10 +81,9 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
|
||||||
*/
|
*/
|
||||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) {
|
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||||
if (m_haveCharacteristics) {
|
if (m_haveCharacteristics) {
|
||||||
std::string v = uuid.toString();
|
for(auto &it: m_characteristicVector) {
|
||||||
for (auto &myPair : m_characteristicMap) {
|
if(it->getUUID() == uuid) {
|
||||||
if (myPair.first == v) {
|
return it;
|
||||||
return myPair.second;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,10 +111,9 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a service - add it to the map
|
// Found a service - add it to the vector
|
||||||
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
||||||
service->m_characteristicMap.insert(std::pair<std::string, NimBLERemoteCharacteristic*>(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic));
|
service->m_characteristicVector.push_back(pRemoteCharacteristic);
|
||||||
service->m_characteristicMapByHandle.insert(std::pair<uint16_t, NimBLERemoteCharacteristic*>(chr->val_handle, pRemoteCharacteristic));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
case BLE_HS_EDONE:{
|
||||||
|
@ -171,17 +169,18 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
||||||
m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0);
|
m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0);
|
||||||
if(m_haveCharacteristics){
|
if(m_haveCharacteristics){
|
||||||
uint16_t endHdl = 0xFFFF;
|
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 %d Characteristics", m_characteristicVector.size());
|
||||||
NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle());
|
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
|
// 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
|
// 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
|
// Make sure we don't go past the service end handle
|
||||||
if(++it != m_characteristicMapByHandle.cend()){
|
if(++it != m_characteristicVector.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());
|
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{
|
else{
|
||||||
NIMBLE_LOGD(LOG_TAG, "END CHARS");
|
NIMBLE_LOGD(LOG_TAG, "END CHARS");
|
||||||
|
@ -190,8 +189,8 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
||||||
--it;
|
--it;
|
||||||
|
|
||||||
//If there is no handles between this characteristic and the next there is no descriptor so skip to the next
|
//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((*it)->getHandle() != endHdl){
|
||||||
if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) {
|
if(!m_pClient->m_isConnected || !(*it)->retrieveDescriptors(endHdl)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,23 +208,14 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve a map of all the characteristics of this service.
|
* @brief Retrieve a vector of all the characteristics of this service.
|
||||||
* @return A map of all the characteristics of this service.
|
* @return A vector of all the characteristics of this service.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics() {
|
std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics() {
|
||||||
return &m_characteristicMap;
|
return &m_characteristicVector;
|
||||||
} // getCharacteristics
|
} // 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.
|
* @brief Get the client associated with this service.
|
||||||
* @return A reference to 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.
|
* @brief Delete the characteristics in the characteristics vector.
|
||||||
* We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic
|
* 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 deleteing
|
* object references. Since we allocated these in this class, we are also responsible for deleting
|
||||||
* them. This method does just that.
|
* them. This method does just that.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteService::removeCharacteristics() {
|
void NimBLERemoteService::removeCharacteristics() {
|
||||||
m_characteristicMap.clear(); // Clear the map
|
for(auto &it: m_characteristicVector) {
|
||||||
|
delete it;
|
||||||
for (auto &myPair : m_characteristicMapByHandle) {
|
|
||||||
delete myPair.second;
|
|
||||||
}
|
}
|
||||||
m_characteristicMapByHandle.clear(); // Clear the map
|
m_characteristicVector.clear(); // Clear the vector
|
||||||
|
|
||||||
} // removeCharacteristics
|
} // removeCharacteristics
|
||||||
|
|
||||||
|
|
||||||
|
@ -338,8 +325,8 @@ std::string NimBLERemoteService::toString() {
|
||||||
res += " 0x";
|
res += " 0x";
|
||||||
res += val;
|
res += val;
|
||||||
|
|
||||||
for (auto &myPair : m_characteristicMap) {
|
for (auto &it: m_characteristicVector) {
|
||||||
res += "\n" + myPair.second->toString();
|
res += "\n" + it->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -351,8 +338,8 @@ std::string NimBLERemoteService::toString() {
|
||||||
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteService::releaseSemaphores() {
|
void NimBLERemoteService::releaseSemaphores() {
|
||||||
for (auto &cPair : m_characteristicMapByHandle) {
|
for(auto &it: m_characteristicVector) {
|
||||||
cPair.second->releaseSemaphores();
|
it->releaseSemaphores();
|
||||||
}
|
}
|
||||||
m_semaphoreGetCharEvt.give(1);
|
m_semaphoreGetCharEvt.give(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "NimBLERemoteCharacteristic.h"
|
#include "NimBLERemoteCharacteristic.h"
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class NimBLEClient;
|
class NimBLEClient;
|
||||||
class NimBLERemoteCharacteristic;
|
class NimBLERemoteCharacteristic;
|
||||||
|
@ -42,8 +42,7 @@ public:
|
||||||
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference.
|
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference.
|
||||||
NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID &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.
|
// BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference.
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*>* getCharacteristics();
|
std::vector<NimBLERemoteCharacteristic*>* getCharacteristics();
|
||||||
std::map<uint16_t, NimBLERemoteCharacteristic*>* getCharacteristicsByHandle(); // Get the characteristics map.
|
|
||||||
// void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap);
|
// void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap);
|
||||||
|
|
||||||
NimBLEClient* getClient(void); // Get a reference to the client associated with this service.
|
NimBLEClient* getClient(void); // Get a reference to the client associated with this service.
|
||||||
|
@ -74,11 +73,8 @@ private:
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
// We maintain a map of characteristics owned by this service keyed by a string representation of the UUID.
|
// We maintain a vector of characteristics owned by this service.
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*> m_characteristicMap;
|
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
|
||||||
|
|
||||||
// We maintain a map of characteristics owned by this service keyed by a handle.
|
|
||||||
std::map<uint16_t, NimBLERemoteCharacteristic*> m_characteristicMapByHandle;
|
|
||||||
|
|
||||||
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
|
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
|
||||||
NimBLEClient* m_pClient;
|
NimBLEClient* m_pClient;
|
||||||
|
|
|
@ -117,13 +117,15 @@ NimBLEScan::NimBLEScan() {
|
||||||
|
|
||||||
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||||
|
|
||||||
// If we've seen this device before get a pointer to it from the map
|
// If we've seen this device before get a pointer to it from the vector
|
||||||
auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString());
|
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||||
if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) {
|
if(it->getAddress() == advertisedAddress) {
|
||||||
advertisedDevice = (*it).second;
|
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.
|
// Otherwise just update the relevant parameters of the already known device.
|
||||||
if(advertisedDevice == nullptr){
|
if(advertisedDevice == nullptr){
|
||||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||||
|
@ -131,7 +133,7 @@ NimBLEScan::NimBLEScan() {
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
//NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type));
|
//NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type));
|
||||||
advertisedDevice->setAdvType(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());
|
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
||||||
}
|
}
|
||||||
else{
|
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
|
// 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) {
|
if(!is_continue) {
|
||||||
clearResults();
|
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
|
// 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) {
|
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
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());
|
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.begin(); ++it) {
|
||||||
delete advertisedDevice;
|
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.
|
* @brief Clear the results of the scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::clearResults() {
|
void NimBLEScan::clearResults() {
|
||||||
for(auto _dev : m_scanResults.m_advertisedDevicesMap){
|
for(auto &it: m_scanResults.m_advertisedDevicesVector) {
|
||||||
delete _dev.second;
|
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.
|
* @return The number of devices found in the last scan.
|
||||||
*/
|
*/
|
||||||
int NimBLEScanResults::getCount() {
|
int NimBLEScanResults::getCount() {
|
||||||
return m_advertisedDevicesMap.size();
|
return m_advertisedDevicesVector.size();
|
||||||
} // getCount
|
} // getCount
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,14 +400,24 @@ int NimBLEScanResults::getCount() {
|
||||||
* @return The device at the specified index.
|
* @return The device at the specified index.
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
||||||
uint32_t x = 0;
|
return *m_advertisedDevicesVector[i];
|
||||||
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 dev;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
|
@ -24,12 +24,13 @@
|
||||||
|
|
||||||
#include "host/ble_gap.h"
|
#include "host/ble_gap.h"
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class NimBLEDevice;
|
class NimBLEDevice;
|
||||||
class NimBLEScan;
|
class NimBLEScan;
|
||||||
class NimBLEAdvertisedDevice;
|
class NimBLEAdvertisedDevice;
|
||||||
class NimBLEAdvertisedDeviceCallbacks;
|
class NimBLEAdvertisedDeviceCallbacks;
|
||||||
|
class NimBLEAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The result of having performed a scan.
|
* @brief The result of having performed a scan.
|
||||||
|
@ -43,10 +44,11 @@ public:
|
||||||
void dump();
|
void dump();
|
||||||
int getCount();
|
int getCount();
|
||||||
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
||||||
|
NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend NimBLEScan;
|
friend NimBLEScan;
|
||||||
std::map<std::string, NimBLEAdvertisedDevice*> m_advertisedDevicesMap;
|
std::vector<NimBLEAdvertisedDevice*> m_advertisedDevicesVector;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue