mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-22 13:10:55 +01:00
Server: Add onSubscribe() callback for characteristics. (#21)
Server: Add onSubscribe() callback for characteristics. Adds a new method to NimBLECharacteristicCallbacks that gets called when a client changes it's subscription status. * Remove NimBLE2902 class. As the NimBLE2902 class usefulness was only related to callback functions that were replaced by the NimBLECharacteristicCallbacks:onSubscribe() method this removes the NimBLE2902 class and moves all subscription handling to NimBLECharacteristic. * Update documents and examples to reflect this change. * Add getSubscribedCount() to get the number of subscribed clients.
This commit is contained in:
parent
fe4586a3ca
commit
4723b1cc53
9 changed files with 93 additions and 236 deletions
|
@ -5,7 +5,6 @@ cmake_minimum_required(VERSION 3.5)
|
||||||
set(SUPPORTED_TARGETS esp32)
|
set(SUPPORTED_TARGETS esp32)
|
||||||
|
|
||||||
idf_component_register(SRCS "src/FreeRTOS.cpp"
|
idf_component_register(SRCS "src/FreeRTOS.cpp"
|
||||||
"src/NimBLE2902.cpp"
|
|
||||||
"src/NimBLE2904.cpp"
|
"src/NimBLE2904.cpp"
|
||||||
"src/NimBLEAddress.cpp"
|
"src/NimBLEAddress.cpp"
|
||||||
"src/NimBLEAdvertisedDevice.cpp"
|
"src/NimBLEAdvertisedDevice.cpp"
|
||||||
|
|
|
@ -33,15 +33,18 @@ When creating a characteristic the properties are now set with `NIMBLE_PROPERTY:
|
||||||
### Descriptors
|
### Descriptors
|
||||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor()` method.
|
Descriptors are now created using the `NimBLECharacteristic::createDescriptor()` method.
|
||||||
|
|
||||||
The previous method `BLECharacteristic::addDescriptor()` is now a private function in the library.
|
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||||
|
|
||||||
This was done because the NimBLE host automatically creates a 0x2902 descriptor if a characteristic has NOTIFY or INDICATE properties applied.
|
0x2902 Descriptor class: formerly known as BLE2902 or NimBLE2902 has been removed.
|
||||||
Due to this fact, the library also creates one automatically for your application.
|
It was no longer useful as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
|
||||||
The only reason to manually create this descriptor now is to assign callback functions.
|
to handle callback functionality and the client subscription status is handled internally.
|
||||||
If you do not require this functionality you can safely exclude the manual creation of the 0x2902 descriptor.
|
|
||||||
|
|
||||||
For any other descriptor, (except 0x2904, see below) it should now be created just as characteristics are
|
NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
|
||||||
by using the `NimBLECharacteristic::createDescriptor` method.
|
|
||||||
|
**Note** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
|
||||||
|
allowing the creation of it would cause a fault in the NimBLE stack.
|
||||||
|
|
||||||
|
All other desctiptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` methods (except 0x2904, see below).
|
||||||
Which are defined as:
|
Which are defined as:
|
||||||
```
|
```
|
||||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||||
|
@ -67,15 +70,14 @@ pDescriptor = pCharacteristic->createDescriptor("ABCD",
|
||||||
Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
|
Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
For the 0x2904 and 0x2902 descriptor, there is a special class that is created when you call `createDescriptor("2904")`or `createDescriptor("2902")`.
|
For the 0x2904, there is a special class that is created when you call `createDescriptor("2904").
|
||||||
|
|
||||||
The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` or `NimBLE2902` so you must cast the returned pointer to
|
The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to
|
||||||
`NimBLE2904` or `NimBLE2902` to access the specific class methods.
|
`NimBLE2904` to access the specific class methods.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
```
|
```
|
||||||
p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904");
|
p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904");
|
||||||
p2902 = (NimBLE2902*)pCharacteristic->createDescriptor("2902");
|
|
||||||
```
|
```
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
@ -91,7 +93,6 @@ Security is set on the characteristic or descriptor properties by applying one o
|
||||||
When a peer wants to read or write a characteristic or descriptor with any of these properties applied
|
When a peer wants to read or write a characteristic or descriptor with any of these properties applied
|
||||||
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
||||||
This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details.
|
This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# Client API Differences
|
# Client API Differences
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
/*
|
|
||||||
* NimBLE2902.cpp
|
|
||||||
*
|
|
||||||
* Created: on March 10, 2020
|
|
||||||
* Author H2zero
|
|
||||||
*
|
|
||||||
* Originally:
|
|
||||||
*
|
|
||||||
* BLE2902.cpp
|
|
||||||
*
|
|
||||||
* Created on: Jun 25, 2017
|
|
||||||
* Author: kolban
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
|
||||||
*/
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
|
||||||
|
|
||||||
#include "nimconfig.h"
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
|
||||||
|
|
||||||
#include "NimBLE2902.h"
|
|
||||||
|
|
||||||
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
|
|
||||||
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902),
|
|
||||||
BLE_GATT_CHR_F_READ |
|
|
||||||
BLE_GATT_CHR_F_WRITE,
|
|
||||||
2, pCharacterisitic)
|
|
||||||
{
|
|
||||||
uint8_t data[2] = { 0, 0 };
|
|
||||||
setValue(data, 2);
|
|
||||||
} // NimBLE2902
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the notifications value.
|
|
||||||
* @return The notifications value. True if notifications are enabled and false if not.
|
|
||||||
*/
|
|
||||||
bool NimBLE2902::getNotifications() {
|
|
||||||
return (getValue()[0] & (1 << 0)) != 0;
|
|
||||||
} // getNotifications
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the indications value.
|
|
||||||
* @return The indications value. True if indications are enabled and false if not.
|
|
||||||
*/
|
|
||||||
bool NimBLE2902::getIndications() {
|
|
||||||
return (getValue()[0] & (1 << 1)) != 0;
|
|
||||||
} // getIndications
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the indications flag.
|
|
||||||
* @param [in] flag The indications flag.
|
|
||||||
*/
|
|
||||||
void NimBLE2902::setIndications(bool flag) {
|
|
||||||
uint8_t *pValue = getValue();
|
|
||||||
if (flag) pValue[0] |= 1 << 1;
|
|
||||||
else pValue[0] &= ~(1 << 1);
|
|
||||||
} // setIndications
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the notifications flag.
|
|
||||||
* @param [in] flag The notifications flag.
|
|
||||||
*/
|
|
||||||
void NimBLE2902::setNotifications(bool flag) {
|
|
||||||
uint8_t *pValue = getValue();
|
|
||||||
if (flag) pValue[0] |= 1 << 0;
|
|
||||||
else pValue[0] &= ~(1 << 0);
|
|
||||||
} // setNotifications
|
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
|
||||||
#endif
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* NimBLE2902.h
|
|
||||||
*
|
|
||||||
* Created: on March 10, 2020
|
|
||||||
* Author H2zero
|
|
||||||
*
|
|
||||||
* Originally:
|
|
||||||
*
|
|
||||||
* BLE2902.h
|
|
||||||
*
|
|
||||||
* Created on: Jun 25, 2017
|
|
||||||
* Author: kolban
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MAIN_NIMBLE2902_H_
|
|
||||||
#define MAIN_NIMBLE2902_H_
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
|
||||||
|
|
||||||
#include "nimconfig.h"
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
|
||||||
|
|
||||||
#include "NimBLEDescriptor.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#define NIMBLE_DESC_FLAG_NOTIFY 0x0001
|
|
||||||
#define NIMBLE_DESC_FLAG_INDICATE 0x0002
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t conn_id;
|
|
||||||
uint16_t sub_val;
|
|
||||||
} chr_sub_status_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Descriptor for Client Characteristic Configuration.
|
|
||||||
*
|
|
||||||
* This is a convenience descriptor for the Client Characteristic Configuration which has a UUID of 0x2902.
|
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
|
||||||
*/
|
|
||||||
class NimBLE2902: public NimBLEDescriptor {
|
|
||||||
public:
|
|
||||||
bool getNotifications();
|
|
||||||
bool getIndications();
|
|
||||||
void setNotifications(bool flag);
|
|
||||||
void setIndications(bool flag);
|
|
||||||
private:
|
|
||||||
NimBLE2902(NimBLECharacteristic* pCharacterisitic);
|
|
||||||
friend class NimBLECharacteristic;
|
|
||||||
std::vector<chr_sub_status_t> m_subscribedVec;
|
|
||||||
|
|
||||||
}; // NimBLE2902
|
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
|
||||||
#endif /* MAIN_NIMBLE2902_H_ */
|
|
|
@ -16,16 +16,18 @@
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLECharacteristic.h"
|
#include "NimBLECharacteristic.h"
|
||||||
#include "NimBLE2902.h"
|
|
||||||
#include "NimBLE2904.h"
|
#include "NimBLE2904.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
#define NULL_HANDLE (0xffff)
|
#define NULL_HANDLE (0xffff)
|
||||||
|
#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";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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.
|
||||||
|
@ -86,20 +88,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
|
||||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
||||||
NimBLEDescriptor* pDescriptor = nullptr;
|
NimBLEDescriptor* pDescriptor = nullptr;
|
||||||
if(uuid == NimBLEUUID(uint16_t(0x2902))) {
|
if(uuid == NimBLEUUID(uint16_t(0x2902))) {
|
||||||
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
|
assert(0 && "0x2902 descriptors cannot be manually created");
|
||||||
assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set");
|
|
||||||
}
|
|
||||||
// We cannot have more than one 2902 descriptor, if it's already been created just return a pointer to it.
|
|
||||||
pDescriptor = getDescriptorByUUID(uuid);
|
|
||||||
if(pDescriptor == nullptr) {
|
|
||||||
pDescriptor = new NimBLE2902(this);
|
|
||||||
} else {
|
|
||||||
return pDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
} else 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, max_len, this);
|
||||||
}
|
}
|
||||||
|
@ -269,21 +260,35 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of clients subscribed to the characteristic.
|
||||||
|
* @returns Number of clients subscribed to notifications / indications.
|
||||||
|
*/
|
||||||
|
size_t NimBLECharacteristic::getSubscribedCount() {
|
||||||
|
return m_subscribedVec.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the subscribe status for this characteristic.\n
|
* @brief Set the subscribe status for this characteristic.\n
|
||||||
* This will maintain a vector of subscribed clients and their indicate/notify status.
|
* This will maintain a vector of subscribed clients and their indicate/notify status.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||||
uint16_t subVal = 0;
|
ble_gap_conn_desc desc;
|
||||||
if(event->subscribe.cur_notify) {
|
if(ble_gap_conn_find(event->subscribe.conn_handle, &desc) != 0) {
|
||||||
subVal |= NIMBLE_DESC_FLAG_NOTIFY;
|
return;
|
||||||
}
|
}
|
||||||
if(event->subscribe.cur_indicate) {
|
|
||||||
subVal |= NIMBLE_DESC_FLAG_INDICATE;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_pTaskData != nullptr) {
|
if(m_pTaskData != nullptr) {
|
||||||
m_pTaskData->rc = (subVal & NIMBLE_DESC_FLAG_INDICATE) ? 0 :
|
m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 :
|
||||||
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
||||||
xTaskNotifyGive(m_pTaskData->task);
|
xTaskNotifyGive(m_pTaskData->task);
|
||||||
}
|
}
|
||||||
|
@ -291,40 +296,28 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||||
event->subscribe.conn_handle, subVal);
|
event->subscribe.conn_handle, subVal);
|
||||||
|
|
||||||
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID(uint16_t(0x2902));
|
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||||
if(p2902 == nullptr){
|
|
||||||
ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s",
|
|
||||||
std::string(getUUID()).c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY);
|
auto it = m_subscribedVec.begin();
|
||||||
p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE);
|
for(;it != m_subscribedVec.end(); ++it) {
|
||||||
p2902->m_pCallbacks->onWrite(p2902);
|
if((*it).first == event->subscribe.conn_handle) {
|
||||||
|
|
||||||
|
|
||||||
auto it = p2902->m_subscribedVec.begin();
|
|
||||||
for(;it != p2902->m_subscribedVec.end(); ++it) {
|
|
||||||
if((*it).conn_id == event->subscribe.conn_handle) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(subVal > 0) {
|
if(subVal > 0) {
|
||||||
if(it == p2902->m_subscribedVec.end()) {
|
if(it == m_subscribedVec.end()) {
|
||||||
chr_sub_status_t client_sub;
|
m_subscribedVec.push_back({event->subscribe.conn_handle, subVal});
|
||||||
client_sub.conn_id = event->subscribe.conn_handle;
|
|
||||||
client_sub.sub_val = subVal;
|
|
||||||
p2902->m_subscribedVec.push_back(client_sub);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*it).sub_val = subVal;
|
(*it).second = subVal;
|
||||||
|
|
||||||
} else if(it != p2902->m_subscribedVec.end()) {
|
} else if(it != m_subscribedVec.end()) {
|
||||||
p2902->m_subscribedVec.erase(it);
|
m_subscribedVec.erase(it);
|
||||||
p2902->m_subscribedVec.shrink_to_fit();
|
m_subscribedVec.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -348,15 +341,16 @@ void NimBLECharacteristic::indicate() {
|
||||||
void NimBLECharacteristic::notify(bool is_notification) {
|
void NimBLECharacteristic::notify(bool is_notification) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", getDataLength());
|
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", getDataLength());
|
||||||
|
|
||||||
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID(uint16_t(0x2902));
|
|
||||||
|
|
||||||
if(p2902 == nullptr) {
|
if(!(m_properties & NIMBLE_PROPERTY::NOTIFY) &&
|
||||||
|
!(m_properties & NIMBLE_PROPERTY::INDICATE))
|
||||||
|
{
|
||||||
NIMBLE_LOGE(LOG_TAG,
|
NIMBLE_LOGE(LOG_TAG,
|
||||||
"<< notify-Error; Notify/indicate not enabled for characterisitc: %s",
|
"<< notify-Error; Notify/indicate not enabled for characterisitc: %s",
|
||||||
std::string(getUUID()).c_str());
|
std::string(getUUID()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p2902->m_subscribedVec.size() == 0) {
|
if (m_subscribedVec.size() == 0) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< notify: No clients subscribed.");
|
NIMBLE_LOGD(LOG_TAG, "<< notify: No clients subscribed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -370,18 +364,18 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||||
(m_properties & BLE_GATT_CHR_F_READ_ENC);
|
(m_properties & BLE_GATT_CHR_F_READ_ENC);
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
for (auto &it : p2902->m_subscribedVec) {
|
for (auto &it : m_subscribedVec) {
|
||||||
uint16_t _mtu = getService()->getServer()->getPeerMTU(it.conn_id);
|
uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first);
|
||||||
|
|
||||||
// check if connected and subscribed
|
// check if connected and subscribed
|
||||||
if(_mtu == 0 || it.sub_val == 0) {
|
if(_mtu == 0 || it.second == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if security requirements are satisfied
|
// check if security requirements are satisfied
|
||||||
if(reqSec) {
|
if(reqSec) {
|
||||||
struct ble_gap_conn_desc desc;
|
struct ble_gap_conn_desc desc;
|
||||||
rc = ble_gap_conn_find(it.conn_id, &desc);
|
rc = ble_gap_conn_find(it.first, &desc);
|
||||||
if(rc != 0 || !desc.sec_state.encrypted) {
|
if(rc != 0 || !desc.sec_state.encrypted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -391,13 +385,13 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3);
|
NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_notification && (!(it.sub_val & NIMBLE_DESC_FLAG_NOTIFY))) {
|
if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) {
|
||||||
NIMBLE_LOGW(LOG_TAG,
|
NIMBLE_LOGW(LOG_TAG,
|
||||||
"Sending notification to client subscribed to indications, sending indication instead");
|
"Sending notification to client subscribed to indications, sending indication instead");
|
||||||
is_notification = false;
|
is_notification = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!is_notification && (!(it.sub_val & NIMBLE_DESC_FLAG_INDICATE))) {
|
if(!is_notification && (!(it.second & NIMBLE_SUB_INDICATE))) {
|
||||||
NIMBLE_LOGW(LOG_TAG,
|
NIMBLE_LOGW(LOG_TAG,
|
||||||
"Sending indication to client subscribed to notification, sending notification instead");
|
"Sending indication to client subscribed to notification, sending notification instead");
|
||||||
is_notification = true;
|
is_notification = true;
|
||||||
|
@ -414,7 +408,7 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||||
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||||
m_pTaskData = &taskData;
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
rc = ble_gattc_indicate_custom(it.conn_id, m_handle, om);
|
rc = ble_gattc_indicate_custom(it.first, m_handle, om);
|
||||||
if(rc != 0){
|
if(rc != 0){
|
||||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -433,7 +427,7 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_notify_custom(it.conn_id, m_handle, om);
|
rc = ble_gattc_notify_custom(it.first, m_handle, om);
|
||||||
if(rc == 0) {
|
if(rc == 0) {
|
||||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||||
} else {
|
} else {
|
||||||
|
@ -574,5 +568,24 @@ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacterist
|
||||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
||||||
} // onStatus
|
} // onStatus
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function called when a client changes subscription status.
|
||||||
|
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||||
|
* @param [in] desc The connection description struct that is associated with the client.
|
||||||
|
* @param [in] subValue The subscription status:
|
||||||
|
* * 0 = Un-Subscribed
|
||||||
|
* * 1 = Notifications
|
||||||
|
* * 2 = Indications
|
||||||
|
* * 3 = Notifications and Indications
|
||||||
|
*/
|
||||||
|
void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
|
||||||
|
ble_gap_conn_desc* desc,
|
||||||
|
uint16_t subValue)
|
||||||
|
{
|
||||||
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -110,6 +110,7 @@ public:
|
||||||
|
|
||||||
std::string toString();
|
std::string toString();
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
|
size_t getSubscribedCount();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -145,6 +146,8 @@ private:
|
||||||
ble_task_data_t *m_pTaskData;
|
ble_task_data_t *m_pTaskData;
|
||||||
portMUX_TYPE m_valMux;
|
portMUX_TYPE m_valMux;
|
||||||
time_t m_timestamp;
|
time_t m_timestamp;
|
||||||
|
|
||||||
|
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
|
||||||
}; // NimBLECharacteristic
|
}; // NimBLECharacteristic
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,6 +184,7 @@ public:
|
||||||
virtual void onWrite(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
|
virtual void onWrite(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
|
||||||
virtual void onNotify(NimBLECharacteristic* pCharacteristic);
|
virtual void onNotify(NimBLECharacteristic* pCharacteristic);
|
||||||
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
|
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
|
||||||
|
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
|
@ -106,7 +106,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "NimBLE2904.h"
|
#include "NimBLE2904.h"
|
||||||
#include "NimBLE2902.h"
|
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -182,10 +182,6 @@ void NimBLEServer::start() {
|
||||||
// we do it now.
|
// we do it now.
|
||||||
if((chr->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
if((chr->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||||
(chr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
(chr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
||||||
|
|
||||||
if(nullptr == chr->getDescriptorByUUID(uint16_t(0x2902))) {
|
|
||||||
chr->createDescriptor(uint16_t(0x2902));
|
|
||||||
}
|
|
||||||
m_notifyChrVec.push_back(chr);
|
m_notifyChrVec.push_back(chr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,9 +299,9 @@ size_t NimBLEServer::getConnectedCount() {
|
||||||
} // BLE_GAP_EVENT_DISCONNECT
|
} // BLE_GAP_EVENT_DISCONNECT
|
||||||
|
|
||||||
case BLE_GAP_EVENT_SUBSCRIBE: {
|
case BLE_GAP_EVENT_SUBSCRIBE: {
|
||||||
NIMBLE_LOGI(LOG_TAG, "subscribe event; cur_notify=%d\n value handle; "
|
NIMBLE_LOGI(LOG_TAG, "subscribe event; attr_handle=%d, subscribed: %s",
|
||||||
"val_handle=%d\n",
|
event->subscribe.attr_handle,
|
||||||
event->subscribe.cur_notify, event->subscribe.attr_handle);
|
(event->subscribe.cur_notify ? "true":"false"));
|
||||||
|
|
||||||
for(auto &it : server->m_notifyChrVec) {
|
for(auto &it : server->m_notifyChrVec) {
|
||||||
if(it->getHandle() == event->subscribe.attr_handle) {
|
if(it->getHandle() == event->subscribe.attr_handle) {
|
||||||
|
|
|
@ -147,31 +147,14 @@ bool NimBLEService::start() {
|
||||||
|
|
||||||
for(uint8_t i=0; i < numChrs;) {
|
for(uint8_t i=0; i < numChrs;) {
|
||||||
uint8_t numDscs = pCharacteristic->m_dscVec.size();
|
uint8_t numDscs = pCharacteristic->m_dscVec.size();
|
||||||
if(numDscs) {
|
|
||||||
// skip 2902 as it's automatically created by NimBLE
|
|
||||||
// if Indicate or Notify flags are set
|
|
||||||
if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
|
||||||
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) &&
|
|
||||||
pCharacteristic->getDescriptorByUUID("2902") != nullptr)
|
|
||||||
{
|
|
||||||
numDscs--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!numDscs){
|
if(!numDscs){
|
||||||
pChr_a[i].descriptors = NULL;
|
pChr_a[i].descriptors = NULL;
|
||||||
} else {
|
} else {
|
||||||
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
||||||
//NIMBLE_LOGD(LOG_TAG, "Adding %d descriptors", numDscs);
|
|
||||||
pDsc_a = new ble_gatt_dsc_def[numDscs+1];
|
pDsc_a = new ble_gatt_dsc_def[numDscs+1];
|
||||||
NimBLEDescriptor* pDescriptor = *pCharacteristic->m_dscVec.begin();
|
NimBLEDescriptor* pDescriptor = *pCharacteristic->m_dscVec.begin();
|
||||||
for(uint8_t d=0; d < numDscs;) {
|
for(uint8_t d=0; d < numDscs;) {
|
||||||
// skip 2902
|
|
||||||
if(pDescriptor->m_uuid == NimBLEUUID(uint16_t(0x2902))) {
|
|
||||||
//NIMBLE_LOGD(LOG_TAG, "Skipped 0x2902");
|
|
||||||
pDescriptor = *(pCharacteristic->m_dscVec.begin()+d+1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pDsc_a[d].uuid = &pDescriptor->m_uuid.getNative()->u;
|
pDsc_a[d].uuid = &pDescriptor->m_uuid.getNative()->u;
|
||||||
pDsc_a[d].att_flags = pDescriptor->m_properties;
|
pDsc_a[d].att_flags = pDescriptor->m_properties;
|
||||||
pDsc_a[d].min_key_size = 0;
|
pDsc_a[d].min_key_size = 0;
|
||||||
|
|
Loading…
Reference in a new issue