Skip to content

Commit d7b1d7f

Browse files
authored
[Server] Implement remove Characteristics/Descriptors. (#264)
This allows for adding and removing of characteristics and descriptors after initial setup of the server. When used it will send a service changed notification to all clients. The changes will not take effect until all clients have disconnected and advertising restarted.
1 parent 0e4fa36 commit d7b1d7f

File tree

8 files changed

+195
-55
lines changed

8 files changed

+195
-55
lines changed

src/NimBLECharacteristic.cpp

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties
4545
* @param [in] pService - pointer to the service instance this characteristic belongs to.
4646
*/
4747
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) {
48-
m_uuid = uuid;
49-
m_handle = NULL_HANDLE;
50-
m_properties = properties;
51-
m_pCallbacks = &defaultCallback;
52-
m_pService = pService;
53-
m_value = "";
54-
m_valMux = portMUX_INITIALIZER_UNLOCKED;
55-
m_timestamp = 0;
48+
m_uuid = uuid;
49+
m_handle = NULL_HANDLE;
50+
m_properties = properties;
51+
m_pCallbacks = &defaultCallback;
52+
m_pService = pService;
53+
m_value = "";
54+
m_valMux = portMUX_INITIALIZER_UNLOCKED;
55+
m_timestamp = 0;
56+
m_removed = 0;
5657
} // NimBLECharacteristic
5758

5859
/**
@@ -95,21 +96,63 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
9596
}
9697

9798
addDescriptor(pDescriptor);
98-
9999
return pDescriptor;
100100
} // createDescriptor
101101

102102

103103
/**
104104
* @brief Add a descriptor to the characteristic.
105-
* @param [in] A pointer to the descriptor to add.
105+
* @param [in] pDescriptor A pointer to the descriptor to add.
106106
*/
107107
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
108+
bool foundRemoved = false;
109+
110+
if(pDescriptor->m_removed > 0) {
111+
for(auto& it : m_dscVec) {
112+
if(it == pDescriptor) {
113+
foundRemoved = true;
114+
pDescriptor->m_removed = 0;
115+
}
116+
}
117+
}
118+
119+
if(!foundRemoved) {
120+
m_dscVec.push_back(pDescriptor);
121+
}
122+
108123
pDescriptor->setCharacteristic(this);
109-
m_dscVec.push_back(pDescriptor);
124+
NimBLEDevice::getServer()->serviceChanged();
110125
}
111126

112127

128+
/**
129+
* @brief Remove a descriptor from the characterisitc.
130+
* @param[in] pDescriptor A pointer to the descriptor instance to remove from the characterisitc.
131+
* @param[in] deleteDsc If true it will delete the descriptor instance and free it's resources.
132+
*/
133+
void NimBLECharacteristic::removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc) {
134+
// Check if the descriptor was already removed and if so, check if this
135+
// is being called to delete the object and do so if requested.
136+
// Otherwise, ignore the call and return.
137+
if(pDescriptor->m_removed > 0) {
138+
if(deleteDsc) {
139+
for(auto it = m_dscVec.begin(); it != m_dscVec.end(); ++it) {
140+
if ((*it) == pDescriptor) {
141+
delete *it;
142+
m_dscVec.erase(it);
143+
break;
144+
}
145+
}
146+
}
147+
148+
return;
149+
}
150+
151+
pDescriptor->m_removed = deleteDsc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
152+
NimBLEDevice::getServer()->serviceChanged();
153+
} // removeDescriptor
154+
155+
113156
/**
114157
* @brief Return the BLE Descriptor for the given UUID.
115158
* @param [in] uuid The UUID of the descriptor.

src/NimBLECharacteristic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class NimBLECharacteristic {
9999
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
100100
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
101101
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
102+
void removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc = false);
102103

103104
std::string getValue(time_t *timestamp = nullptr);
104105
size_t getDataLength();
@@ -152,6 +153,7 @@ class NimBLECharacteristic {
152153
std::vector<NimBLEDescriptor*> m_dscVec;
153154
portMUX_TYPE m_valMux;
154155
time_t m_timestamp;
156+
uint8_t m_removed;
155157

156158
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
157159
}; // NimBLECharacteristic

src/NimBLEDescriptor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
5353
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
5454
m_valMux = portMUX_INITIALIZER_UNLOCKED;
5555
m_properties = 0;
56+
m_removed = 0;
5657

5758
if (properties & BLE_GATT_CHR_F_READ) { // convert uint16_t properties to uint8_t
5859
m_properties |= BLE_ATT_F_READ;

src/NimBLEDescriptor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class NimBLEDescriptor {
9393
uint8_t m_properties;
9494
attr_value_t m_value;
9595
portMUX_TYPE m_valMux;
96+
uint8_t m_removed;
9697
}; // NimBLEDescriptor
9798

9899

src/NimBLEServer.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,7 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
9191

9292
NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
9393
m_svcVec.push_back(pService); // Save a reference to this service being on this server.
94-
95-
if(m_gattsStarted) {
96-
ble_svc_gatt_changed(0x0001, 0xffff);
97-
m_svcChanged = true;
98-
resetGATT();
99-
}
94+
serviceChanged();
10095

10196
NIMBLE_LOGD(LOG_TAG, "<< createService");
10297
return pService;
@@ -157,6 +152,18 @@ NimBLEAdvertising* NimBLEServer::getAdvertising() {
157152
} // getAdvertising
158153

159154

155+
/**
156+
* @brief Sends a service changed notification and resets the GATT server.
157+
*/
158+
void NimBLEServer::serviceChanged() {
159+
if(m_gattsStarted) {
160+
m_svcChanged = true;
161+
ble_svc_gatt_changed(0x0001, 0xffff);
162+
resetGATT();
163+
}
164+
}
165+
166+
160167
/**
161168
* @brief Start the GATT server. Required to be called after setup of all
162169
* services and characteristics / descriptors for the NimBLE host to register them.
@@ -630,7 +637,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
630637
if(service->m_removed > 0) {
631638
if(deleteSvc) {
632639
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ++it) {
633-
if ((*it)->getUUID() == service->getUUID()) {
640+
if ((*it) == service) {
634641
delete *it;
635642
m_svcVec.erase(it);
636643
break;
@@ -646,11 +653,8 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
646653
return;
647654
}
648655

649-
service->m_removed = deleteSvc ? 2 : 1;
650-
m_svcChanged = true;
651-
652-
ble_svc_gatt_changed(0x0001, 0xffff);
653-
resetGATT();
656+
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
657+
serviceChanged();
654658
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
655659
}
656660

@@ -677,10 +681,7 @@ void NimBLEServer::addService(NimBLEService* service) {
677681
}
678682

679683
service->m_removed = 0;
680-
m_svcChanged = true;
681-
682-
ble_svc_gatt_changed(0x0001, 0xffff);
683-
resetGATT();
684+
serviceChanged();
684685
}
685686

686687

@@ -699,7 +700,7 @@ void NimBLEServer::resetGATT() {
699700

700701
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ) {
701702
if ((*it)->m_removed > 0) {
702-
if ((*it)->m_removed == 2) {
703+
if ((*it)->m_removed == NIMBLE_ATT_REMOVE_DELETE) {
703704
delete *it;
704705
it = m_svcVec.erase(it);
705706
} else {

src/NimBLEServer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include "nimconfig.h"
2121
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
2222

23+
#define NIMBLE_ATT_REMOVE_HIDE 1
24+
#define NIMBLE_ATT_REMOVE_DELETE 2
25+
2326
#include "NimBLEUtils.h"
2427
#include "NimBLEAddress.h"
2528
#include "NimBLEAdvertising.h"
@@ -69,6 +72,7 @@ class NimBLEServer {
6972
NimBLEServer();
7073
~NimBLEServer();
7174
friend class NimBLECharacteristic;
75+
friend class NimBLEService;
7276
friend class NimBLEDevice;
7377
friend class NimBLEAdvertising;
7478

@@ -86,6 +90,7 @@ class NimBLEServer {
8690
std::vector<NimBLECharacteristic*> m_notifyChrVec;
8791

8892
static int handleGapEvent(struct ble_gap_event *event, void *arg);
93+
void serviceChanged();
8994
void resetGATT();
9095
bool setIndicateWait(uint16_t conn_handle);
9196
void clearIndicateWait(uint16_t conn_handle);

0 commit comments

Comments
 (0)