mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-12-18 09:10:47 +01:00
Remove characteristic subscription tracking.
Removes tracking of client characteristic subscription status from `NimBLEServer` and `NimBLECharacteristic` and instead uses the functions and tracking in the host stack. * `NimBLECharacteristic::notify` and `NimBLECharacteristic::indicate` now return a `bool`, true = success.
This commit is contained in:
parent
d9178cfa9b
commit
a12f3d4785
5 changed files with 131 additions and 235 deletions
|
@ -18,9 +18,6 @@
|
||||||
# include "NimBLEDevice.h"
|
# include "NimBLEDevice.h"
|
||||||
# include "NimBLELog.h"
|
# include "NimBLELog.h"
|
||||||
|
|
||||||
# define NIMBLE_SUB_NOTIFY 0x0001
|
|
||||||
# define NIMBLE_SUB_INDICATE 0x0002
|
|
||||||
|
|
||||||
static NimBLECharacteristicCallbacks defaultCallback;
|
static NimBLECharacteristicCallbacks defaultCallback;
|
||||||
static const char* LOG_TAG = "NimBLECharacteristic";
|
static const char* LOG_TAG = "NimBLECharacteristic";
|
||||||
|
|
||||||
|
@ -28,21 +25,21 @@ static const char* LOG_TAG = "NimBLECharacteristic";
|
||||||
* @brief Construct a characteristic
|
* @brief Construct a characteristic
|
||||||
* @param [in] uuid - UUID (const char*) for the characteristic.
|
* @param [in] uuid - UUID (const char*) for the characteristic.
|
||||||
* @param [in] properties - Properties for the characteristic.
|
* @param [in] properties - Properties for the characteristic.
|
||||||
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
* @param [in] maxLen - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
||||||
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, uint16_t max_len, NimBLEService* pService)
|
NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, uint16_t maxLen, NimBLEService* pService)
|
||||||
: NimBLECharacteristic(NimBLEUUID(uuid), properties, max_len, pService) {}
|
: NimBLECharacteristic(NimBLEUUID(uuid), properties, maxLen, pService) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a characteristic
|
* @brief Construct a characteristic
|
||||||
* @param [in] uuid - UUID for the characteristic.
|
* @param [in] uuid - UUID for the characteristic.
|
||||||
* @param [in] properties - Properties for the characteristic.
|
* @param [in] properties - Properties for the characteristic.
|
||||||
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
* @param [in] maxLen - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
|
||||||
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
* @param [in] pService - pointer to the service instance this characteristic belongs to.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID& uuid, uint16_t properties, uint16_t max_len, NimBLEService* pService)
|
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID& uuid, uint16_t properties, uint16_t maxLen, NimBLEService* pService)
|
||||||
: NimBLELocalValueAttribute{uuid, 0, max_len}, m_pCallbacks{&defaultCallback}, m_pService{pService} {
|
: NimBLELocalValueAttribute{uuid, 0, maxLen}, m_pCallbacks{&defaultCallback}, m_pService{pService} {
|
||||||
setProperties(properties);
|
setProperties(properties);
|
||||||
} // NimBLECharacteristic
|
} // NimBLECharacteristic
|
||||||
|
|
||||||
|
@ -59,26 +56,26 @@ NimBLECharacteristic::~NimBLECharacteristic() {
|
||||||
* @brief Create a new BLE Descriptor associated with this characteristic.
|
* @brief Create a new BLE Descriptor associated with this characteristic.
|
||||||
* @param [in] uuid - The UUID of the descriptor.
|
* @param [in] uuid - The UUID of the descriptor.
|
||||||
* @param [in] properties - The properties of the descriptor.
|
* @param [in] properties - The properties of the descriptor.
|
||||||
* @param [in] max_len - The max length in bytes of the descriptor value.
|
* @param [in] maxLen - The max length in bytes of the descriptor value.
|
||||||
* @return The new BLE descriptor.
|
* @return The new BLE descriptor.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) {
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t maxLen) {
|
||||||
return createDescriptor(NimBLEUUID(uuid), properties, max_len);
|
return createDescriptor(NimBLEUUID(uuid), properties, maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new BLE Descriptor associated with this characteristic.
|
* @brief Create a new BLE Descriptor associated with this characteristic.
|
||||||
* @param [in] uuid - The UUID of the descriptor.
|
* @param [in] uuid - The UUID of the descriptor.
|
||||||
* @param [in] properties - The properties of the descriptor.
|
* @param [in] properties - The properties of the descriptor.
|
||||||
* @param [in] max_len - The max length in bytes of the descriptor value.
|
* @param [in] maxLen - The max length in bytes of the descriptor value.
|
||||||
* @return The new BLE descriptor.
|
* @return The new BLE descriptor.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID& uuid, uint32_t properties, uint16_t max_len) {
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID& uuid, uint32_t properties, uint16_t maxLen) {
|
||||||
NimBLEDescriptor* pDescriptor = nullptr;
|
NimBLEDescriptor* pDescriptor = nullptr;
|
||||||
if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
||||||
pDescriptor = new NimBLE2904(this);
|
pDescriptor = new NimBLE2904(this);
|
||||||
} else {
|
} else {
|
||||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
pDescriptor = new NimBLEDescriptor(uuid, properties, maxLen, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
addDescriptor(pDescriptor);
|
addDescriptor(pDescriptor);
|
||||||
|
@ -199,182 +196,108 @@ void NimBLECharacteristic::setService(NimBLEService* pService) {
|
||||||
m_pService = pService;
|
m_pService = pService;
|
||||||
} // setService
|
} // setService
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the number of clients subscribed to the characteristic.
|
|
||||||
* @returns Number of clients subscribed to notifications / indications.
|
|
||||||
*/
|
|
||||||
size_t NimBLECharacteristic::getSubscribedCount() const {
|
|
||||||
return m_subscribedVec.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the subscribe status for this characteristic.\n
|
|
||||||
* This will maintain a vector of subscribed clients and their indicate/notify status.
|
|
||||||
*/
|
|
||||||
void NimBLECharacteristic::setSubscribe(const ble_gap_event* event, NimBLEConnInfo& connInfo) {
|
|
||||||
uint16_t subVal = 0;
|
|
||||||
if (event->subscribe.cur_notify > 0 && (m_properties & NIMBLE_PROPERTY::NOTIFY)) {
|
|
||||||
subVal |= NIMBLE_SUB_NOTIFY;
|
|
||||||
}
|
|
||||||
if (event->subscribe.cur_indicate && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
|
||||||
subVal |= NIMBLE_SUB_INDICATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", connInfo.getConnHandle(), subVal);
|
|
||||||
|
|
||||||
if (!event->subscribe.cur_indicate && event->subscribe.prev_indicate) {
|
|
||||||
NimBLEDevice::getServer()->clearIndicateWait(connInfo.getConnHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = m_subscribedVec.begin();
|
|
||||||
for (; it != m_subscribedVec.end(); ++it) {
|
|
||||||
if ((*it).first == connInfo.getConnHandle()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subVal > 0) {
|
|
||||||
if (it == m_subscribedVec.end()) {
|
|
||||||
m_subscribedVec.push_back({connInfo.getConnHandle(), subVal});
|
|
||||||
} else {
|
|
||||||
(*it).second = subVal;
|
|
||||||
}
|
|
||||||
} else if (it != m_subscribedVec.end()) {
|
|
||||||
m_subscribedVec.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pCallbacks->onSubscribe(this, connInfo, subVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send an indication.
|
* @brief Send an indication.
|
||||||
* @param[in] conn_handle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
* @param[in] connHandle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
||||||
* the indication to all subscribed clients.
|
* the indication to all subscribed clients.
|
||||||
|
* @return True if the indication was sent successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::indicate(uint16_t conn_handle) const {
|
bool NimBLECharacteristic::indicate(uint16_t connHandle) const {
|
||||||
sendValue(m_value.data(), m_value.size(), false, conn_handle);
|
return sendValue(nullptr, 0, false, connHandle);
|
||||||
} // indicate
|
} // indicate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send an indication.
|
* @brief Send an indication.
|
||||||
* @param[in] value A pointer to the data to send.
|
* @param[in] value A pointer to the data to send.
|
||||||
* @param[in] length The length of the data to send.
|
* @param[in] length The length of the data to send.
|
||||||
* @param[in] conn_handle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
* @param[in] connHandle Connection handle to send an individual indication, or BLE_HS_CONN_HANDLE_NONE to send
|
||||||
* the indication to all subscribed clients.
|
* the indication to all subscribed clients.
|
||||||
|
* @return True if the indication was sent successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::indicate(const uint8_t* value, size_t length, uint16_t conn_handle) const {
|
bool NimBLECharacteristic::indicate(const uint8_t* value, size_t length, uint16_t connHandle) const {
|
||||||
sendValue(value, length, false, conn_handle);
|
return sendValue(value, length, false, connHandle);
|
||||||
} // indicate
|
} // indicate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a notification.
|
* @brief Send a notification.
|
||||||
* @param[in] conn_handle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
* @param[in] connHandle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
||||||
* the notification to all subscribed clients.
|
* the notification to all subscribed clients.
|
||||||
|
* @return True if the notification was sent successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::notify(uint16_t conn_handle) const {
|
bool NimBLECharacteristic::notify(uint16_t connHandle) const {
|
||||||
sendValue(m_value.data(), m_value.size(), true, conn_handle);
|
return sendValue(nullptr, 0, true, connHandle);
|
||||||
} // notify
|
} // notify
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a notification.
|
* @brief Send a notification.
|
||||||
* @param[in] value A pointer to the data to send.
|
* @param[in] value A pointer to the data to send.
|
||||||
* @param[in] length The length of the data to send.
|
* @param[in] length The length of the data to send.
|
||||||
* @param[in] conn_handle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
* @param[in] connHandle Connection handle to send an individual notification, or BLE_HS_CONN_HANDLE_NONE to send
|
||||||
* the notification to all subscribed clients.
|
* the notification to all subscribed clients.
|
||||||
|
* @return True if the notification was sent successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::notify(const uint8_t* value, size_t length, uint16_t conn_handle) const {
|
bool NimBLECharacteristic::notify(const uint8_t* value, size_t length, uint16_t connHandle) const {
|
||||||
sendValue(value, length, true, conn_handle);
|
return sendValue(value, length, true, connHandle);
|
||||||
} // indicate
|
} // indicate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends a notification or indication.
|
* @brief Sends a notification or indication.
|
||||||
* @param[in] value A pointer to the data to send.
|
* @param[in] value A pointer to the data to send.
|
||||||
* @param[in] length The length of the data to send.
|
* @param[in] length The length of the data to send.
|
||||||
* @param[in] is_notification if true sends a notification, false sends an indication.
|
* @param[in] isNotification if true sends a notification, false sends an indication.
|
||||||
* @param[in] conn_handle Connection handle to send to a specific peer, or BLE_HS_CONN_HANDLE_NONE to send
|
* @param[in] connHandle Connection handle to send to a specific peer.
|
||||||
* to all subscribed clients.
|
* @return True if the value was sent successfully, false otherwise.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool is_notification, uint16_t conn_handle) const {
|
bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool isNotification, uint16_t connHandle) const {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> sendValue");
|
int rc = 0;
|
||||||
|
|
||||||
if (is_notification && !(getProperties() & NIMBLE_PROPERTY::NOTIFY)) {
|
if (value != nullptr && length > 0) { // custom notification value
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: notification not enabled for characteristic");
|
// Notify all connected peers unless a specific handle is provided
|
||||||
return;
|
for (const auto& ch : NimBLEDevice::getServer()->getPeerDevices()) {
|
||||||
}
|
if (connHandle != BLE_HS_CONN_HANDLE_NONE && ch != connHandle) {
|
||||||
|
continue; // only send to the specific handle, minor inefficiency but saves code.
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_notification && !(getProperties() & NIMBLE_PROPERTY::INDICATE)) {
|
// Must re-create the data buffer on each iteration because it is freed by the calls bellow.
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: indication not enabled for characteristic");
|
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
|
||||||
return;
|
if (!om) {
|
||||||
}
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to allocate mbuf");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_subscribedVec.size()) {
|
if (isNotification) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< sendValue: No clients subscribed.");
|
rc = ble_gattc_notify_custom(ch, m_handle, om);
|
||||||
return;
|
} else {
|
||||||
}
|
rc = ble_gattc_indicate_custom(ch, m_handle, om);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& it : m_subscribedVec) {
|
if (rc != 0) {
|
||||||
// check if connected and subscribed
|
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to send value, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
if (!it.second) {
|
break;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sending to a specific client?
|
|
||||||
if ((conn_handle <= BLE_HCI_LE_CONN_HANDLE_MAX) && (it.first != conn_handle)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_notification && !(it.second & NIMBLE_SUB_NOTIFY)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_notification && !(it.second & NIMBLE_SUB_INDICATE)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if security requirements are satisfied
|
|
||||||
if ((getProperties() & BLE_GATT_CHR_F_READ_AUTHEN) || (getProperties() & BLE_GATT_CHR_F_READ_AUTHOR) ||
|
|
||||||
(getProperties() & BLE_GATT_CHR_F_READ_ENC)) {
|
|
||||||
ble_gap_conn_desc desc;
|
|
||||||
if (ble_gap_conn_find(it.first, &desc) != 0 || !desc.sec_state.encrypted) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
|
||||||
// don't create the m_buf until we are sure to send the data or else
|
// Null buffer will read the value from the characteristic
|
||||||
// we could be allocating a buffer that doesn't get released.
|
if (isNotification) {
|
||||||
// We also must create it in each loop iteration because it is consumed with each host call.
|
rc = ble_gattc_notify_custom(connHandle, m_handle, NULL);
|
||||||
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
|
|
||||||
if (!om) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to allocate mbuf");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_notification) {
|
|
||||||
ble_gattc_notify_custom(it.first, getHandle(), om);
|
|
||||||
} else {
|
} else {
|
||||||
if (!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
|
rc = ble_gattc_indicate_custom(connHandle, m_handle, NULL);
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: waiting for previous indicate");
|
|
||||||
os_mbuf_free_chain(om);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ble_gattc_indicate_custom(it.first, getHandle(), om) != 0) {
|
|
||||||
NimBLEDevice::getServer()->clearIndicateWait(it.first);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else { // Notify or indicate to all connected peers the characteristic value
|
||||||
|
ble_gatts_chr_updated(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< sendValue");
|
return rc == 0;
|
||||||
} // sendValue
|
} // sendValue
|
||||||
|
|
||||||
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
|
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
|
||||||
m_pCallbacks->onRead(this, connInfo);
|
m_pCallbacks->onRead(this, connInfo);
|
||||||
}
|
} // readEvent
|
||||||
|
|
||||||
void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) {
|
void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) {
|
||||||
setValue(val, len);
|
setValue(val, len);
|
||||||
m_pCallbacks->onWrite(this, connInfo);
|
m_pCallbacks->onWrite(this, connInfo);
|
||||||
}
|
} // writeEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the callback handlers for this characteristic.
|
* @brief Set the callback handlers for this characteristic.
|
||||||
|
@ -455,7 +378,7 @@ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacterist
|
||||||
* * 3 = Notifications and Indications
|
* * 3 = Notifications and Indications
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
|
void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
|
||||||
NimBLEConnInfo& connInfo,
|
NimBLEConnInfo& connInfo,
|
||||||
uint16_t subValue) {
|
uint16_t subValue) {
|
||||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,32 +39,31 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
||||||
public:
|
public:
|
||||||
NimBLECharacteristic(const char* uuid,
|
NimBLECharacteristic(const char* uuid,
|
||||||
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
|
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
|
||||||
NimBLEService* pService = nullptr);
|
NimBLEService* pService = nullptr);
|
||||||
NimBLECharacteristic(const NimBLEUUID& uuid,
|
NimBLECharacteristic(const NimBLEUUID& uuid,
|
||||||
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
|
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
|
||||||
NimBLEService* pService = nullptr);
|
NimBLEService* pService = nullptr);
|
||||||
|
|
||||||
~NimBLECharacteristic();
|
~NimBLECharacteristic();
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
size_t getSubscribedCount() const;
|
|
||||||
void addDescriptor(NimBLEDescriptor* pDescriptor);
|
void addDescriptor(NimBLEDescriptor* pDescriptor);
|
||||||
void removeDescriptor(NimBLEDescriptor* pDescriptor, bool deleteDsc = false);
|
void removeDescriptor(NimBLEDescriptor* pDescriptor, bool deleteDsc = false);
|
||||||
uint16_t getProperties() const;
|
uint16_t getProperties() const;
|
||||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||||
void indicate(uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
bool indicate(uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
|
||||||
void indicate(const uint8_t* value, size_t length, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
bool indicate(const uint8_t* value, size_t length, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
|
||||||
void notify(uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
bool notify(uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
|
||||||
void notify(const uint8_t* value, size_t length, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
bool notify(const uint8_t* value, size_t length, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
|
||||||
|
|
||||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN);
|
||||||
NimBLEDescriptor* createDescriptor(const NimBLEUUID& uuid,
|
NimBLEDescriptor* createDescriptor(const NimBLEUUID& uuid,
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN);
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid) const;
|
NimBLEDescriptor* getDescriptorByUUID(const char* uuid) const;
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID& uuid) const;
|
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID& uuid) const;
|
||||||
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle) const;
|
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle) const;
|
||||||
|
@ -81,18 +80,18 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
||||||
* pointer and getting the length of the array using sizeof.
|
* pointer and getting the length of the array using sizeof.
|
||||||
* @tparam T The a reference to a class containing the data to send.
|
* @tparam T The a reference to a class containing the data to send.
|
||||||
* @param[in] value The <type\>value to set.
|
* @param[in] value The <type\>value to set.
|
||||||
* @param[in] conn_handle The connection handle to send the notification to.
|
* @param[in] connHandle The connection handle to send the notification to.
|
||||||
* @note This function is only available if the type T is not a pointer.
|
* @note This function is only available if the type T is not a pointer.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!std::is_pointer<T>::value, void>::type
|
typename std::enable_if<!std::is_pointer<T>::value, bool>::type notify(const T& value,
|
||||||
notify(const T& value, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const {
|
uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
if constexpr (Has_data_size<T>::value) {
|
if constexpr (Has_data_size<T>::value) {
|
||||||
notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), conn_handle);
|
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
||||||
} else if constexpr (Has_c_str_length<T>::value) {
|
} else if constexpr (Has_c_str_length<T>::value) {
|
||||||
notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), conn_handle);
|
return notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
|
||||||
} else {
|
} else {
|
||||||
notify(reinterpret_cast<const uint8_t*>(&value), sizeof(value), conn_handle);
|
return notify(reinterpret_cast<const uint8_t*>(&value), sizeof(value), connHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,18 +102,18 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
||||||
* pointer and getting the length of the array using sizeof.
|
* pointer and getting the length of the array using sizeof.
|
||||||
* @tparam T The a reference to a class containing the data to send.
|
* @tparam T The a reference to a class containing the data to send.
|
||||||
* @param[in] value The <type\>value to set.
|
* @param[in] value The <type\>value to set.
|
||||||
* @param[in] conn_handle The connection handle to send the indication to.
|
* @param[in] connHandle The connection handle to send the indication to.
|
||||||
* @note This function is only available if the type T is not a pointer.
|
* @note This function is only available if the type T is not a pointer.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!std::is_pointer<T>::value, void>::type
|
typename std::enable_if<!std::is_pointer<T>::value, bool>::type indicate(
|
||||||
indicate(const T& value, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const {
|
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
if constexpr (Has_data_size<T>::value) {
|
if constexpr (Has_data_size<T>::value) {
|
||||||
indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), conn_handle);
|
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
||||||
} else if constexpr (Has_c_str_length<T>::value) {
|
} else if constexpr (Has_c_str_length<T>::value) {
|
||||||
indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), conn_handle);
|
return indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), connHandle);
|
||||||
} else {
|
} else {
|
||||||
indicate(reinterpret_cast<const uint8_t*>(&value), sizeof(value), conn_handle);
|
return indicate(reinterpret_cast<const uint8_t*>(&value), sizeof(value), connHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,18 +122,16 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
||||||
friend class NimBLEService;
|
friend class NimBLEService;
|
||||||
|
|
||||||
void setService(NimBLEService* pService);
|
void setService(NimBLEService* pService);
|
||||||
void setSubscribe(const ble_gap_event* event, NimBLEConnInfo& connInfo);
|
|
||||||
void readEvent(NimBLEConnInfo& connInfo) override;
|
void readEvent(NimBLEConnInfo& connInfo) override;
|
||||||
void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) override;
|
void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) override;
|
||||||
void sendValue(const uint8_t* value,
|
bool sendValue(const uint8_t* value,
|
||||||
size_t length,
|
size_t length,
|
||||||
bool is_notification = true,
|
bool is_notification = true,
|
||||||
uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const;
|
||||||
|
|
||||||
NimBLECharacteristicCallbacks* m_pCallbacks{nullptr};
|
NimBLECharacteristicCallbacks* m_pCallbacks{nullptr};
|
||||||
NimBLEService* m_pService{nullptr};
|
NimBLEService* m_pService{nullptr};
|
||||||
std::vector<NimBLEDescriptor*> m_vDescriptors{};
|
std::vector<NimBLEDescriptor*> m_vDescriptors{};
|
||||||
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec{};
|
|
||||||
}; // NimBLECharacteristic
|
}; // NimBLECharacteristic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,11 +34,11 @@ class NimBLEDescriptorCallbacks;
|
||||||
*/
|
*/
|
||||||
class NimBLEDescriptor : public NimBLELocalValueAttribute {
|
class NimBLEDescriptor : public NimBLELocalValueAttribute {
|
||||||
public:
|
public:
|
||||||
NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, NimBLECharacteristic* pCharacteristic = nullptr);
|
NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t maxLen, NimBLECharacteristic* pCharacteristic = nullptr);
|
||||||
|
|
||||||
NimBLEDescriptor(const NimBLEUUID& uuid,
|
NimBLEDescriptor(const NimBLEUUID& uuid,
|
||||||
uint16_t properties,
|
uint16_t properties,
|
||||||
uint16_t max_len,
|
uint16_t maxLen,
|
||||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||||
~NimBLEDescriptor() = default;
|
~NimBLEDescriptor() = default;
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,8 @@ NimBLEServer::NimBLEServer()
|
||||||
m_advertiseOnDisconnect{false},
|
m_advertiseOnDisconnect{false},
|
||||||
# endif
|
# endif
|
||||||
m_pServerCallbacks{&defaultCallbacks},
|
m_pServerCallbacks{&defaultCallbacks},
|
||||||
m_svcVec{},
|
m_svcVec{} {
|
||||||
m_notifyChrVec{} {
|
|
||||||
m_connectedPeers.fill(BLE_HS_CONN_HANDLE_NONE);
|
m_connectedPeers.fill(BLE_HS_CONN_HANDLE_NONE);
|
||||||
m_indWait.fill(BLE_HS_CONN_HANDLE_NONE);
|
|
||||||
} // NimBLEServer
|
} // NimBLEServer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,13 +197,8 @@ void NimBLEServer::start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& chr : svc->m_vChars) {
|
// Set the descriptor handles now as the stack does not set these when the service is started
|
||||||
// if Notify / Indicate is enabled but we didn't create the descriptor
|
for (const auto& chr : svc->m_vChars) {
|
||||||
// we do it now.
|
|
||||||
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
@ -519,22 +512,25 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
event->subscribe.attr_handle,
|
event->subscribe.attr_handle,
|
||||||
(event->subscribe.cur_notify ? "true" : "false"));
|
(event->subscribe.cur_notify ? "true" : "false"));
|
||||||
|
|
||||||
for (const auto& chr : pServer->m_notifyChrVec) {
|
for (const auto& svc : pServer->m_svcVec) {
|
||||||
if (chr->getHandle() == event->subscribe.attr_handle) {
|
for (const auto& chr : svc->m_vChars) {
|
||||||
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
|
if (chr->getHandle() == event->subscribe.attr_handle) {
|
||||||
if (rc != 0) {
|
rc = ble_gap_conn_find(event->subscribe.conn_handle, &peerInfo.m_desc);
|
||||||
break;
|
if (rc != 0) {
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto chrProps = chr->getProperties();
|
auto chrProps = chr->getProperties();
|
||||||
if (!peerInfo.isEncrypted() &&
|
if (!peerInfo.isEncrypted() &&
|
||||||
(chrProps & BLE_GATT_CHR_F_READ_AUTHEN || chrProps & BLE_GATT_CHR_F_READ_AUTHOR ||
|
(chrProps & BLE_GATT_CHR_F_READ_AUTHEN || chrProps & BLE_GATT_CHR_F_READ_AUTHOR ||
|
||||||
chrProps & BLE_GATT_CHR_F_READ_ENC)) {
|
chrProps & BLE_GATT_CHR_F_READ_ENC)) {
|
||||||
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
chr->setSubscribe(event, peerInfo);
|
chr->m_pCallbacks->onSubscribe(chr,
|
||||||
break;
|
peerInfo,
|
||||||
|
event->subscribe.cur_notify + event->subscribe.cur_indicate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,9 +549,11 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
case BLE_GAP_EVENT_NOTIFY_TX: {
|
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||||
NimBLECharacteristic* pChar = nullptr;
|
NimBLECharacteristic* pChar = nullptr;
|
||||||
|
|
||||||
for (auto& chr : pServer->m_notifyChrVec) {
|
for (const auto& svc : pServer->m_svcVec) {
|
||||||
if (chr->getHandle() == event->notify_tx.attr_handle) {
|
for (auto& chr : svc->m_vChars) {
|
||||||
pChar = chr;
|
if (chr->getHandle() == event->notify_tx.attr_handle) {
|
||||||
|
pChar = chr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +565,6 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
if (event->notify_tx.status == 0) {
|
if (event->notify_tx.status == 0) {
|
||||||
return 0; // Indication sent but not yet acknowledged.
|
return 0; // Indication sent but not yet acknowledged.
|
||||||
}
|
}
|
||||||
pServer->clearIndicateWait(event->notify_tx.conn_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pChar->m_pCallbacks->onStatus(pChar, event->notify_tx.status);
|
pChar->m_pCallbacks->onStatus(pChar, event->notify_tx.status);
|
||||||
|
@ -703,19 +700,21 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||||
NIMBLE_LOGD(LOG_TAG,
|
NIMBLE_LOGD(LOG_TAG,
|
||||||
"Gatt %s event",
|
"Gatt %s event",
|
||||||
(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
|
(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 pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||||
const auto& val = pAtt->getAttVal();
|
auto val = pAtt->getAttVal();
|
||||||
NimBLEConnInfo peerInfo{};
|
NimBLEConnInfo peerInfo{};
|
||||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||||
|
|
||||||
switch (ctxt->op) {
|
switch (ctxt->op) {
|
||||||
case BLE_GATT_ACCESS_OP_READ_DSC:
|
case BLE_GATT_ACCESS_OP_READ_DSC:
|
||||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
// Don't call readEvent if this is an internal read (handle is NONE)
|
||||||
// so we don't want to call the onRead() callback again.
|
if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||||
if (ctxt->om->om_pkthdr_len > 8 || connHandle == BLE_HS_CONN_HANDLE_NONE ||
|
// If the packet header is only 8 bytes then this is a follow up of a long read
|
||||||
val.size() <= (ble_att_mtu(connHandle) - 3)) {
|
// so we don't want to call the onRead() callback again.
|
||||||
pAtt->readEvent(peerInfo);
|
if (ctxt->om->om_pkthdr_len > 8 || pAtt->getAttVal().size() <= (ble_att_mtu(connHandle) - 3)) {
|
||||||
|
pAtt->readEvent(peerInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_npl_hw_enter_critical();
|
ble_npl_hw_enter_critical();
|
||||||
|
@ -726,19 +725,19 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||||
|
|
||||||
case BLE_GATT_ACCESS_OP_WRITE_DSC:
|
case BLE_GATT_ACCESS_OP_WRITE_DSC:
|
||||||
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
|
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
|
||||||
uint16_t att_max_len = val.max_size();
|
uint16_t maxLen = val.max_size();
|
||||||
if (ctxt->om->om_len > att_max_len) {
|
if (ctxt->om->om_len > maxLen) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[att_max_len];
|
uint8_t buf[maxLen];
|
||||||
uint16_t len = ctxt->om->om_len;
|
uint16_t len = ctxt->om->om_len;
|
||||||
memcpy(buf, ctxt->om->om_data, len);
|
memcpy(buf, ctxt->om->om_data, len);
|
||||||
|
|
||||||
os_mbuf* next;
|
os_mbuf* next;
|
||||||
next = SLIST_NEXT(ctxt->om, om_next);
|
next = SLIST_NEXT(ctxt->om, om_next);
|
||||||
while (next != NULL) {
|
while (next != NULL) {
|
||||||
if ((len + next->om_len) > att_max_len) {
|
if ((len + next->om_len) > maxLen) {
|
||||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
}
|
}
|
||||||
memcpy(&buf[len], next->om_data, next->om_len);
|
memcpy(&buf[len], next->om_data, next->om_len);
|
||||||
|
@ -760,8 +759,8 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||||
/**
|
/**
|
||||||
* @brief Set the server callbacks.
|
* @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
|
||||||
* disconnecting. This function can be called to register a callback handler that will be invoked when these
|
* client disconnecting. This function can be called to register a callback handler that will be invoked when these
|
||||||
* events are detected.
|
* events are detected.
|
||||||
*
|
*
|
||||||
* @param [in] pCallbacks The callbacks to be invoked.
|
* @param [in] pCallbacks The callbacks to be invoked.
|
||||||
|
@ -1026,25 +1025,6 @@ void NimBLEServer::setDataLen(uint16_t connHandle, uint16_t octets) const {
|
||||||
# endif
|
# endif
|
||||||
} // setDataLen
|
} // setDataLen
|
||||||
|
|
||||||
bool NimBLEServer::setIndicateWait(uint16_t connHandle) {
|
|
||||||
for (auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
|
||||||
if (m_indWait[i] == connHandle) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NimBLEServer::clearIndicateWait(uint16_t connHandle) {
|
|
||||||
for (auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
|
||||||
if (m_indWait[i] == connHandle) {
|
|
||||||
m_indWait[i] = BLE_HS_CONN_HANDLE_NONE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Default callback handlers */
|
/** Default callback handlers */
|
||||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo) {
|
||||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||||
|
|
|
@ -113,9 +113,7 @@ class NimBLEServer {
|
||||||
# endif
|
# endif
|
||||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||||
std::vector<NimBLEService*> m_svcVec;
|
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_connectedPeers;
|
||||||
std::array<uint16_t, CONFIG_BT_NIMBLE_MAX_CONNECTIONS> m_indWait;
|
|
||||||
|
|
||||||
static int handleGapEvent(struct ble_gap_event* event, void* arg);
|
static int handleGapEvent(struct ble_gap_event* event, void* arg);
|
||||||
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
|
static int handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_gatt_access_ctxt* ctxt, void* arg);
|
||||||
|
@ -123,8 +121,6 @@ class NimBLEServer {
|
||||||
std::string getPeerNameImpl(uint16_t connHandle, int cb_type = -1) const;
|
std::string getPeerNameImpl(uint16_t connHandle, int cb_type = -1) const;
|
||||||
void serviceChanged();
|
void serviceChanged();
|
||||||
void resetGATT();
|
void resetGATT();
|
||||||
bool setIndicateWait(uint16_t connHandle);
|
|
||||||
void clearIndicateWait(uint16_t connHandle);
|
|
||||||
|
|
||||||
}; // NimBLEServer
|
}; // NimBLEServer
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue