Files
esp-nimble-cpp/src/NimBLEServer.cpp

1078 lines
39 KiB
C++
Raw Normal View History

2020-03-29 17:44:20 -06:00
/*
* NimBLEServer.cpp
*
* Created: on March 2, 2020
* Author H2zero
*
2020-03-29 17:44:20 -06:00
* Originally:
*
* BLEServer.cpp
*
* Created on: Apr 16, 2017
* Author: kolban
*/
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
# include "NimBLEServer.h"
# include "NimBLEDevice.h"
# include "NimBLELog.h"
# if defined(CONFIG_NIMBLE_CPP_IDF)
# include "services/gap/ble_svc_gap.h"
# include "services/gatt/ble_svc_gatt.h"
# else
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
# endif
# 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";
2020-03-29 17:44:20 -06:00
static NimBLEServerCallbacks defaultCallbacks;
/**
* @brief Construct a BLE Server
2020-03-29 17:44:20 -06:00
*
* This class is not designed to be individually instantiated.
* Instead it should be created the NimBLEDevice API.
2020-03-29 17:44:20 -06:00
*/
NimBLEServer::NimBLEServer()
: m_gattsStarted{false},
m_getPeerNameOnConnect{false},
m_svcChanged{false},
m_deleteCallbacks{false},
# if !CONFIG_BT_NIMBLE_EXT_ADV
m_advertiseOnDisconnect{false},
# endif
m_pServerCallbacks{&defaultCallbacks},
m_svcVec{} {
m_connectedPeers.fill(BLE_HS_CONN_HANDLE_NONE);
} // NimBLEServer
2020-03-29 17:44:20 -06:00
/**
* @brief Destructor: frees all resources / attributes created.
*/
NimBLEServer::~NimBLEServer() {
for (const auto& svc : m_svcVec) {
delete svc;
}
if (m_deleteCallbacks) {
delete m_pServerCallbacks;
}
}
2020-03-29 17:44:20 -06:00
/**
* @brief Create a BLE Service.
2020-03-29 17:44:20 -06:00
* @param [in] uuid The UUID of the new service.
* @return A pointer to the new service object.
2020-03-29 17:44:20 -06:00
*/
NimBLEService* NimBLEServer::createService(const char* uuid) {
return createService(NimBLEUUID(uuid));
} // createService
2020-03-29 17:44:20 -06:00
/**
* @brief Create a BLE Service.
2020-03-29 17:44:20 -06:00
* @param [in] uuid The UUID of the new service.
* @return A pointer to the new service object.
2020-03-29 17:44:20 -06:00
*/
NimBLEService* NimBLEServer::createService(const NimBLEUUID& uuid) {
NimBLEService* pService = new NimBLEService(uuid);
m_svcVec.push_back(pService);
serviceChanged();
return pService;
2020-03-29 17:44:20 -06:00
} // createService
/**
* @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.
2020-03-29 17:44:20 -06:00
*/
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) const {
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
} // getServiceByUUID
2020-03-29 17:44:20 -06:00
/**
* @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.
2020-03-29 17:44:20 -06:00
*/
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID& uuid, uint16_t instanceId) const {
uint16_t position = 0;
for (const auto& svc : m_svcVec) {
if (svc->getUUID() == uuid) {
if (position == instanceId) {
return svc;
}
position++;
}
}
return nullptr;
} // getServiceByUUID
2020-03-29 17:44:20 -06:00
/**
* @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) const {
for (const auto& svc : m_svcVec) {
if (svc->getHandle() == handle) {
return svc;
}
}
return nullptr;
}
2020-03-29 17:44:20 -06:00
# if CONFIG_BT_NIMBLE_EXT_ADV
2020-03-29 17:44:20 -06:00
/**
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
* @return A pinter to an advertising object.
2020-03-29 17:44:20 -06:00
*/
NimBLEExtAdvertising* NimBLEServer::getAdvertising() const {
return NimBLEDevice::getAdvertising();
} // getAdvertising
# endif
2020-03-29 17:44:20 -06:00
# 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 A pointer to an advertising object.
*/
NimBLEAdvertising* NimBLEServer::getAdvertising() const {
return NimBLEDevice::getAdvertising();
} // getAdvertising
# endif
2020-03-29 17:44:20 -06:00
/**
* @brief Sends a service changed notification and resets the GATT server.
*/
void NimBLEServer::serviceChanged() {
if (m_gattsStarted) {
m_svcChanged = true;
ble_svc_gatt_changed(0x0001, 0xffff);
resetGATT();
}
} // serviceChanged
2020-03-29 17:44:20 -06:00
/**
* @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.
2020-03-29 17:44:20 -06:00
*/
void NimBLEServer::start() {
if (m_gattsStarted) {
return; //already started
}
2020-03-29 17:44:20 -06:00
int rc = ble_gatts_start();
if (rc != 0) {
2024-07-03 14:27:31 -06:00
NIMBLE_LOGE(LOG_TAG, "ble_gatts_start; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
return;
2020-03-29 17:44:20 -06:00
}
# if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
2020-03-29 17:44:20 -06:00
ble_gatts_show_local();
# endif
// Get the assigned service handles and build a vector of characteristics
// with Notify / Indicate capabilities for event handling
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");
continue; // Skip this service as it was not started
}
}
// Set the descriptor handles now as the stack does not set these when the service is started
for (const auto& chr : svc->m_vChars) {
for (auto& desc : chr->m_vDescriptors) {
ble_gatts_find_dsc(svc->getUUID().getBase(), chr->getUUID().getBase(), desc->getUUID().getBase(), &desc->m_handle);
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
}
2020-03-29 17:44:20 -06:00
}
}
m_gattsStarted = true;
} // start
2020-03-29 17:44:20 -06:00
/**
* @brief Disconnect the specified client with optional reason.
* @param [in] connHandle Connection handle of the client to disconnect.
* @param [in] reason code for disconnecting.
* @return True if successful.
2020-03-29 17:44:20 -06:00
*/
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;
2020-03-29 17:44:20 -06:00
}
return true;
} // disconnect
/**
* @brief Disconnect the specified client with optional reason.
* @param [in] connInfo Connection of the client to disconnect.
* @param [in] reason code for disconnecting.
* @return NimBLE host return code.
*/
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] enable true == advertise, false == don't advertise.
*/
void NimBLEServer::advertiseOnDisconnect(bool enable) {
m_advertiseOnDisconnect = enable;
} // advertiseOnDisconnect
# endif
2020-03-29 17:44:20 -06:00
/**
* @brief Set the server to automatically read the name from the connected peer before
* the onConnect callback is called and enables the override callback with name parameter.
* @param [in] enable Enable reading the connected peer name upon connection.
*/
void NimBLEServer::getPeerNameOnConnect(bool enable) {
m_getPeerNameOnConnect = enable;
} // getPeerNameOnConnect
2020-03-29 17:44:20 -06:00
/**
* @brief Return the number of connected clients.
* @return The number of connected clients.
*/
uint8_t NimBLEServer::getConnectedCount() const {
size_t count = 0;
for (const auto& peer : m_connectedPeers) {
if (peer != BLE_HS_CONN_HANDLE_NONE) {
count++;
}
}
2020-03-29 17:44:20 -06:00
return count;
} // getConnectedCount
2020-03-29 17:44:20 -06:00
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
/**
* @brief Get a vector of the connected client handles.
* @return A vector of the connected client handles.
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
*/
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);
}
}
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
return peers;
} // getPeerDevices
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
/**
* @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.
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
*/
NimBLEConnInfo NimBLEServer::getPeerInfo(uint8_t index) const {
if (index >= m_connectedPeers.size()) {
NIMBLE_LOGE(LOG_TAG, "Invalid index %u", index);
return NimBLEConnInfo{};
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
}
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++;
}
}
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
return NimBLEConnInfo{};
} // getPeerInfo
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
/**
* @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.
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
*/
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) const {
NimBLEConnInfo peerInfo{};
if (ble_gap_conn_find_by_addr(address.getBase(), &peerInfo.m_desc) != 0) {
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
}
return peerInfo;
} // getPeerInfo
/**
* @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.
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
*/
NimBLEConnInfo NimBLEServer::getPeerInfoByHandle(uint16_t connHandle) const {
NimBLEConnInfo peerInfo{};
if (ble_gap_conn_find(connHandle, &peerInfo.m_desc) != 0) {
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
}
return peerInfo;
} // getPeerIDInfo
/**
* @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 resumed, if not, the the RC value is checked to determine which callback
* should be called.
*/
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;
if (rc == 0) {
if (attr) {
name->append(OS_MBUF_DATA(attr->om, char*), OS_MBUF_PKTLEN(attr->om));
return rc;
}
}
if (rc == BLE_HS_EDONE) {
if (pTaskData->m_flags != -1) {
NimBLEServer* pServer = (NimBLEServer*)pTaskData->m_pInstance;
NimBLEConnInfo peerInfo{};
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) {
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo, *name);
} else if (pTaskData->m_flags == NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB) {
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo, *name);
}
}
} else {
NIMBLE_LOGE(LOG_TAG, "NimBLEServerPeerNameCB rc=%d; %s", rc, NimBLEUtils::returnCodeToString(rc));
}
if (pTaskData->m_flags == -1) {
NimBLEUtils::taskRelease(*pTaskData, rc);
} else {
// If the read was triggered for callback use then these were allocated.
delete name;
delete pTaskData;
}
return rc;
}
/**
* @brief Implementation of the function that sends the read command.
*/
std::string NimBLEServer::getPeerNameImpl(uint16_t connHandle, int cbType) const {
std::string* buf = new std::string{};
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(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(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 (cbType == -1) {
NimBLEUtils::taskWait(*pTaskData, BLE_NPL_TIME_FOREVER);
rc = pTaskData->m_flags;
std::string name{*(std::string*)pTaskData->m_pBuf};
delete buf;
delete pTaskData;
if (rc != 0 && rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "getPeerName rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
}
return name;
}
// TaskData and name buffer will be deleted in the callback.
return "";
}
/**
* @brief Get the name of the connected peer.
* @param connInfo A reference to a NimBLEConnInfo instance to read the name from.
* @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) const {
std::string name = getPeerNameImpl(connInfo.getConnHandle());
return name;
}
Add connection info class and access methods to server and client. This adds the ability to access information about the current connection. A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information. Example server use: ``` for(auto i=0; i<pServer->getConnectedCount();i++) { NimBLEConnInfo connInfo = pServer->getPeerInfo(i); printf("Connected client %d info:\n", i); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ``` Example client use: ``` if (pClient->isConnected()) { NimBLEConnInfo connInfo = pClient->getConnInfo(); printf("Connection info:\n"); printf("Peer address: %s\n", connInfo.getAddress().toString().c_str()); printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str()); printf("Handle: %u\n", connInfo.getConnHandle()); printf("Interval: %u\n", connInfo.getConnInterval()); printf("Timeout: %u\n", connInfo.getConnTimeout()); printf("Latency: %u\n", connInfo.getConnLatency()); printf("MTU: %u\n", connInfo.getMTU()); printf("Master: %s\n", connInfo.isMaster()? "true":"false"); printf("Slave: %s\n", connInfo.isSlave()? "true":"false"); printf("Bonded: %s\n", connInfo.isBonded()? "true":"false"); printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false"); printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false"); printf("Encryption Key Size: %u\n", connInfo.getSecKeySize()); } ```
2021-05-07 09:02:43 -06:00
2020-03-29 17:44:20 -06:00
/**
* @brief Gap event handler.
2020-03-29 17:44:20 -06:00
*/
int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s", NimBLEUtils::gapEventToString(event->type));
int rc = 0;
NimBLEConnInfo peerInfo{};
NimBLEServer* pServer = NimBLEDevice::getServer();
switch (event->type) {
case BLE_GAP_EVENT_CONNECT: {
2020-03-29 17:44:20 -06:00
if (event->connect.status != 0) {
/* Connection failed; resume advertising */
NIMBLE_LOGE(LOG_TAG, "Connection failed");
# if !CONFIG_BT_NIMBLE_EXT_ADV
2020-03-29 17:44:20 -06:00
NimBLEDevice::startAdvertising();
# endif
} else {
rc = ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc);
2021-05-07 11:06:45 -06:00
if (rc != 0) {
return 0;
}
for (auto& peer : pServer->m_connectedPeers) {
if (peer == BLE_HS_CONN_HANDLE_NONE) {
peer = event->connect.conn_handle;
break;
}
}
if (pServer->m_getPeerNameOnConnect) {
pServer->getPeerNameImpl(event->connect.conn_handle, NIMBLE_SERVER_GET_PEER_NAME_ON_CONNECT_CB);
} else {
pServer->m_pServerCallbacks->onConnect(pServer, peerInfo);
}
2020-03-29 17:44:20 -06:00
}
break;
} // BLE_GAP_EVENT_CONNECT
2020-03-29 17:44:20 -06:00
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.
switch (event->disconnect.reason) {
2020-03-29 17:44:20 -06:00
case BLE_HS_ETIMEOUT_HCI:
case BLE_HS_EOS:
case BLE_HS_ECONTROLLER:
case BLE_HS_ENOTSYNCED:
NIMBLE_LOGE(LOG_TAG, "Disconnect - host reset, rc=%d", event->disconnect.reason);
2020-03-29 17:44:20 -06:00
NimBLEDevice::onReset(event->disconnect.reason);
break;
default:
2020-03-29 17:44:20 -06:00
break;
}
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();
}
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
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_DISCONNECT
2020-03-29 17:44:20 -06:00
case BLE_GAP_EVENT_SUBSCRIBE: {
NIMBLE_LOGI(LOG_TAG,
"subscribe event; attr_handle=%d, subscribed: %s",
event->subscribe.attr_handle,
(event->subscribe.cur_notify ? "true" : "false"));
for (const auto& svc : pServer->m_svcVec) {
for (const auto& chr : svc->m_vChars) {
if (chr->getHandle() == event->subscribe.attr_handle) {
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
break;
}
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);
}
chr->m_pCallbacks->onSubscribe(chr,
peerInfo,
event->subscribe.cur_notify + event->subscribe.cur_indicate);
}
}
2020-03-29 17:44:20 -06:00
}
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_SUBSCRIBE
2020-03-29 17:44:20 -06:00
case BLE_GAP_EVENT_MTU: {
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);
}
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_MTU
2020-03-29 17:44:20 -06:00
case BLE_GAP_EVENT_NOTIFY_TX: {
NimBLECharacteristic* pChar = nullptr;
for (const auto& svc : pServer->m_svcVec) {
for (auto& chr : svc->m_vChars) {
if (chr->getHandle() == event->notify_tx.attr_handle) {
pChar = chr;
}
}
}
if (pChar == nullptr) {
return 0;
}
if (event->notify_tx.indication) {
if (event->notify_tx.status == 0) {
return 0; // Indication sent but not yet acknowledged.
2020-03-29 17:44:20 -06:00
}
}
pChar->m_pCallbacks->onStatus(pChar, event->notify_tx.status);
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_NOTIFY_TX
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
2020-03-29 17:44:20 -06:00
case BLE_GAP_EVENT_CONN_UPDATE: {
if (ble_gap_conn_find(event->connect.conn_handle, &peerInfo.m_desc) == 0) {
pServer->m_pServerCallbacks->onConnParamsUpdate(peerInfo);
}
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_CONN_UPDATE
2020-04-23 15:17:09 -06:00
case BLE_GAP_EVENT_REPEAT_PAIRING: {
/* We already have a bond with the peer, but it is attempting to
* establish a new secure link. This app sacrifices security for
* convenience: just throw away the old bond and accept the new link.
*/
/* Delete the old bond. */
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
2021-05-07 11:06:45 -06:00
return BLE_GAP_REPEAT_PAIRING_IGNORE;
}
ble_store_util_delete_peer(&peerInfo.m_desc.peer_id_addr);
2020-04-23 15:17:09 -06:00
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
* continue with the pairing operation.
*/
return BLE_GAP_REPEAT_PAIRING_RETRY;
} // BLE_GAP_EVENT_REPEAT_PAIRING
case BLE_GAP_EVENT_ENC_CHANGE: {
rc = ble_gap_conn_find(event->enc_change.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
2020-03-29 17:44:20 -06:00
return BLE_ATT_ERR_INVALID_HANDLE;
}
if (pServer->m_getPeerNameOnConnect) {
pServer->getPeerNameImpl(event->enc_change.conn_handle, NIMBLE_SERVER_GET_PEER_NAME_ON_AUTH_CB);
} else {
pServer->m_pServerCallbacks->onAuthenticationComplete(peerInfo);
}
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_ENC_CHANGE
case BLE_GAP_EVENT_IDENTITY_RESOLVED: {
rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
return BLE_ATT_ERR_INVALID_HANDLE;
}
pServer->m_pServerCallbacks->onIdentity(peerInfo);
break;
} // BLE_GAP_EVENT_IDENTITY_RESOLVED
# if CONFIG_BT_NIMBLE_EXT_ADV
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: {
rc = ble_gap_conn_find(event->phy_updated.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
return BLE_ATT_ERR_INVALID_HANDLE;
}
pServer->m_pServerCallbacks->onPhyUpdate(peerInfo, event->phy_updated.tx_phy, event->phy_updated.rx_phy);
return 0;
} // BLE_GAP_EVENT_PHY_UPDATE_COMPLETE
# endif
2020-03-29 17:44:20 -06:00
case BLE_GAP_EVENT_PASSKEY_ACTION: {
struct ble_sm_io pkey = {0, 0};
2020-03-29 17:44:20 -06:00
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
pkey.action = event->passkey.params.action;
2020-03-29 17:44:20 -06:00
// backward compatibility
pkey.passkey = NimBLEDevice::getSecurityPasskey(); // This is the passkey to be entered on peer
// if the (static)passkey is the default, check the callback for custom value
// both values default to the same.
if (pkey.passkey == 123456) {
pkey.passkey = pServer->m_pServerCallbacks->onPassKeyDisplay();
2020-03-29 17:44:20 -06:00
}
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
2020-03-29 17:44:20 -06:00
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
2022-01-15 12:43:17 -07:00
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
rc = ble_gap_conn_find(event->passkey.conn_handle, &peerInfo.m_desc);
if (rc != 0) {
return BLE_ATT_ERR_INVALID_HANDLE;
}
pServer->m_pServerCallbacks->onConfirmPassKey(peerInfo, event->passkey.params.numcmp);
2020-03-29 17:44:20 -06:00
} else if (event->passkey.params.action == BLE_SM_IOACT_OOB) {
// 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);
2020-03-29 17:44:20 -06:00
} else if (event->passkey.params.action == BLE_SM_IOACT_NONE) {
NIMBLE_LOGD(LOG_TAG, "No passkey action required");
}
break;
2020-03-29 17:44:20 -06:00
} // BLE_GAP_EVENT_PASSKEY_ACTION
default:
break;
}
2020-03-29 17:44:20 -06:00
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
2020-03-29 17:44:20 -06:00
return 0;
} // handleGapEvent
2020-03-29 17:44:20 -06:00
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
/**
* @brief GATT event handler.
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
*/
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);
auto val = pAtt->getAttVal();
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
NimBLEConnInfo peerInfo{};
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
switch (ctxt->op) {
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
case BLE_GATT_ACCESS_OP_READ_DSC:
case BLE_GATT_ACCESS_OP_READ_CHR: {
// Don't call readEvent if this is an internal read (handle is NONE)
if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
// If the packet header is only 8 bytes then 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 || pAtt->getAttVal().size() <= (ble_att_mtu(connHandle) - 3)) {
pAtt->readEvent(peerInfo);
}
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
}
ble_npl_hw_enter_critical();
int rc = os_mbuf_append(ctxt->om, val.data(), val.size());
ble_npl_hw_exit_critical(0);
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
case BLE_GATT_ACCESS_OP_WRITE_DSC:
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
uint16_t maxLen = val.max_size();
if (ctxt->om->om_len > maxLen) {
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
uint8_t buf[maxLen];
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
uint16_t len = ctxt->om->om_len;
memcpy(buf, ctxt->om->om_data, len);
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
os_mbuf* next;
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
next = SLIST_NEXT(ctxt->om, om_next);
while (next != NULL) {
if ((len + next->om_len) > maxLen) {
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
memcpy(&buf[len], next->om_data, next->om_len);
len += next->om_len;
next = SLIST_NEXT(next, om_next);
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
}
pAtt->writeEvent(buf, len, peerInfo);
return 0;
}
default:
break;
}
return BLE_ATT_ERR_UNLIKELY;
} // handleGattEvent
2020-03-29 17:44:20 -06:00
/**
* @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 disconnecting. This function can be called to register a callback handler that will be invoked when these
2020-03-29 17:44:20 -06:00
* events are detected.
*
* @param [in] pCallbacks The callbacks to be invoked.
* @param [in] deleteCallbacks if true callback class will be deleted when server is destructed.
2020-03-29 17:44:20 -06:00
*/
void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCallbacks) {
if (pCallbacks != nullptr) {
m_pServerCallbacks = pCallbacks;
m_deleteCallbacks = deleteCallbacks;
} else {
m_pServerCallbacks = &defaultCallbacks;
m_deleteCallbacks = false;
}
2020-03-29 17:44:20 -06:00
} // setCallbacks
/**
* @brief Remove a service from the server.
*
* @details Immediately removes access to the service by clients, sends a service changed indication,
* and removes the service (if applicable) from the advertisements.
* The service is not deleted unless the deleteSvc parameter is true, otherwise the service remains
* available and can be re-added in the future. If desired a removed but not deleted service can
* be deleted later by calling this method with deleteSvc set to true.
*
* @note The service will not be removed from the database until all open connections are closed
* as it requires resetting the GATT server. In the interim the service will have it's visibility disabled.
*
* @note Advertising will need to be restarted by the user after calling this as we must stop
* advertising in order to remove the service.
*
* @param [in] service The service object to remove.
* @param [in] deleteSvc true if the service should be deleted.
*/
void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
// Check if the service was already removed and if so check if this
// is being called to delete the object and do so if requested.
// Otherwise, ignore the call and return.
if (service->getRemoved() > 0) {
if (deleteSvc) {
for (auto it = m_svcVec.begin(); it != m_svcVec.end(); ++it) {
if ((*it) == service) {
delete *it;
m_svcVec.erase(it);
break;
}
}
}
return;
}
int rc = ble_gatts_svc_set_visibility(service->getHandle(), 0);
if (rc != 0) {
return;
}
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
service->setRemoved(deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE);
serviceChanged();
# 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
* or created and later added to services list.
* @param [in] service The service object to add.
* @note If it is desired to advertise the service it must be added by
* calling NimBLEAdvertising::addServiceUUID.
*/
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());
}
// If adding a service that was not removed add it and return.
// Else reset GATT and send service changed notification.
if (service->getRemoved() == 0) {
m_svcVec.push_back(service);
return;
}
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
service->setRemoved(0);
serviceChanged();
}
/**
* @brief Resets the GATT server, used when services are added/removed after initialization.
*/
void NimBLEServer::resetGATT() {
if (getConnectedCount() > 0) {
return;
}
NimBLEDevice::stopAdvertising();
ble_gatts_reset();
ble_svc_gap_init();
ble_svc_gatt_init();
for (auto it = m_svcVec.begin(); it != m_svcVec.end();) {
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 14:47:36 -06:00
if ((*it)->getRemoved() > 0) {
if ((*it)->getRemoved() == NIMBLE_ATT_REMOVE_DELETE) {
delete *it;
it = m_svcVec.erase(it);
} else {
++it;
}
continue;
}
(*it)->start();
++it;
}
m_svcChanged = false;
m_gattsStarted = false;
} // resetGATT
# if CONFIG_BT_NIMBLE_EXT_ADV
2020-03-29 17:44:20 -06:00
/**
* @brief Start advertising.
* @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] 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
2020-03-29 17:44:20 -06:00
* retrieving the advertising object and invoking start upon it.
*/
bool NimBLEServer::startAdvertising(uint8_t instId, int duration, int maxEvents) const {
return getAdvertising()->start(instId, duration, maxEvents);
2020-03-29 17:44:20 -06:00
} // startAdvertising
/**
* @brief Convenience function to stop advertising a data set.
* @param [in] instId The extended advertisement instance ID to stop advertising.
* @return True if advertising stopped successfully.
*/
bool NimBLEServer::stopAdvertising(uint8_t instId) const {
return getAdvertising()->stop(instId);
} // stopAdvertising
/**
* @brief Request an update to the PHY used for a peer connection.
* @param [in] connHandle the connection handle to the update the PHY for.
* @param [in] txPhyMask TX PHY. Can be mask of following:
* - BLE_GAP_LE_PHY_1M_MASK
* - BLE_GAP_LE_PHY_2M_MASK
* - BLE_GAP_LE_PHY_CODED_MASK
* - BLE_GAP_LE_PHY_ANY_MASK
* @param [in] rxPhyMask RX PHY. Can be mask of following:
* - BLE_GAP_LE_PHY_1M_MASK
* - BLE_GAP_LE_PHY_2M_MASK
* - BLE_GAP_LE_PHY_CODED_MASK
* - BLE_GAP_LE_PHY_ANY_MASK
* @param phyOptions Additional PHY options. Valid values are:
* - BLE_GAP_LE_PHY_CODED_ANY (default)
* - BLE_GAP_LE_PHY_CODED_S2
* - BLE_GAP_LE_PHY_CODED_S8
* @return True if successful.
*/
bool NimBLEServer::updatePhy(uint16_t connHandle, uint8_t txPhyMask, uint8_t rxPhyMask, uint16_t phyOptions) {
int rc = ble_gap_set_prefered_le_phy(connHandle, txPhyMask, rxPhyMask, phyOptions);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Failed to update phy; rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
}
return rc == 0;
} // updatePhy
/**
* @brief Get the PHY used for a peer connection.
* @param [in] connHandle the connection handle to the get the PHY for.
* @param [out] txPhy The TX PHY.
* @param [out] rxPhy The RX PHY.
* @return True if successful.
*/
bool NimBLEServer::getPhy(uint16_t connHandle, uint8_t* txPhy, uint8_t* rxPhy) {
int rc = ble_gap_read_le_phy(connHandle, txPhy, rxPhy);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Failed to read phy; rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
}
return rc == 0;
} // getPhy
# endif
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Start advertising.
* @param [in] duration The duration in milliseconds to advertise for, default = forever.
* @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(uint32_t duration) const {
return getAdvertising()->start(duration);
} // startAdvertising
2020-03-29 17:44:20 -06:00
/**
* @brief Stop advertising.
* @return True if advertising stopped successfully.
2020-03-29 17:44:20 -06:00
*/
bool NimBLEServer::stopAdvertising() const {
return getAdvertising()->stop();
} // stopAdvertising
# endif
2020-03-29 17:44:20 -06:00
/**
* @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 connHandle) const {
return ble_att_mtu(connHandle);
} // getPeerMTU
/**
2021-01-20 15:20:11 -07:00
* @brief Request an Update the connection parameters:
* * Can only be used after a connection has been established.
* @param [in] connHandle The connection handle of the peer to send the request to.
2021-01-20 15:20:11 -07:00
* @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.
2020-03-29 17:44:20 -06:00
*/
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};
int rc = ble_gap_update_params(connHandle, &params);
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] 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 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 = (octets + 14) * 8;
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
/** Default callback handlers */
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
2020-03-29 17:44:20 -06:00
} // onConnect
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, std::string& name) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
} // onConnect
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
2020-03-29 17:44:20 -06:00
} // onDisconnect
void NimBLEServerCallbacks::onMTUChange(uint16_t MTU, NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onMTUChange(): Default");
} // onMTUChange
uint32_t NimBLEServerCallbacks::onPassKeyDisplay() {
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyDisplay: default: 123456");
2020-03-29 17:44:20 -06:00
return 123456;
} // onPassKeyDisplay
2020-03-29 17:44:20 -06:00
void NimBLEServerCallbacks::onConfirmPassKey(NimBLEConnInfo& connInfo, uint32_t pin) {
2020-03-29 17:44:20 -06:00
NIMBLE_LOGD("NimBLEServerCallbacks", "onConfirmPIN: default: true");
NimBLEDevice::injectConfirmPasskey(connInfo, true);
} // onConfirmPIN
2020-03-29 17:44:20 -06:00
void NimBLEServerCallbacks::onIdentity(NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onIdentity: default");
} // onIdentity
void NimBLEServerCallbacks::onAuthenticationComplete(NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
} // onAuthenticationComplete
void NimBLEServerCallbacks::onAuthenticationComplete(NimBLEConnInfo& connInfo, const std::string& name) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
} // onAuthenticationComplete
void NimBLEServerCallbacks::onConnParamsUpdate(NimBLEConnInfo& connInfo) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnParamsUpdate: default");
} // onConnParamsUpdate
# if CONFIG_BT_NIMBLE_EXT_ADV
void NimBLEServerCallbacks::onPhyUpdate(NimBLEConnInfo& connInfo, uint8_t txPhy, uint8_t rxPhy) {
NIMBLE_LOGD("NimBLEServerCallbacks", "onPhyUpdate: default, txPhy: %d, rxPhy: %d", txPhy, rxPhy);
} // onPhyUpdate
# endif
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */