Skip to content

Commit ac3d357

Browse files
committed
Add support for creating a NimBLEClient from a NimBLEServer peer.
This allows the NimBLEServer instance to create a NimBLEClient instance to read/write form/to a connected peer. Only one instance is supported subsequent calls will overwrite the previous client connection information and data.
1 parent a55489f commit ac3d357

File tree

4 files changed

+79
-63
lines changed

4 files changed

+79
-63
lines changed

src/NimBLEClient.cpp

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -551,62 +551,6 @@ uint16_t NimBLEClient::getConnHandle() const {
551551
return m_connHandle;
552552
} // getConnHandle
553553

554-
/**
555-
* @brief Clear the connection information for this client.
556-
* @note This is designed to be used to reset the connection information after
557-
* calling setConnection(), and should not be used to disconnect from a peer.
558-
* To disconnect from a peer, use disconnect().
559-
*/
560-
void NimBLEClient::clearConnection() {
561-
m_connHandle = BLE_HS_CONN_HANDLE_NONE;
562-
m_peerAddress = NimBLEAddress{};
563-
} // clearConnection
564-
565-
/**
566-
* @brief Set the connection information for this client.
567-
* @param [in] connInfo The connection information.
568-
* @return True on success.
569-
* @note Sets the connection established flag to true.
570-
* @note If the client is already connected to a peer, this will return false.
571-
* @note This is designed to be used when a connection is made outside of the
572-
* NimBLEClient class, such as when a connection is made by the
573-
* NimBLEServer class and the client is passed the connection info.
574-
* This enables the GATT Server to read the attributes of the client connected to it.
575-
*/
576-
bool NimBLEClient::setConnection(const NimBLEConnInfo& connInfo) {
577-
if (isConnected()) {
578-
NIMBLE_LOGE(LOG_TAG, "Already connected");
579-
return false;
580-
}
581-
582-
m_peerAddress = connInfo.getAddress();
583-
m_connHandle = connInfo.getConnHandle();
584-
return true;
585-
} // setConnection
586-
587-
/**
588-
* @brief Set the connection information for this client.
589-
* @param [in] connHandle The connection handle.
590-
* @note Sets the connection established flag to true.
591-
* @note This is designed to be used when a connection is made outside of the
592-
* NimBLEClient class, such as when a connection is made by the
593-
* NimBLEServer class and the client is passed the connection handle.
594-
* This enables the GATT Server to read the attributes of the client connected to it.
595-
* @note If the client is already connected to a peer, this will return false.
596-
* @note This will look up the peer address using the connection handle.
597-
*/
598-
bool NimBLEClient::setConnection(uint16_t connHandle) {
599-
// we weren't provided the peer address, look it up using ble_gap_conn_find
600-
NimBLEConnInfo connInfo;
601-
int rc = ble_gap_conn_find(connHandle, &connInfo.m_desc);
602-
if (rc != 0) {
603-
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
604-
return false;
605-
}
606-
607-
return setConnection(connInfo);
608-
} // setConnection
609-
610554
/**
611555
* @brief Retrieve the address of the peer.
612556
* @return A NimBLEAddress instance with the peer address data.

src/NimBLEClient.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ class NimBLEClient {
6060
void setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks = true);
6161
std::string toString() const;
6262
uint16_t getConnHandle() const;
63-
void clearConnection();
64-
bool setConnection(const NimBLEConnInfo& connInfo);
65-
bool setConnection(uint16_t connHandle);
6663
uint16_t getMTU() const;
6764
bool exchangeMTU();
6865
bool secureConnection(bool async = false) const;
@@ -140,6 +137,7 @@ class NimBLEClient {
140137
ble_gap_conn_params m_connParams;
141138

142139
friend class NimBLEDevice;
140+
friend class NimBLEServer;
143141
}; // class NimBLEClient
144142

145143
/**
@@ -155,7 +153,7 @@ class NimBLEClientCallbacks {
155153
*/
156154
virtual void onConnect(NimBLEClient* pClient);
157155

158-
/**
156+
/**
159157
* @brief Called when a connection attempt fails.
160158
* @param [in] pClient A pointer to the connecting client object.
161159
* @param [in] reason Contains the reason code for the connection failure.

src/NimBLEServer.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
# include "NimBLEDevice.h"
2020
# include "NimBLELog.h"
2121

22+
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
23+
# include "NimBLEClient.h"
24+
# endif
25+
2226
# if defined(CONFIG_NIMBLE_CPP_IDF)
2327
# include "services/gap/ble_svc_gap.h"
2428
# include "services/gatt/ble_svc_gatt.h"
@@ -63,6 +67,10 @@ NimBLEServer::~NimBLEServer() {
6367
if (m_deleteCallbacks) {
6468
delete m_pServerCallbacks;
6569
}
70+
71+
if (m_pClient != nullptr) {
72+
delete m_pClient;
73+
}
6674
}
6775

6876
/**
@@ -169,7 +177,7 @@ void NimBLEServer::serviceChanged() {
169177
*/
170178
void NimBLEServer::start() {
171179
if (m_gattsStarted) {
172-
return; //already started
180+
return; // already started
173181
}
174182

175183
int rc = ble_gatts_start();
@@ -497,6 +505,11 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
497505
}
498506
}
499507

508+
if (pServer->m_pClient->m_connHandle == event->disconnect.conn.conn_handle) {
509+
// If this was also the client make sure it's flagged as disconnected.
510+
pServer->m_pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
511+
}
512+
500513
if (pServer->m_svcChanged) {
501514
pServer->resetGATT();
502515
}
@@ -705,8 +718,8 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
705718
NIMBLE_LOGD(LOG_TAG,
706719
"Gatt %s event",
707720
(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
708-
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
709-
auto val = pAtt->getAttVal();
721+
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
722+
auto val = pAtt->getAttVal();
710723
NimBLEConnInfo peerInfo{};
711724
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
712725

@@ -1029,6 +1042,54 @@ void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
10291042
# endif
10301043
} // setDataLen
10311044

1045+
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
1046+
/**
1047+
* @brief Create a client instance from the connection handle.
1048+
* @param [in] connHandle The connection handle to create a client instance from.
1049+
* @return A pointer to the NimBLEClient instance or nullptr if there was an error.
1050+
* @note Only one instance is supported subsequent calls will overwrite the previous
1051+
* client connection information and data.
1052+
*/
1053+
NimBLEClient* NimBLEServer::getClient(uint16_t connHandle) {
1054+
NimBLEConnInfo connInfo;
1055+
int rc = ble_gap_conn_find(connHandle, &connInfo.m_desc);
1056+
if (rc != 0) {
1057+
NIMBLE_LOGE(LOG_TAG, "Client info not found");
1058+
return nullptr;
1059+
}
1060+
1061+
return getClient(connInfo);
1062+
} // getClient
1063+
1064+
/**
1065+
* @brief Create a client instance from the NimBLEConnInfo reference.
1066+
* @param [in] connInfo The connection info to create a client instance from.
1067+
* @return A pointer to the NimBLEClient instance or nullptr if there was an error.
1068+
* @note Only one instance is supported subsequent calls will overwrite the previous
1069+
* client connection information and data.
1070+
*/
1071+
NimBLEClient* NimBLEServer::getClient(const NimBLEConnInfo& connInfo) {
1072+
if (m_pClient == nullptr) {
1073+
m_pClient = new NimBLEClient(connInfo.getAddress());
1074+
}
1075+
1076+
m_pClient->deleteServices(); // Changed peer connection delete the database.
1077+
m_pClient->m_peerAddress = connInfo.getAddress();
1078+
m_pClient->m_connHandle = connInfo.getConnHandle();
1079+
return m_pClient;
1080+
} // getClient
1081+
1082+
/**
1083+
* @brief Delete the NimBLEClient instance that was created with `getClient()`
1084+
*/
1085+
void NimBLEServer::deleteClient() {
1086+
if (m_pClient != nullptr) {
1087+
delete m_pClient;
1088+
m_pClient = nullptr;
1089+
}
1090+
} // deleteClient
1091+
# endif
1092+
10321093
/** Default callback handlers */
10331094
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
10341095
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");

src/NimBLEServer.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class NimBLEExtAdvertising;
4848
# else
4949
class NimBLEAdvertising;
5050
# endif
51+
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
52+
class NimBLEClient;
53+
# endif
5154

5255
/**
5356
* @brief The model of a BLE server.
@@ -77,6 +80,12 @@ class NimBLEServer {
7780
void advertiseOnDisconnect(bool enable);
7881
void setDataLen(uint16_t connHandle, uint16_t tx_octets) const;
7982

83+
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
84+
NimBLEClient* getClient(uint16_t connHandle);
85+
NimBLEClient* getClient(const NimBLEConnInfo& connInfo);
86+
void deleteClient();
87+
# endif
88+
8089
# if CONFIG_BT_NIMBLE_EXT_ADV
8190
NimBLEExtAdvertising* getAdvertising() const;
8291
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
@@ -115,6 +124,10 @@ class NimBLEServer {
115124
std::vector<NimBLEService*> m_svcVec;
116125
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
117126

127+
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
128+
NimBLEClient* m_pClient{nullptr};
129+
# endif
130+
118131
static int handleGapEvent(struct ble_gap_event* event, void* arg);
119132
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
120133
static int peerNameCB(uint16_t connHandle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);

0 commit comments

Comments
 (0)