mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-12-18 09:10:47 +01:00
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.
This commit is contained in:
parent
a55489fee2
commit
ac3d3575cc
4 changed files with 79 additions and 63 deletions
|
@ -551,62 +551,6 @@ uint16_t NimBLEClient::getConnHandle() const {
|
||||||
return m_connHandle;
|
return m_connHandle;
|
||||||
} // getConnHandle
|
} // getConnHandle
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clear the connection information for this client.
|
|
||||||
* @note This is designed to be used to reset the connection information after
|
|
||||||
* calling setConnection(), and should not be used to disconnect from a peer.
|
|
||||||
* To disconnect from a peer, use disconnect().
|
|
||||||
*/
|
|
||||||
void NimBLEClient::clearConnection() {
|
|
||||||
m_connHandle = BLE_HS_CONN_HANDLE_NONE;
|
|
||||||
m_peerAddress = NimBLEAddress{};
|
|
||||||
} // clearConnection
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the connection information for this client.
|
|
||||||
* @param [in] connInfo The connection information.
|
|
||||||
* @return True on success.
|
|
||||||
* @note Sets the connection established flag to true.
|
|
||||||
* @note If the client is already connected to a peer, this will return false.
|
|
||||||
* @note This is designed to be used when a connection is made outside of the
|
|
||||||
* NimBLEClient class, such as when a connection is made by the
|
|
||||||
* NimBLEServer class and the client is passed the connection info.
|
|
||||||
* This enables the GATT Server to read the attributes of the client connected to it.
|
|
||||||
*/
|
|
||||||
bool NimBLEClient::setConnection(const NimBLEConnInfo& connInfo) {
|
|
||||||
if (isConnected()) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Already connected");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_peerAddress = connInfo.getAddress();
|
|
||||||
m_connHandle = connInfo.getConnHandle();
|
|
||||||
return true;
|
|
||||||
} // setConnection
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the connection information for this client.
|
|
||||||
* @param [in] connHandle The connection handle.
|
|
||||||
* @note Sets the connection established flag to true.
|
|
||||||
* @note This is designed to be used when a connection is made outside of the
|
|
||||||
* NimBLEClient class, such as when a connection is made by the
|
|
||||||
* NimBLEServer class and the client is passed the connection handle.
|
|
||||||
* This enables the GATT Server to read the attributes of the client connected to it.
|
|
||||||
* @note If the client is already connected to a peer, this will return false.
|
|
||||||
* @note This will look up the peer address using the connection handle.
|
|
||||||
*/
|
|
||||||
bool NimBLEClient::setConnection(uint16_t connHandle) {
|
|
||||||
// we weren't provided the peer address, look it up using ble_gap_conn_find
|
|
||||||
NimBLEConnInfo connInfo;
|
|
||||||
int rc = ble_gap_conn_find(connHandle, &connInfo.m_desc);
|
|
||||||
if (rc != 0) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return setConnection(connInfo);
|
|
||||||
} // setConnection
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the address of the peer.
|
* @brief Retrieve the address of the peer.
|
||||||
* @return A NimBLEAddress instance with the peer address data.
|
* @return A NimBLEAddress instance with the peer address data.
|
||||||
|
|
|
@ -60,9 +60,6 @@ class NimBLEClient {
|
||||||
void setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks = true);
|
void setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks = true);
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
uint16_t getConnHandle() const;
|
uint16_t getConnHandle() const;
|
||||||
void clearConnection();
|
|
||||||
bool setConnection(const NimBLEConnInfo& connInfo);
|
|
||||||
bool setConnection(uint16_t connHandle);
|
|
||||||
uint16_t getMTU() const;
|
uint16_t getMTU() const;
|
||||||
bool exchangeMTU();
|
bool exchangeMTU();
|
||||||
bool secureConnection(bool async = false) const;
|
bool secureConnection(bool async = false) const;
|
||||||
|
@ -140,6 +137,7 @@ class NimBLEClient {
|
||||||
ble_gap_conn_params m_connParams;
|
ble_gap_conn_params m_connParams;
|
||||||
|
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
|
friend class NimBLEServer;
|
||||||
}; // class NimBLEClient
|
}; // class NimBLEClient
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
# include "NimBLEDevice.h"
|
# include "NimBLEDevice.h"
|
||||||
# include "NimBLELog.h"
|
# include "NimBLELog.h"
|
||||||
|
|
||||||
|
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
# include "NimBLEClient.h"
|
||||||
|
# endif
|
||||||
|
|
||||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
# include "services/gap/ble_svc_gap.h"
|
# include "services/gap/ble_svc_gap.h"
|
||||||
# include "services/gatt/ble_svc_gatt.h"
|
# include "services/gatt/ble_svc_gatt.h"
|
||||||
|
@ -63,6 +67,10 @@ NimBLEServer::~NimBLEServer() {
|
||||||
if (m_deleteCallbacks) {
|
if (m_deleteCallbacks) {
|
||||||
delete m_pServerCallbacks;
|
delete m_pServerCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_pClient != nullptr) {
|
||||||
|
delete m_pClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,7 +177,7 @@ void NimBLEServer::serviceChanged() {
|
||||||
*/
|
*/
|
||||||
void NimBLEServer::start() {
|
void NimBLEServer::start() {
|
||||||
if (m_gattsStarted) {
|
if (m_gattsStarted) {
|
||||||
return; //already started
|
return; // already started
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = ble_gatts_start();
|
int rc = ble_gatts_start();
|
||||||
|
@ -497,6 +505,11 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pServer->m_pClient->m_connHandle == event->disconnect.conn.conn_handle) {
|
||||||
|
// If this was also the client make sure it's flagged as disconnected.
|
||||||
|
pServer->m_pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (pServer->m_svcChanged) {
|
if (pServer->m_svcChanged) {
|
||||||
pServer->resetGATT();
|
pServer->resetGATT();
|
||||||
}
|
}
|
||||||
|
@ -1029,6 +1042,54 @@ void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
|
||||||
# endif
|
# endif
|
||||||
} // setDataLen
|
} // setDataLen
|
||||||
|
|
||||||
|
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
/**
|
||||||
|
* @brief Create a client instance from the connection handle.
|
||||||
|
* @param [in] connHandle The connection handle to create a client instance from.
|
||||||
|
* @return A pointer to the NimBLEClient instance or nullptr if there was an error.
|
||||||
|
* @note Only one instance is supported subsequent calls will overwrite the previous
|
||||||
|
* client connection information and data.
|
||||||
|
*/
|
||||||
|
NimBLEClient* NimBLEServer::getClient(uint16_t connHandle) {
|
||||||
|
NimBLEConnInfo connInfo;
|
||||||
|
int rc = ble_gap_conn_find(connHandle, &connInfo.m_desc);
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Client info not found");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getClient(connInfo);
|
||||||
|
} // getClient
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a client instance from the NimBLEConnInfo reference.
|
||||||
|
* @param [in] connInfo The connection info to create a client instance from.
|
||||||
|
* @return A pointer to the NimBLEClient instance or nullptr if there was an error.
|
||||||
|
* @note Only one instance is supported subsequent calls will overwrite the previous
|
||||||
|
* client connection information and data.
|
||||||
|
*/
|
||||||
|
NimBLEClient* NimBLEServer::getClient(const NimBLEConnInfo& connInfo) {
|
||||||
|
if (m_pClient == nullptr) {
|
||||||
|
m_pClient = new NimBLEClient(connInfo.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pClient->deleteServices(); // Changed peer connection delete the database.
|
||||||
|
m_pClient->m_peerAddress = connInfo.getAddress();
|
||||||
|
m_pClient->m_connHandle = connInfo.getConnHandle();
|
||||||
|
return m_pClient;
|
||||||
|
} // getClient
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete the NimBLEClient instance that was created with `getClient()`
|
||||||
|
*/
|
||||||
|
void NimBLEServer::deleteClient() {
|
||||||
|
if (m_pClient != nullptr) {
|
||||||
|
delete m_pClient;
|
||||||
|
m_pClient = nullptr;
|
||||||
|
}
|
||||||
|
} // deleteClient
|
||||||
|
# endif
|
||||||
|
|
||||||
/** Default callback handlers */
|
/** Default callback handlers */
|
||||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||||
|
|
|
@ -48,6 +48,9 @@ class NimBLEExtAdvertising;
|
||||||
# else
|
# else
|
||||||
class NimBLEAdvertising;
|
class NimBLEAdvertising;
|
||||||
# endif
|
# endif
|
||||||
|
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
class NimBLEClient;
|
||||||
|
# endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The model of a BLE server.
|
* @brief The model of a BLE server.
|
||||||
|
@ -77,6 +80,12 @@ class NimBLEServer {
|
||||||
void advertiseOnDisconnect(bool enable);
|
void advertiseOnDisconnect(bool enable);
|
||||||
void setDataLen(uint16_t connHandle, uint16_t tx_octets) const;
|
void setDataLen(uint16_t connHandle, uint16_t tx_octets) const;
|
||||||
|
|
||||||
|
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
NimBLEClient* getClient(uint16_t connHandle);
|
||||||
|
NimBLEClient* getClient(const NimBLEConnInfo& connInfo);
|
||||||
|
void deleteClient();
|
||||||
|
# endif
|
||||||
|
|
||||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEExtAdvertising* getAdvertising() const;
|
NimBLEExtAdvertising* getAdvertising() const;
|
||||||
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
|
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
|
||||||
|
@ -115,6 +124,10 @@ class NimBLEServer {
|
||||||
std::vector<NimBLEService*> m_svcVec;
|
std::vector<NimBLEService*> m_svcVec;
|
||||||
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
|
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
|
||||||
|
|
||||||
|
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
NimBLEClient* m_pClient{nullptr};
|
||||||
|
# endif
|
||||||
|
|
||||||
static int handleGapEvent(struct ble_gap_event* event, void* arg);
|
static int handleGapEvent(struct ble_gap_event* event, void* arg);
|
||||||
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
|
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
|
||||||
static int peerNameCB(uint16_t connHandle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);
|
static int peerNameCB(uint16_t connHandle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg);
|
||||||
|
|
Loading…
Reference in a new issue