mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-12-18 01:00:47 +01:00
[BREAKING] Refactor NimBLEServer
* General code cleanup * `NimBLEServerCallbacks::onMTUChanged` renamed to `NimBLEServerCallbacks::onMTUChange` to be consistent with the client callback. * `NimBLEServer::getPeerIDInfo` renamed to `NimBLEServer::getPeerInfoByHandle` to better describe it's use. * Use a std::array to store client connection handles instead of std::vector to reduce memory allocation. * `NimBLEServer::disconnect` now returns `bool`, true = success, instead of `int` to be consistent with the rest of the library.
This commit is contained in:
parent
c4c9f7913a
commit
d9178cfa9b
5 changed files with 448 additions and 510 deletions
|
@ -199,12 +199,7 @@ bool NimBLEAdvertising::start(uint32_t duration, const NimBLEAddress* dirAddr) {
|
|||
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||
if (pServer != nullptr) {
|
||||
if (!pServer->m_gattsStarted) {
|
||||
pServer->start();
|
||||
} else if (pServer->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise; Max connections reached");
|
||||
return false;
|
||||
}
|
||||
pServer->start(); // make sure the GATT server is ready before advertising
|
||||
}
|
||||
# endif
|
||||
|
||||
|
|
|
@ -62,9 +62,7 @@ bool NimBLEExtAdvertising::setInstanceData(uint8_t instId, NimBLEExtAdvertisemen
|
|||
# if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||
if (pServer != nullptr) {
|
||||
if (!pServer->m_gattsStarted) {
|
||||
pServer->start();
|
||||
}
|
||||
pServer->start(); // make sure the GATT server is ready before advertising
|
||||
}
|
||||
|
||||
int rc = ble_gap_ext_adv_configure(
|
||||
|
|
|
@ -27,134 +27,119 @@
|
|||
# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
|
||||
# endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <algorithm>
|
||||
|
||||
# define NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB 0
|
||||
# define NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB 1
|
||||
|
||||
static const char* LOG_TAG = "NimBLEServer";
|
||||
static NimBLEServerCallbacks defaultCallbacks;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a %BLE Server
|
||||
* @brief Construct a BLE Server
|
||||
*
|
||||
* This class is not designed to be individually instantiated. Instead one should create a server by asking
|
||||
* the NimBLEDevice class.
|
||||
* This class is not designed to be individually instantiated.
|
||||
* Instead it should be created the NimBLEDevice API.
|
||||
*/
|
||||
NimBLEServer::NimBLEServer() {
|
||||
memset(m_indWait, BLE_HS_CONN_HANDLE_NONE, sizeof(m_indWait));
|
||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
NimBLEServer::NimBLEServer()
|
||||
: m_gattsStarted{false},
|
||||
m_getPeerNameOnConnect{false},
|
||||
m_svcChanged{false},
|
||||
m_deleteCallbacks{false},
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_advertiseOnDisconnect = true;
|
||||
m_advertiseOnDisconnect{false},
|
||||
# endif
|
||||
m_svcChanged = false;
|
||||
m_deleteCallbacks = true;
|
||||
m_getPeerNameOnConnect = false;
|
||||
m_pServerCallbacks{&defaultCallbacks},
|
||||
m_svcVec{},
|
||||
m_notifyChrVec{} {
|
||||
m_connectedPeers.fill(BLE_HS_CONN_HANDLE_NONE);
|
||||
m_indWait.fill(BLE_HS_CONN_HANDLE_NONE);
|
||||
} // NimBLEServer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Destructor: frees all resources / attributes created.
|
||||
*/
|
||||
NimBLEServer::~NimBLEServer() {
|
||||
for(const auto &it : m_svcVec) {
|
||||
delete it;
|
||||
for (const auto& svc : m_svcVec) {
|
||||
delete svc;
|
||||
}
|
||||
|
||||
if(m_deleteCallbacks && m_pServerCallbacks != &defaultCallbacks) {
|
||||
if (m_deleteCallbacks) {
|
||||
delete m_pServerCallbacks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a %BLE Service.
|
||||
* @brief Create a BLE Service.
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the new service object.
|
||||
* @return A pointer to the new service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::createService(const char* uuid) {
|
||||
return createService(NimBLEUUID(uuid));
|
||||
} // createService
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a %BLE Service.
|
||||
* @brief Create a BLE Service.
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the new service object.
|
||||
* @return A pointer to the new service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::createService(const NimBLEUUID& uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
|
||||
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if(getServiceByUUID(uuid) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
|
||||
std::string(uuid).c_str());
|
||||
}
|
||||
|
||||
NimBLEService* pService = new NimBLEService(uuid);
|
||||
m_svcVec.push_back(pService);
|
||||
serviceChanged();
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< createService");
|
||||
return pService;
|
||||
} // createService
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @brief Get a BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) const {
|
||||
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
|
||||
} // getServiceByUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @brief Get a BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID& uuid, uint16_t instanceId) const {
|
||||
uint16_t position = 0;
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
for (const auto& svc : m_svcVec) {
|
||||
if (svc->getUUID() == uuid) {
|
||||
if (position == instanceId) {
|
||||
return it;
|
||||
return svc;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
} // getServiceByUUID
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its handle
|
||||
* @brief Get a BLE Service by its handle
|
||||
* @param handle The handle of the service.
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
NimBLEService* NimBLEServer::getServiceByHandle(uint16_t handle) const {
|
||||
for (const auto& svc : m_svcVec) {
|
||||
if (svc->getHandle() == handle) {
|
||||
return svc;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
* @return An advertising object.
|
||||
* @return A pinter to an advertising object.
|
||||
*/
|
||||
NimBLEExtAdvertising* NimBLEServer::getAdvertising() {
|
||||
NimBLEExtAdvertising* NimBLEServer::getAdvertising() const {
|
||||
return NimBLEDevice::getAdvertising();
|
||||
} // getAdvertising
|
||||
# endif
|
||||
|
@ -162,9 +147,9 @@ NimBLEExtAdvertising* NimBLEServer::getAdvertising() {
|
|||
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
* @return An advertising object.
|
||||
* @return A pointer to an advertising object.
|
||||
*/
|
||||
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
||||
NimBLEAdvertising* NimBLEServer::getAdvertising() const {
|
||||
return NimBLEDevice::getAdvertising();
|
||||
} // getAdvertising
|
||||
# endif
|
||||
|
@ -178,17 +163,16 @@ void NimBLEServer::serviceChanged() {
|
|||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
}
|
||||
}
|
||||
|
||||
} // serviceChanged
|
||||
|
||||
/**
|
||||
* @brief Start the GATT server. Required to be called after setup of all
|
||||
* services and characteristics / descriptors for the NimBLE host to register them.
|
||||
* @brief Start the GATT server.
|
||||
* @details Required to be called after setup of all services and characteristics / descriptors
|
||||
* for the NimBLE host to register them.
|
||||
*/
|
||||
void NimBLEServer::start() {
|
||||
if (m_gattsStarted) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Gatt server already started");
|
||||
return;
|
||||
return; //already started
|
||||
}
|
||||
|
||||
int rc = ble_gatts_start();
|
||||
|
@ -200,29 +184,17 @@ void NimBLEServer::start() {
|
|||
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
|
||||
ble_gatts_show_local();
|
||||
# endif
|
||||
/*** Future use ***
|
||||
* TODO: implement service changed handling
|
||||
|
||||
ble_uuid16_t svc = {BLE_UUID_TYPE_16, 0x1801};
|
||||
ble_uuid16_t chr = {BLE_UUID_TYPE_16, 0x2a05};
|
||||
|
||||
rc = ble_gatts_find_chr(&svc.u, &chr.u, NULL, &m_svcChgChrHdl);
|
||||
if(rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gatts_find_chr: rc=%d, %s", rc,
|
||||
NimBLEUtils::returnCodeToString(rc));
|
||||
abort();
|
||||
}
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "Service changed characterisic handle: %d", m_svcChgChrHdl);
|
||||
*/
|
||||
// Get the assigned service handles and build a vector of characteristics
|
||||
// with Notify / Indicate capabilities for event handling
|
||||
for(auto &svc : m_svcVec) {
|
||||
for (const auto& svc : m_svcVec) {
|
||||
if (svc->getRemoved() == 0) {
|
||||
rc = ble_gatts_find_svc(svc->getUUID().getBase(), &svc->m_handle);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGW(LOG_TAG, "GATT Server started without service: %s, Service %s",
|
||||
svc->getUUID().toString().c_str(), svc->isStarted() ? "missing" : "not started");
|
||||
NIMBLE_LOGW(LOG_TAG,
|
||||
"GATT Server started without service: %s, Service %s",
|
||||
svc->getUUID().toString().c_str(),
|
||||
svc->isStarted() ? "missing" : "not started");
|
||||
continue; // Skip this service as it was not started
|
||||
}
|
||||
}
|
||||
|
@ -230,16 +202,12 @@ void NimBLEServer::start() {
|
|||
for (auto& chr : svc->m_vChars) {
|
||||
// if Notify / Indicate is enabled but we didn't create the descriptor
|
||||
// we do it now.
|
||||
if((chr->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||
(chr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
||||
if ((chr->m_properties & BLE_GATT_CHR_F_INDICATE) || (chr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
||||
m_notifyChrVec.push_back(chr);
|
||||
}
|
||||
|
||||
for (auto& desc : chr->m_vDescriptors) {
|
||||
ble_gatts_find_dsc(svc->getUUID().getBase(),
|
||||
chr->getUUID().getBase(),
|
||||
desc->getUUID().getBase(),
|
||||
&desc->m_handle);
|
||||
ble_gatts_find_dsc(svc->getUUID().getBase(), chr->getUUID().getBase(), desc->getUUID().getBase(), &desc->m_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,24 +215,20 @@ void NimBLEServer::start() {
|
|||
m_gattsStarted = true;
|
||||
} // start
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disconnect the specified client with optional reason.
|
||||
* @param [in] connId Connection Id of the client to disconnect.
|
||||
* @param [in] connHandle Connection handle of the client to disconnect.
|
||||
* @param [in] reason code for disconnecting.
|
||||
* @return NimBLE host return code.
|
||||
* @return True if successful.
|
||||
*/
|
||||
int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> disconnect()");
|
||||
|
||||
int rc = ble_gap_terminate(connId, reason);
|
||||
if(rc != 0){
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc,
|
||||
NimBLEUtils::returnCodeToString(rc));
|
||||
bool NimBLEServer::disconnect(uint16_t connHandle, uint8_t reason) const {
|
||||
int rc = ble_gap_terminate(connHandle, reason);
|
||||
if (rc != 0 && rc != BLE_HS_ENOTCONN && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< disconnect()");
|
||||
return rc;
|
||||
return true;
|
||||
} // disconnect
|
||||
|
||||
/**
|
||||
|
@ -273,17 +237,17 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||
* @param [in] reason code for disconnecting.
|
||||
* @return NimBLE host return code.
|
||||
*/
|
||||
int NimBLEServer::disconnect(const NimBLEConnInfo &connInfo, uint8_t reason) {
|
||||
bool NimBLEServer::disconnect(const NimBLEConnInfo& connInfo, uint8_t reason) const {
|
||||
return disconnect(connInfo.getConnHandle(), reason);
|
||||
} // disconnect
|
||||
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Set the server to automatically start advertising when a client disconnects.
|
||||
* @param [in] aod true == advertise, false == don't advertise.
|
||||
* @param [in] enable true == advertise, false == don't advertise.
|
||||
*/
|
||||
void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
||||
m_advertiseOnDisconnect = aod;
|
||||
void NimBLEServer::advertiseOnDisconnect(bool enable) {
|
||||
m_advertiseOnDisconnect = enable;
|
||||
} // advertiseOnDisconnect
|
||||
# endif
|
||||
|
||||
|
@ -300,57 +264,78 @@ void NimBLEServer::getPeerNameOnConnect(bool enable) {
|
|||
* @brief Return the number of connected clients.
|
||||
* @return The number of connected clients.
|
||||
*/
|
||||
size_t NimBLEServer::getConnectedCount() {
|
||||
return m_connectedPeersVec.size();
|
||||
uint8_t NimBLEServer::getConnectedCount() const {
|
||||
size_t count = 0;
|
||||
for (const auto& peer : m_connectedPeers) {
|
||||
if (peer != BLE_HS_CONN_HANDLE_NONE) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
} // getConnectedCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the vector of the connected client ID's.
|
||||
* @brief Get a vector of the connected client handles.
|
||||
* @return A vector of the connected client handles.
|
||||
*/
|
||||
std::vector<uint16_t> NimBLEServer::getPeerDevices() {
|
||||
return m_connectedPeersVec;
|
||||
} // getPeerDevices
|
||||
std::vector<uint16_t> NimBLEServer::getPeerDevices() const {
|
||||
std::vector<uint16_t> peers{};
|
||||
for (const auto& peer : m_connectedPeers) {
|
||||
if (peer != BLE_HS_CONN_HANDLE_NONE) {
|
||||
peers.push_back(peer);
|
||||
}
|
||||
}
|
||||
|
||||
return peers;
|
||||
} // getPeerDevices
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by vector index.
|
||||
* @param [in] index The vector index of the peer.
|
||||
* @return A NimBLEConnInfo instance with the peer connection information, or an empty instance if not found.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(size_t index) {
|
||||
if (index >= m_connectedPeersVec.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "No peer at index %u", index);
|
||||
return NimBLEConnInfo();
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(uint8_t index) const {
|
||||
if (index >= m_connectedPeers.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid index %u", index);
|
||||
return NimBLEConnInfo{};
|
||||
}
|
||||
|
||||
return getPeerIDInfo(m_connectedPeersVec[index]);
|
||||
} // getPeerInfo
|
||||
auto count = 0;
|
||||
for (const auto& peer : m_connectedPeers) {
|
||||
if (peer != BLE_HS_CONN_HANDLE_NONE) {
|
||||
if (count == index) {
|
||||
return getPeerInfoByHandle(m_connectedPeers[count]);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return NimBLEConnInfo{};
|
||||
} // getPeerInfo
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by address.
|
||||
* @param [in] address The address of the peer.
|
||||
* @return A NimBLEConnInfo instance with the peer connection information, or an empty instance if not found.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) {
|
||||
NimBLEConnInfo peerInfo;
|
||||
int rc = ble_gap_conn_find_by_addr(address.getBase(), &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) const {
|
||||
NimBLEConnInfo peerInfo{};
|
||||
if (ble_gap_conn_find_by_addr(address.getBase(), &peerInfo.m_desc) != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by connection ID.
|
||||
* @param [in] id The connection id of the peer.
|
||||
* @brief Get the connection information of a connected peer by connection handle.
|
||||
* @param [in] connHandle The connection handle of the peer.
|
||||
* @return A NimBLEConnInfo instance with the peer connection information, or an empty instance if not found.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
NimBLEConnInfo peerInfo;
|
||||
|
||||
int rc = ble_gap_conn_find(id, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfoByHandle(uint16_t connHandle) const {
|
||||
NimBLEConnInfo peerInfo{};
|
||||
if (ble_gap_conn_find(connHandle, &peerInfo.m_desc) != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
|
@ -361,13 +346,10 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
|||
* @brief Callback that is called after reading from the peer name characteristic.
|
||||
* @details This will check the task pointer in the task data struct to determine
|
||||
* the action to take once the name has been read. If there is a task waiting then
|
||||
* it will be woken, if not, the the RC value is checked to determine which callback
|
||||
* it will be resumed, if not, the the RC value is checked to determine which callback
|
||||
* should be called.
|
||||
*/
|
||||
int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg) {
|
||||
int NimBLEServer::peerNameCB(uint16_t connHandle, const ble_gatt_error* error, ble_gatt_attr* attr, void* arg) {
|
||||
NimBLETaskData* pTaskData = (NimBLETaskData*)arg;
|
||||
std::string* name = (std::string*)pTaskData->m_pBuf;
|
||||
int rc = error->status;
|
||||
|
@ -383,7 +365,7 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
|||
if (pTaskData->m_flags != -1) {
|
||||
NimBLEServer* pServer = (NimBLEServer*)pTaskData->m_pInstance;
|
||||
NimBLEConnInfo peerInfo{};
|
||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||
|
||||
// check the flag to indicate which callback should be called.
|
||||
if (pTaskData->m_flags == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||
|
@ -408,30 +390,25 @@ int NimBLEServer::peerNameCB(uint16_t conn_handle,
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Internal method that sends the read command.
|
||||
* @brief Implementation of the function that sends the read command.
|
||||
*/
|
||||
std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, int cb_type) {
|
||||
std::string NimBLEServer::getPeerNameImpl(uint16_t connHandle, int cbType) const {
|
||||
std::string* buf = new std::string{};
|
||||
NimBLETaskData *pTaskData = new NimBLETaskData(this, cb_type, buf);
|
||||
NimBLETaskData* pTaskData = new NimBLETaskData(const_cast<NimBLEServer*>(this), cbType, buf);
|
||||
ble_uuid16_t uuid{{BLE_UUID_TYPE_16}, BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME};
|
||||
int rc = ble_gattc_read_by_uuid(conn_handle,
|
||||
1,
|
||||
0xffff,
|
||||
&uuid.u,
|
||||
NimBLEServer::peerNameCB,
|
||||
pTaskData);
|
||||
int rc = ble_gattc_read_by_uuid(connHandle, 1, 0xffff, &uuid.u, NimBLEServer::peerNameCB, pTaskData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_read_by_uuid rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
NimBLEConnInfo peerInfo{};
|
||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||
if (cb_type == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||
m_pServerCallbacks->onConnect(this, peerInfo, *buf);
|
||||
} else if (cb_type == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||
if (cbType == NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB) {
|
||||
m_pServerCallbacks->onConnect(const_cast<NimBLEServer*>(this), peerInfo, *buf);
|
||||
} else if (cbType == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
|
||||
m_pServerCallbacks->onAuthenticationComplete(peerInfo, *buf);
|
||||
}
|
||||
delete buf;
|
||||
delete pTaskData;
|
||||
} else if (cb_type == -1) {
|
||||
} else if (cbType == -1) {
|
||||
NimBLEUtils::taskWait(*pTaskData, BLE_NPL_TIME_FOREVER);
|
||||
rc = pTaskData->m_flags;
|
||||
std::string name{*(std::string*)pTaskData->m_pBuf};
|
||||
|
@ -454,29 +431,22 @@ std::string NimBLEServer::getPeerNameInternal(uint16_t conn_handle, int cb_type)
|
|||
* @returns A string containing the name.
|
||||
* @note This is a blocking call and should NOT be called from any callbacks!
|
||||
*/
|
||||
std::string NimBLEServer::getPeerName(const NimBLEConnInfo& connInfo) {
|
||||
std::string name = getPeerNameInternal(connInfo.getConnHandle());
|
||||
std::string NimBLEServer::getPeerName(const NimBLEConnInfo& connInfo) const {
|
||||
std::string name = getPeerNameImpl(connInfo.getConnHandle());
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle a GATT Server Event.
|
||||
*
|
||||
* @param [in] event
|
||||
* @param [in] gatts_if
|
||||
* @param [in] param
|
||||
*
|
||||
* @brief Gap event handler.
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s", NimBLEUtils::gapEventToString(event->type));
|
||||
|
||||
int rc = 0;
|
||||
NimBLEConnInfo peerInfo;
|
||||
NimBLEConnInfo peerInfo{};
|
||||
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||
|
||||
switch (event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_CONNECT: {
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising */
|
||||
|
@ -490,21 +460,23 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
pServer->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||
for (auto& peer : pServer->m_connectedPeers) {
|
||||
if (peer == BLE_HS_CONN_HANDLE_NONE) {
|
||||
peer = event->connect.conn_handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pServer->m_getPeerNameOnConnect) {
|
||||
pServer->getPeerNameInternal(event->connect.conn_handle,
|
||||
NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
|
||||
pServer->getPeerNameImpl(event->connect.conn_handle, NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
|
||||
} else {
|
||||
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_CONNECT
|
||||
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT: {
|
||||
// If Host reset tell the device now before returning to prevent
|
||||
// any errors caused by calling host functions before resync.
|
||||
|
@ -520,73 +492,70 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
break;
|
||||
}
|
||||
|
||||
pServer->m_connectedPeersVec.erase(std::remove(pServer->m_connectedPeersVec.begin(),
|
||||
pServer->m_connectedPeersVec.end(),
|
||||
event->disconnect.conn.conn_handle),
|
||||
pServer->m_connectedPeersVec.end());
|
||||
for (auto& peer : pServer->m_connectedPeers) {
|
||||
if (peer == event->disconnect.conn.conn_handle) {
|
||||
peer = BLE_HS_CONN_HANDLE_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pServer->m_svcChanged) {
|
||||
pServer->resetGATT();
|
||||
}
|
||||
|
||||
NimBLEConnInfo peerInfo(event->disconnect.conn);
|
||||
peerInfo.m_desc = event->disconnect.conn;
|
||||
pServer->m_pServerCallbacks->onDisconnect(pServer, peerInfo, event->disconnect.reason);
|
||||
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
if (pServer->m_advertiseOnDisconnect) {
|
||||
pServer->startAdvertising();
|
||||
}
|
||||
# endif
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_DISCONNECT
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE: {
|
||||
NIMBLE_LOGI(LOG_TAG, "subscribe event; attr_handle=%d, subscribed: %s",
|
||||
NIMBLE_LOGI(LOG_TAG,
|
||||
"subscribe event; attr_handle=%d, subscribed: %s",
|
||||
event->subscribe.attr_handle,
|
||||
(event->subscribe.cur_notify ? "true" : "false"));
|
||||
|
||||
for(auto &it : pServer->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->subscribe.attr_handle) {
|
||||
for (const auto& chr : pServer->m_notifyChrVec) {
|
||||
if (chr->getHandle() == event->subscribe.attr_handle) {
|
||||
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(((it->getProperties() & BLE_GATT_CHR_F_READ_AUTHEN) ||
|
||||
(it->getProperties() & BLE_GATT_CHR_F_READ_AUTHOR) ||
|
||||
(it->getProperties() & BLE_GATT_CHR_F_READ_ENC)) &&
|
||||
!peerInfo.isEncrypted()) {
|
||||
auto chrProps = chr->getProperties();
|
||||
if (!peerInfo.isEncrypted() &&
|
||||
(chrProps & BLE_GATT_CHR_F_READ_AUTHEN || chrProps & BLE_GATT_CHR_F_READ_AUTHOR ||
|
||||
chrProps & BLE_GATT_CHR_F_READ_ENC)) {
|
||||
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
||||
}
|
||||
|
||||
it->setSubscribe(event, peerInfo);
|
||||
chr->setSubscribe(event, peerInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_SUBSCRIBE
|
||||
|
||||
case BLE_GAP_EVENT_MTU: {
|
||||
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
|
||||
event->mtu.conn_handle,
|
||||
event->mtu.value);
|
||||
|
||||
rc = ble_gap_conn_find(event->mtu.conn_handle, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d", event->mtu.conn_handle, event->mtu.value);
|
||||
if (ble_gap_conn_find(event->mtu.conn_handle, &peerInfo.m_desc) == 0) {
|
||||
pServer->m_pServerCallbacks->onMTUChange(event->mtu.value, peerInfo);
|
||||
}
|
||||
|
||||
pServer->m_pServerCallbacks->onMTUChange(event->mtu.value, peerInfo);
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_MTU
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||
NimBLECharacteristic* pChar = nullptr;
|
||||
|
||||
for(auto &it : pServer->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
pChar = it;
|
||||
for (auto& chr : pServer->m_notifyChrVec) {
|
||||
if (chr->getHandle() == event->notify_tx.attr_handle) {
|
||||
pChar = chr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,28 +571,24 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
}
|
||||
|
||||
pChar->m_pCallbacks->onStatus(pChar, event->notify_tx.status);
|
||||
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
|
||||
return NimBLEExtAdvertising::handleGapEvent(event, arg);
|
||||
# else
|
||||
return NimBLEAdvertising::handleGapEvent(event, arg);
|
||||
# endif
|
||||
// BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
|
||||
} // BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
|
||||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
if (ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc) == 0) {
|
||||
pServer->m_pServerCallbacks->onConnParamsUpdate(peerInfo);
|
||||
}
|
||||
|
||||
pServer->m_pServerCallbacks->onConnParamsUpdate(peerInfo);
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_CONN_UPDATE
|
||||
|
||||
case BLE_GAP_EVENT_REPEAT_PAIRING: {
|
||||
|
@ -653,12 +618,12 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
}
|
||||
|
||||
if (pServer->m_getPeerNameOnConnect) {
|
||||
pServer->getPeerNameInternal(event->enc_change.conn_handle,
|
||||
NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
|
||||
pServer->getPeerNameImpl(event->enc_change.conn_handle, NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
|
||||
} else {
|
||||
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
|
||||
}
|
||||
return 0;
|
||||
|
||||
break;
|
||||
} // BLE_GAP_EVENT_ENC_CHANGE
|
||||
|
||||
case BLE_GAP_EVENT_IDENTITY_RESOLVED: {
|
||||
|
@ -668,7 +633,7 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
}
|
||||
|
||||
pServer->m_pServerCallbacks->onIdentity(peerInfo);
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
|
@ -678,9 +643,7 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
return BLE_ATT_ERR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
pServer->m_pServerCallbacks->onPhyUpdate(peerInfo,
|
||||
event->phy_updated.tx_phy,
|
||||
event->phy_updated.rx_phy);
|
||||
pServer->m_pServerCallbacks->onPhyUpdate(peerInfo, event->phy_updated.tx_phy, event->phy_updated.rx_phy);
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_PHY_UPDATE_COMPLETE
|
||||
# endif
|
||||
|
@ -709,22 +672,20 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
}
|
||||
|
||||
pServer->m_pServerCallbacks->onConfirmPassKey(peerInfo, event->passkey.params.numcmp);
|
||||
//TODO: Handle out of band pairing
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
|
||||
static uint8_t tem_oob[16] = {0};
|
||||
pkey.action = event->passkey.params.action;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
pkey.oob[i] = tem_oob[i];
|
||||
}
|
||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc);
|
||||
//////////////////////////////////
|
||||
// TODO: Handle out of band pairing
|
||||
// static uint8_t tem_oob[16] = {0};
|
||||
// pkey.action = event->passkey.params.action;
|
||||
// for (int i = 0; i < 16; i++) {
|
||||
// pkey.oob[i] = tem_oob[i];
|
||||
// }
|
||||
// rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||
// NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_OOB; ble_sm_inject_io result: %d", rc);
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
|
||||
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
|
||||
return 0;
|
||||
break;
|
||||
} // BLE_GAP_EVENT_PASSKEY_ACTION
|
||||
|
||||
default:
|
||||
|
@ -735,27 +696,25 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||
return 0;
|
||||
} // handleGapEvent
|
||||
|
||||
|
||||
/**
|
||||
* @brief STATIC callback to handle events from the NimBLE stack.
|
||||
* @brief GATT event handler.
|
||||
*/
|
||||
int NimBLEServer::handleGattEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Gatt %s event", (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ||
|
||||
ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
|
||||
int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg) {
|
||||
NIMBLE_LOGD(LOG_TAG,
|
||||
"Gatt %s event",
|
||||
(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
|
||||
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||
const auto& val = pAtt->getAttVal();
|
||||
NimBLEConnInfo peerInfo{};
|
||||
ble_gap_conn_find(conn_handle, &peerInfo.m_desc);
|
||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC:
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8 ||
|
||||
conn_handle == BLE_HS_CONN_HANDLE_NONE ||
|
||||
val.size() <= (ble_att_mtu(conn_handle) - 3)) {
|
||||
if (ctxt->om->om_pkthdr_len > 8 || connHandle == BLE_HS_CONN_HANDLE_NONE ||
|
||||
val.size() <= (ble_att_mtu(connHandle) - 3)) {
|
||||
pAtt->readEvent(peerInfo);
|
||||
}
|
||||
|
||||
|
@ -801,7 +760,7 @@ int NimBLEServer::handleGattEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||
/**
|
||||
* @brief Set the server callbacks.
|
||||
*
|
||||
* As a %BLE server operates, it will generate server level events such as a new client connecting or a previous client
|
||||
* As a BLE server operates, it will generate server level events such as a new client connecting or a previous client
|
||||
* disconnecting. This function can be called to register a callback handler that will be invoked when these
|
||||
* events are detected.
|
||||
*
|
||||
|
@ -814,10 +773,10 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCa
|
|||
m_deleteCallbacks = deleteCallbacks;
|
||||
} else {
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_deleteCallbacks = false;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a service from the server.
|
||||
*
|
||||
|
@ -864,8 +823,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
|||
# if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||
# endif
|
||||
}
|
||||
|
||||
} // removeService
|
||||
|
||||
/**
|
||||
* @brief Adds a service which was either already created but removed from availability,\n
|
||||
|
@ -877,8 +835,7 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
|||
void NimBLEServer::addService(NimBLEService* service) {
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if (getServiceByUUID(service->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
|
||||
std::string(service->getUUID()).c_str());
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s", std::string(service->getUUID()).c_str());
|
||||
}
|
||||
|
||||
// If adding a service that was not removed add it and return.
|
||||
|
@ -892,7 +849,6 @@ void NimBLEServer::addService(NimBLEService* service) {
|
|||
serviceChanged();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Resets the GATT server, used when services are added/removed after initialization.
|
||||
*/
|
||||
|
@ -923,33 +879,29 @@ void NimBLEServer::resetGATT() {
|
|||
|
||||
m_svcChanged = false;
|
||||
m_gattsStarted = false;
|
||||
}
|
||||
|
||||
} // resetGATT
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||
* @param [in] instId The extended advertisement instance ID to start.
|
||||
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||
* @param [in] maxEvents Maximum number of advertisement events to send, 0 = no limit (default).
|
||||
* @return True if advertising started successfully.
|
||||
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* retrieving the advertising object and invoking start upon it.
|
||||
*/
|
||||
bool NimBLEServer::startAdvertising(uint8_t inst_id,
|
||||
int duration,
|
||||
int max_events) {
|
||||
return getAdvertising()->start(inst_id, duration, max_events);
|
||||
bool NimBLEServer::startAdvertising(uint8_t instId, int duration, int maxEvents) const {
|
||||
return getAdvertising()->start(instId, duration, maxEvents);
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convenience function to stop advertising a data set.
|
||||
* @param [in] inst_id The extended advertisement instance ID to stop advertising.
|
||||
* @param [in] instId The extended advertisement instance ID to stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
bool NimBLEServer::stopAdvertising(uint8_t inst_id) {
|
||||
return getAdvertising()->stop(inst_id);
|
||||
bool NimBLEServer::stopAdvertising(uint8_t instId) const {
|
||||
return getAdvertising()->stop(instId);
|
||||
} // stopAdvertising
|
||||
|
||||
/**
|
||||
|
@ -1005,86 +957,78 @@ bool NimBLEServer::getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy) {
|
|||
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* retrieving the advertising object and invoking start upon it.
|
||||
*/
|
||||
bool NimBLEServer::startAdvertising(uint32_t duration) {
|
||||
bool NimBLEServer::startAdvertising(uint32_t duration) const {
|
||||
return getAdvertising()->start(duration);
|
||||
} // startAdvertising
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
bool NimBLEServer::stopAdvertising() {
|
||||
bool NimBLEServer::stopAdvertising() const {
|
||||
return getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Get the MTU of the client.
|
||||
* @returns The client MTU or 0 if not found/connected.
|
||||
* @brief Get the MTU value of a client connection.
|
||||
* @param [in] connHandle The connection handle of the client to get the MTU value for.
|
||||
* @returns The MTU or 0 if not found/connected.
|
||||
*/
|
||||
uint16_t NimBLEServer::getPeerMTU(uint16_t conn_id) {
|
||||
return ble_att_mtu(conn_id);
|
||||
uint16_t NimBLEServer::getPeerMTU(uint16_t connHandle) const {
|
||||
return ble_att_mtu(connHandle);
|
||||
} // getPeerMTU
|
||||
|
||||
|
||||
/**
|
||||
* @brief Request an Update the connection parameters:
|
||||
* * Can only be used after a connection has been established.
|
||||
* @param [in] conn_handle The connection handle of the peer to send the request to.
|
||||
* @param [in] connHandle The connection handle of the peer to send the request to.
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
|
||||
* @param [in] latency The number of packets allowed to skip (extends max interval).
|
||||
* @param [in] timeout The timeout time in 10ms units before disconnecting.
|
||||
*/
|
||||
void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout)
|
||||
{
|
||||
ble_gap_upd_params params;
|
||||
void NimBLEServer::updateConnParams(
|
||||
uint16_t connHandle, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout) const {
|
||||
ble_gap_upd_params params = {.itvl_min = minInterval,
|
||||
.itvl_max = maxInterval,
|
||||
.latency = latency,
|
||||
.supervision_timeout = timeout,
|
||||
.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN,
|
||||
.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN};
|
||||
|
||||
params.latency = latency;
|
||||
params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
|
||||
params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
|
||||
|
||||
int rc = ble_gap_update_params(conn_handle, ¶ms);
|
||||
int rc = ble_gap_update_params(connHandle, ¶ms);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
} // updateConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Request an update of the data packet length.
|
||||
* * Can only be used after a connection has been established.
|
||||
* @details Sends a data length update request to the peer.
|
||||
* The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes.
|
||||
* The peer needs to support the Bluetooth 4.2 specifications, to be capable of DLE.
|
||||
* @param [in] conn_handle The connection handle of the peer to send the request to.
|
||||
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
* @param [in] connHandle The connection handle of the peer to send the request to.
|
||||
* @param [in] octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
|
||||
*/
|
||||
void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) {
|
||||
void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
|
||||
(ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
|
||||
return;
|
||||
# else
|
||||
uint16_t tx_time = (tx_octets + 14) * 8;
|
||||
uint16_t tx_time = (octets + 14) * 8;
|
||||
|
||||
int rc = ble_gap_set_data_len(conn_handle, tx_octets, tx_time);
|
||||
int rc = ble_gap_set_data_len(connHandle, octets, tx_time);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
# endif
|
||||
} // setDataLen
|
||||
|
||||
|
||||
bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
|
||||
bool NimBLEServer::setIndicateWait(uint16_t connHandle) {
|
||||
for (auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
if (m_indWait[i] == connHandle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1092,17 +1036,15 @@ bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEServer::clearIndicateWait(uint16_t conn_handle) {
|
||||
void NimBLEServer::clearIndicateWait(uint16_t connHandle) {
|
||||
for (auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
if (m_indWait[i] == connHandle) {
|
||||
m_indWait[i] = BLE_HS_CONN_HANDLE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
|
@ -1112,8 +1054,7 @@ void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& con
|
|||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
} // onConnect
|
||||
|
||||
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer,
|
||||
NimBLEConnInfo& connInfo, int reason) {
|
||||
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
||||
} // onDisconnect
|
||||
|
||||
|
|
|
@ -12,123 +12,122 @@
|
|||
* Author: kolban
|
||||
*/
|
||||
|
||||
#ifndef MAIN_NIMBLESERVER_H_
|
||||
#define MAIN_NIMBLESERVER_H_
|
||||
#ifndef NIMBLE_CPP_SERVER_H_
|
||||
#define NIMBLE_CPP_SERVER_H_
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
class NimBLEServer;
|
||||
class NimBLEServerCallbacks;
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEAddress.h"
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#include "NimBLEExtAdvertising.h"
|
||||
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||
# include "host/ble_gap.h"
|
||||
# else
|
||||
#include "NimBLEAdvertising.h"
|
||||
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||
# endif
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
|
||||
/**** FIX COMPILATION ****/
|
||||
# undef min
|
||||
# undef max
|
||||
/**************************/
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <array>
|
||||
|
||||
# define NIMBLE_ATT_REMOVE_HIDE 1
|
||||
# define NIMBLE_ATT_REMOVE_DELETE 2
|
||||
|
||||
#define onMtuChanged onMTUChange
|
||||
class NimBLEService;
|
||||
class NimBLEServerCallbacks;
|
||||
class NimBLEUUID;
|
||||
class NimBLEConnInfo;
|
||||
class NimBLEAddress;
|
||||
class NimBLEService;
|
||||
class NimBLECharacteristic;
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
class NimBLEExtAdvertising;
|
||||
# else
|
||||
class NimBLEAdvertising;
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief The model of a %BLE server.
|
||||
* @brief The model of a BLE server.
|
||||
*/
|
||||
class NimBLEServer {
|
||||
public:
|
||||
size_t getConnectedCount();
|
||||
void start();
|
||||
uint8_t getConnectedCount() const;
|
||||
bool disconnect(uint16_t connHandle, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM) const;
|
||||
bool disconnect(const NimBLEConnInfo& connInfo, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM) const;
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCallbacks = true);
|
||||
void updateConnParams(uint16_t connHandle, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout) const;
|
||||
NimBLEService* createService(const char* uuid);
|
||||
NimBLEService* createService(const NimBLEUUID& uuid);
|
||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0) const;
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID& uuid, uint16_t instanceId = 0) const;
|
||||
NimBLEService* getServiceByHandle(uint16_t handle) const;
|
||||
void removeService(NimBLEService* service, bool deleteSvc = false);
|
||||
void addService(NimBLEService* service);
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
||||
bool deleteCallbacks = true);
|
||||
uint16_t getPeerMTU(uint16_t connHandle) const;
|
||||
std::vector<uint16_t> getPeerDevices() const;
|
||||
NimBLEConnInfo getPeerInfo(uint8_t index) const;
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address) const;
|
||||
NimBLEConnInfo getPeerInfoByHandle(uint16_t connHandle) const;
|
||||
std::string getPeerName(const NimBLEConnInfo& connInfo) const;
|
||||
void getPeerNameOnConnect(bool enable);
|
||||
void advertiseOnDisconnect(bool enable);
|
||||
void setDataLen(uint16_t connHandle, uint16_t tx_octets) const;
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEExtAdvertising* getAdvertising();
|
||||
bool startAdvertising(uint8_t inst_id,
|
||||
int duration = 0,
|
||||
int max_events = 0);
|
||||
bool stopAdvertising(uint8_t inst_id);
|
||||
NimBLEExtAdvertising* getAdvertising() const;
|
||||
bool startAdvertising(uint8_t instanceId, int duration = 0, int maxEvents = 0) const;
|
||||
bool stopAdvertising(uint8_t instanceId) const;
|
||||
bool updatePhy(uint16_t connHandle, uint8_t txPhysMask, uint8_t rxPhysMask, uint16_t phyOptions);
|
||||
bool getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy);
|
||||
# endif
|
||||
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
bool startAdvertising(uint32_t duration = 0);
|
||||
#endif
|
||||
bool stopAdvertising();
|
||||
void start();
|
||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||
int disconnect(uint16_t connID,
|
||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
int disconnect(const NimBLEConnInfo &connInfo,
|
||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
void updateConnParams(uint16_t conn_handle,
|
||||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void setDataLen(uint16_t conn_handle, uint16_t tx_octets);
|
||||
uint16_t getPeerMTU(uint16_t conn_id);
|
||||
std::vector<uint16_t> getPeerDevices();
|
||||
NimBLEConnInfo getPeerInfo(size_t index);
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
std::string getPeerName(const NimBLEConnInfo& connInfo);
|
||||
void getPeerNameOnConnect(bool enable);
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
void advertiseOnDisconnect(bool);
|
||||
NimBLEAdvertising* getAdvertising() const;
|
||||
bool startAdvertising(uint32_t duration = 0) const;
|
||||
bool stopAdvertising() const;
|
||||
# endif
|
||||
|
||||
private:
|
||||
NimBLEServer();
|
||||
~NimBLEServer();
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEAdvertising;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLECharacteristic;
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
friend class NimBLEExtAdvertising;
|
||||
friend class NimBLEExtAdvertisementData;
|
||||
# else
|
||||
friend class NimBLEAdvertising;
|
||||
# endif
|
||||
|
||||
bool m_gattsStarted;
|
||||
NimBLEServer();
|
||||
~NimBLEServer();
|
||||
|
||||
bool m_gattsStarted : 1;
|
||||
bool m_getPeerNameOnConnect : 1;
|
||||
bool m_svcChanged : 1;
|
||||
bool m_deleteCallbacks : 1;
|
||||
# if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
bool m_advertiseOnDisconnect;
|
||||
bool m_advertiseOnDisconnect : 1;
|
||||
# endif
|
||||
bool m_getPeerNameOnConnect;
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
uint16_t m_indWait[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||
std::vector<uint16_t> m_connectedPeersVec;
|
||||
|
||||
// uint16_t m_svcChgChrHdl; // Future use
|
||||
|
||||
std::vector<NimBLEService*> m_svcVec;
|
||||
std::vector<NimBLECharacteristic*> m_notifyChrVec;
|
||||
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_connectedPeers;
|
||||
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_indWait;
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event* event, void* arg);
|
||||
static int peerNameCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
std::string getPeerNameInternal(uint16_t conn_handle, int cb_type = -1);
|
||||
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);
|
||||
std::string getPeerNameImpl(uint16_t connHandle, int cb_type = -1) const;
|
||||
void serviceChanged();
|
||||
void resetGATT();
|
||||
bool setIndicateWait(uint16_t conn_handle);
|
||||
void clearIndicateWait(uint16_t conn_handle);
|
||||
|
||||
static int handleGattEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
bool setIndicateWait(uint16_t connHandle);
|
||||
void clearIndicateWait(uint16_t connHandle);
|
||||
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callbacks associated with the operation of a %BLE server.
|
||||
*/
|
||||
|
@ -232,5 +231,5 @@ public:
|
|||
# endif
|
||||
}; // NimBLEServerCallbacks
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
||||
#endif /* MAIN_NIMBLESERVER_H_ */
|
||||
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif // NIMBLE_CPP_SERVER_H_
|
||||
|
|
|
@ -17,8 +17,13 @@
|
|||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
# include "NimBLEDevice.h"
|
||||
# include "NimBLEService.h"
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
# include "NimBLEExtAdvertising.h"
|
||||
# else
|
||||
# include "NimBLEAdvertising.h"
|
||||
# endif
|
||||
# include "NimBLEDevice.h"
|
||||
# include "NimBLEUtils.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue