Skip to content

Commit 76ce18a

Browse files
DavidJRobertsonh2zero
authored andcommitted
[NimBLEServer] Support duplicate characteristics
* Add method to get all characteristics of a service * Added method on NimBLEDescriptor to get the value out as a std::string * Added methods to get things by handle where UUID could be used already. * Added helper methods for getting a list of characteristics with a given UUID and service * Demote the warning log for adding duplicate characteristics to a debug level log. * Add methods to get services and characteristics using UUID + index
1 parent 4fbed5a commit 76ce18a

File tree

8 files changed

+155
-51
lines changed

8 files changed

+155
-51
lines changed

src/NimBLECharacteristic.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,19 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
101101

102102

103103
/**
104-
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
105-
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
106-
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
104+
* @brief Return the BLE Descriptor for the given UUID.
105+
* @param [in] uuid The UUID of the descriptor.
106+
* @return A pointer to the descriptor object or nullptr if not found.
107107
*/
108108
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
109109
return getDescriptorByUUID(NimBLEUUID(uuid));
110110
} // getDescriptorByUUID
111111

112112

113113
/**
114-
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
115-
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
116-
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
114+
* @brief Return the BLE Descriptor for the given UUID.
115+
* @param [in] uuid The UUID of the descriptor.
116+
* @return A pointer to the descriptor object or nullptr if not found.
117117
*/
118118
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
119119
for (auto &it : m_dscVec) {
@@ -124,6 +124,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
124124
return nullptr;
125125
} // getDescriptorByUUID
126126

127+
/**
128+
* @brief Return the BLE Descriptor for the given handle.
129+
* @param [in] uuid The handle of the descriptor.
130+
* @return A pointer to the descriptor object or nullptr if not found.
131+
*/
132+
NimBLEDescriptor *NimBLECharacteristic::getDescriptorByHandle(uint16_t handle) {
133+
for (auto &it : m_dscVec) {
134+
if (it->getHandle() == handle) {
135+
return it;
136+
}
137+
}
138+
return nullptr;
139+
}
140+
127141

128142
/**
129143
* @brief Get the handle of the characteristic.

src/NimBLECharacteristic.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ class NimBLECharacteristicCallbacks;
5959
*/
6060
class NimBLECharacteristic {
6161
public:
62+
63+
uint16_t getHandle();
64+
NimBLEUUID getUUID();
65+
std::string toString();
66+
67+
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
68+
69+
void indicate();
70+
void notify(bool is_notification = true);
71+
size_t getSubscribedCount();
72+
6273
NimBLEDescriptor* createDescriptor(const char* uuid,
6374
uint32_t properties =
6475
NIMBLE_PROPERTY::READ |
@@ -72,9 +83,10 @@ class NimBLECharacteristic {
7283

7384
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
7485
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
75-
NimBLEUUID getUUID();
76-
std::string getValue(time_t *timestamp = nullptr);
86+
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
7787

88+
std::string getValue(time_t *timestamp = nullptr);
89+
size_t getDataLength();
7890
/**
7991
* @brief A template to convert the characteristic data to <type\>.
8092
* @tparam T The type to convert the data to.
@@ -92,25 +104,20 @@ class NimBLECharacteristic {
92104
return *((T *)pData);
93105
}
94106

95-
size_t getDataLength();
96-
void indicate();
97-
void notify(bool is_notification = true);
98-
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
99107
void setValue(const uint8_t* data, size_t size);
100108
void setValue(const std::string &value);
101-
102109
/**
103110
* @brief Convenience template to set the characteristic value to <type\>val.
104111
* @param [in] s The value to set.
105112
*/
106113
template<typename T>
107-
void setValue(const T &s) {
114+
void setValue(const T &s) {
108115
setValue((uint8_t*)&s, sizeof(T));
109116
}
110117

111-
std::string toString();
112-
uint16_t getHandle();
113-
size_t getSubscribedCount();
118+
119+
120+
114121

115122
private:
116123

src/NimBLEDescriptor.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ uint8_t* NimBLEDescriptor::getValue() {
122122
return m_value.attr_value;
123123
} // getValue
124124

125+
/**
126+
* @brief Get the value of this descriptor as a string.
127+
* @return A std::string instance containing a copy of the descriptor's value.
128+
*/
129+
std::string NimBLEDescriptor::getStringValue() {
130+
return std::string((char *) m_value.attr_value, m_value.attr_len);
131+
}
125132

126133
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
127134
struct ble_gatt_access_ctxt *ctxt,
128-
void *arg)
129-
{
135+
void *arg) {
130136
const ble_uuid_t *uuid;
131137
int rc;
132138
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;

src/NimBLEDescriptor.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,23 @@ class NimBLEDescriptorCallbacks;
4444
class NimBLEDescriptor {
4545
public:
4646
uint16_t getHandle();
47-
size_t getLength();
4847
NimBLEUUID getUUID();
49-
uint8_t* getValue();
48+
std::string toString();
49+
5050
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
51+
52+
size_t getLength();
53+
uint8_t* getValue();
54+
std::string getStringValue();
55+
5156
void setValue(const uint8_t* data, size_t size);
5257
void setValue(const std::string &value);
53-
std::string toString();
54-
5558
/**
5659
* @brief Convenience template to set the descriptor value to <type\>val.
5760
* @param [in] s The value to set.
5861
*/
5962
template<typename T>
60-
void setValue(const T &s) {
63+
void setValue(const T &s) {
6164
setValue((uint8_t*)&s, sizeof(T));
6265
}
6366

src/NimBLEServer.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,28 +104,47 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
104104

105105
/**
106106
* @brief Get a %BLE Service by its UUID
107-
* @param [in] uuid The UUID of the new service.
108-
* @return A reference to the service object.
107+
* @param [in] uuid The UUID of the service.
108+
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
109+
* @return A pointer to the service object or nullptr if not found.
109110
*/
110-
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
111-
return getServiceByUUID(NimBLEUUID(uuid));
111+
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
112+
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
112113
} // getServiceByUUID
113114

114115

115116
/**
116117
* @brief Get a %BLE Service by its UUID
117-
* @param [in] uuid The UUID of the new service.
118-
* @return A reference to the service object.
118+
* @param [in] uuid The UUID of the service.
119+
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
120+
* @return A pointer to the service object or nullptr if not found.
119121
*/
120-
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
122+
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId) {
123+
uint16_t position = 0;
121124
for (auto &it : m_svcVec) {
122125
if (it->getUUID() == uuid) {
123-
return it;
126+
if (position == instanceId){
127+
return it;
128+
}
129+
position++;
124130
}
125131
}
126132
return nullptr;
127133
} // getServiceByUUID
128134

135+
/**
136+
* @brief Get a %BLE Service by its handle
137+
* @param handle The handle of the service.
138+
* @return A pointer to the service object or nullptr if not found.
139+
*/
140+
NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
141+
for (auto &it : m_svcVec) {
142+
if (it->getHandle() == handle) {
143+
return it;
144+
}
145+
}
146+
return nullptr;
147+
}
129148

130149
/**
131150
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
@@ -646,7 +665,7 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
646665
if(rc != 0) {
647666
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
648667
}
649-
} // updateConnParams
668+
}// updateConnParams
650669

651670

652671
/** Default callback handlers */

src/NimBLEServer.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ class NimBLEServer {
4949
void startAdvertising();
5050
void stopAdvertising();
5151
void start();
52-
NimBLEService* getServiceByUUID(const char* uuid);
53-
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
52+
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
53+
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
54+
NimBLEService* getServiceByHandle(uint16_t handle);
5455
int disconnect(uint16_t connID,
5556
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
5657
void updateConnParams(uint16_t conn_handle,

src/NimBLEService.cpp

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,9 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
233233
*/
234234
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
235235
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
236-
// Check that we don't add the same characteristic twice.
236+
237237
if (getCharacteristic(uuid) != nullptr) {
238-
NIMBLE_LOGW(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
238+
NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
239239
std::string(uuid).c_str());
240240
}
241241

@@ -249,28 +249,72 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
249249
/**
250250
* @brief Get a pointer to the characteristic object with the specified UUID.
251251
* @param [in] uuid The UUID of the characteristic.
252+
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
252253
* @return A pointer to the characteristic object or nullptr if not found.
253254
*/
254-
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
255-
return getCharacteristic(NimBLEUUID(uuid));
255+
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
256+
return getCharacteristic(NimBLEUUID(uuid), instanceId);
256257
}
257258

258-
259259
/**
260260
* @brief Get a pointer to the characteristic object with the specified UUID.
261261
* @param [in] uuid The UUID of the characteristic.
262+
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
262263
* @return A pointer to the characteristic object or nullptr if not found.
263264
*/
264-
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
265+
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId) {
266+
uint16_t position = 0;
265267
for (auto &it : m_chrVec) {
266268
if (it->getUUID() == uuid) {
267-
return it;
269+
if (position == instanceId) {
270+
return it;
271+
}
272+
position++;
268273
}
269274
}
275+
return nullptr;
276+
}
270277

278+
/**
279+
* @brief Get a pointer to the characteristic object with the specified handle.
280+
* @param handle The handle of the characteristic.
281+
* @return A pointer to the characteristic object or nullptr if not found.
282+
*/
283+
NimBLECharacteristic *NimBLEService::getCharacteristicByHandle(uint16_t handle) {
284+
for (auto &it : m_chrVec) {
285+
if (it->getHandle() == handle) {
286+
return it;
287+
}
288+
}
271289
return nullptr;
272290
}
273291

292+
/**
293+
* @return A vector containing pointers to each characteristic associated with this service.
294+
*/
295+
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics() {
296+
return m_chrVec;
297+
}
298+
299+
/**
300+
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
301+
*/
302+
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const char *uuid) {
303+
return getCharacteristics(NimBLEUUID(uuid));
304+
}
305+
306+
/**
307+
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
308+
*/
309+
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const NimBLEUUID &uuid) {
310+
std::vector<NimBLECharacteristic*> result;
311+
for (auto &it : m_chrVec) {
312+
if (it->getUUID() == uuid) {
313+
result.push_back(it);
314+
}
315+
}
316+
return result;
317+
}
274318

275319
/**
276320
* @brief Return a string representation of this service.
@@ -295,7 +339,7 @@ std::string NimBLEService::toString() {
295339
*/
296340
NimBLEServer* NimBLEService::getServer() {
297341
return m_pServer;
298-
} // getServer
342+
}// getServer
299343

300344
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
301345
#endif // CONFIG_BT_ENABLED

src/NimBLEService.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ class NimBLECharacteristic;
3535
*/
3636
class NimBLEService {
3737
public:
38+
39+
NimBLEServer* getServer();
40+
41+
NimBLEUUID getUUID();
42+
uint16_t getHandle();
43+
std::string toString();
44+
void dump();
45+
46+
bool start();
47+
3848
NimBLECharacteristic* createCharacteristic(const char* uuid,
3949
uint32_t properties =
4050
NIMBLE_PROPERTY::READ |
@@ -45,14 +55,14 @@ class NimBLEService {
4555
NIMBLE_PROPERTY::READ |
4656
NIMBLE_PROPERTY::WRITE);
4757

48-
void dump();
49-
NimBLECharacteristic* getCharacteristic(const char* uuid);
50-
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
51-
NimBLEUUID getUUID();
52-
NimBLEServer* getServer();
53-
bool start();
54-
std::string toString();
55-
uint16_t getHandle();
58+
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
59+
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
60+
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
61+
62+
std::vector<NimBLECharacteristic*> getCharacteristics();
63+
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
64+
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
65+
5666

5767
private:
5868
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);

0 commit comments

Comments
 (0)