mirror of https://github.com/arendst/Tasmota.git
update NimBLE-Arduino
This commit is contained in:
parent
9a7f252d88
commit
7064a82fbf
|
@ -100,7 +100,7 @@ The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a poin
|
|||
Defined as:
|
||||
```
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true);
|
||||
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true);
|
||||
```
|
||||
If set to false the client will use the services database it retrieved from the peripheral last time it connected.
|
||||
This allows for faster connections and power saving if the devices just dropped connection and want to reconnect.
|
||||
|
@ -111,6 +111,46 @@ NimBLERemoteCharacteristic::registerForNotify();
|
|||
```
|
||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||
|
||||
```
|
||||
NimBLEClient::getServices()
|
||||
NimBLERemoteService::getCharacteristics()
|
||||
```
|
||||
Now return a pointer to a `std::vector` of the respective object database instead of `std::map`.
|
||||
|
||||
`NimBLERemoteService::getCharacteristicsByHandle()`
|
||||
Has been removed from the API as it is no longer maintained in the library.
|
||||
|
||||
The last two above changes reduce the heap usage significantly with minimal application code adjustments.
|
||||
|
||||
**NEW** on May 23, 2020
|
||||
> ```
|
||||
> NimBLEClient::getServices(bool refresh = false)
|
||||
> NimBLERemoteService::getCharacteristics(bool refresh = false)
|
||||
> NimBLERemoteCharacteristic::getDecriptors(bool refresh = false)
|
||||
>```
|
||||
> These methods now take an optional (bool) parameter.
|
||||
If true it will clear the respective vector and retrieve all the respective attributes from the peripheral.
|
||||
If false it will retrieve the attributes only if the vector is empty, otherwise the vector is returned
|
||||
with the currently stored attributes.
|
||||
|
||||
> Removed the automatic discovery of all peripheral attributes as they consumed time and resources for data
|
||||
the user may not be interested in.
|
||||
|
||||
> Added `NimBLEClient::discoverAtrributes()` for the user to discover all the peripheral attributes
|
||||
to replace the the former functionality.
|
||||
|
||||
|
||||
> ```
|
||||
>getService(NimBLEUUID)
|
||||
>getCharacteristic(NimBLEUUID)
|
||||
>getDescriptor(NimBLEUUID)
|
||||
>```
|
||||
>These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
|
||||
the specified attribute from the peripheral.
|
||||
|
||||
> These changes allow more control for the user to manage the resources used for the attributes.
|
||||
|
||||
|
||||
#### Client Security:
|
||||
The client will automatically initiate security when the peripheral responds that it's required.
|
||||
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
# *** UPDATE ***
|
||||
Server now handles long reads and writes, still work to do on client.
|
||||
**Breaking change:** Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database.
|
||||
|
||||
NEW Client callback created - ```bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params)```
|
||||
Called when the server wants to change the connection parameters, return true to accept them or false if not.
|
||||
Check NimBLE_Client.ino example for a demonstration.
|
||||
This change will affect your application code if you use `NimBLEClient::getServices()` or `NimBLERemoteService::getCharacteristics()`
|
||||
in your application as they now return a pointer to `std::vector` of the respective attributes.
|
||||
|
||||
In addition `NimBLERemoteService::getCharacteristicsByHandle()` has been removed as it is no longer maintained in the library.
|
||||
|
||||
These changes were necessary due to the amount of resources required to use `std::map`, it was not justifed by any benfit it provided.
|
||||
|
||||
It is expected that there will be minimal impact on most applications, if you need help adjusting your code please create an issue.
|
||||
|
||||
# NimBLE-Arduino
|
||||
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
||||
|
@ -59,10 +62,9 @@ Change the settings in the `nimconfig.h` file to customize NimBLE to your projec
|
|||
|
||||
# Continuing development:
|
||||
|
||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@0a1604a.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
Also tracking the NimBLE related changes in esp-idf, master branch, currently [@48bd2d7.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@fead24e.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
Also tracking the NimBLE related changes in esp-idf, master branch, currently [@2bc28bb.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
|
||||
# Acknowledgments:
|
||||
|
||||
|
|
|
@ -61,8 +61,7 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
|||
void onAuthenticationComplete(ble_gap_conn_desc* desc){
|
||||
/** Check that encryption was successful, if not we disconnect the client */
|
||||
if(!desc->sec_state.encrypted) {
|
||||
/** NOTE: createServer returns the current server reference unless one is not already created */
|
||||
NimBLEDevice::createServer()->disconnect(desc->conn_handle);
|
||||
NimBLEDevice::getServer()->disconnect(desc->conn_handle);
|
||||
Serial.println("Encrypt connection failed - disconnecting client");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -89,28 +89,28 @@ uint32_t FreeRTOS::Semaphore::wait(std::string owner) {
|
|||
* @return True if we took the semaphore within timeframe.
|
||||
*/
|
||||
bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
|
||||
NIMBLE_LOGD(LOG_TAG, ">> wait: Semaphore waiting: %s for %s", toString().c_str(), owner.c_str());
|
||||
|
||||
if (m_usePthreads && timeoutMs != portMAX_DELAY) {
|
||||
assert(false); // We apparently don't have a timed wait for pthreads.
|
||||
}
|
||||
if (m_usePthreads && timeoutMs != portMAX_DELAY) {
|
||||
assert(false); // We apparently don't have a timed wait for pthreads.
|
||||
}
|
||||
|
||||
auto ret = pdTRUE;
|
||||
auto ret = pdTRUE;
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
ret = xSemaphoreTake(m_semaphore, timeoutMs);
|
||||
}
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_lock(&m_pthread_mutex);
|
||||
} else {
|
||||
ret = xSemaphoreTake(m_semaphore, timeoutMs);
|
||||
}
|
||||
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
if (m_usePthreads) {
|
||||
pthread_mutex_unlock(&m_pthread_mutex);
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret);
|
||||
return ret;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< wait: Semaphore %s released: %d", toString().c_str(), ret);
|
||||
return ret;
|
||||
} // wait
|
||||
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ public:
|
|||
bool take(std::string owner = "<Unknown>");
|
||||
bool take(uint32_t timeoutMs, std::string owner = "<Unknown>");
|
||||
std::string toString();
|
||||
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
|
||||
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
|
||||
uint32_t wait(std::string owner = "<Unknown>");
|
||||
uint32_t value(){ return m_value; };
|
||||
uint32_t value(){ return m_value; };
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t m_semaphore;
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
|
||||
/* Modifiers */
|
||||
enum MODIFIER_KEY {
|
||||
KEY_CTRL = 1,
|
||||
KEY_SHIFT = 2,
|
||||
KEY_ALT = 4,
|
||||
KEY_CTRL = 1,
|
||||
KEY_SHIFT = 2,
|
||||
KEY_ALT = 4,
|
||||
};
|
||||
|
||||
|
||||
|
@ -43,37 +43,37 @@ enum MEDIA_KEY {
|
|||
};
|
||||
|
||||
enum FUNCTION_KEY {
|
||||
KEY_F1 = 128, /* F1 key */
|
||||
KEY_F2, /* F2 key */
|
||||
KEY_F3, /* F3 key */
|
||||
KEY_F4, /* F4 key */
|
||||
KEY_F5, /* F5 key */
|
||||
KEY_F6, /* F6 key */
|
||||
KEY_F7, /* F7 key */
|
||||
KEY_F8, /* F8 key */
|
||||
KEY_F9, /* F9 key */
|
||||
KEY_F10, /* F10 key */
|
||||
KEY_F11, /* F11 key */
|
||||
KEY_F12, /* F12 key */
|
||||
KEY_F1 = 128, /* F1 key */
|
||||
KEY_F2, /* F2 key */
|
||||
KEY_F3, /* F3 key */
|
||||
KEY_F4, /* F4 key */
|
||||
KEY_F5, /* F5 key */
|
||||
KEY_F6, /* F6 key */
|
||||
KEY_F7, /* F7 key */
|
||||
KEY_F8, /* F8 key */
|
||||
KEY_F9, /* F9 key */
|
||||
KEY_F10, /* F10 key */
|
||||
KEY_F11, /* F11 key */
|
||||
KEY_F12, /* F12 key */
|
||||
|
||||
KEY_PRINT_SCREEN, /* Print Screen key */
|
||||
KEY_SCROLL_LOCK, /* Scroll lock */
|
||||
KEY_CAPS_LOCK, /* caps lock */
|
||||
KEY_NUM_LOCK, /* num lock */
|
||||
KEY_INSERT, /* Insert key */
|
||||
KEY_HOME, /* Home key */
|
||||
KEY_PAGE_UP, /* Page Up key */
|
||||
KEY_PAGE_DOWN, /* Page Down key */
|
||||
KEY_PRINT_SCREEN, /* Print Screen key */
|
||||
KEY_SCROLL_LOCK, /* Scroll lock */
|
||||
KEY_CAPS_LOCK, /* caps lock */
|
||||
KEY_NUM_LOCK, /* num lock */
|
||||
KEY_INSERT, /* Insert key */
|
||||
KEY_HOME, /* Home key */
|
||||
KEY_PAGE_UP, /* Page Up key */
|
||||
KEY_PAGE_DOWN, /* Page Down key */
|
||||
|
||||
RIGHT_ARROW, /* Right arrow */
|
||||
LEFT_ARROW, /* Left arrow */
|
||||
DOWN_ARROW, /* Down arrow */
|
||||
UP_ARROW, /* Up arrow */
|
||||
RIGHT_ARROW, /* Right arrow */
|
||||
LEFT_ARROW, /* Left arrow */
|
||||
DOWN_ARROW, /* Down arrow */
|
||||
UP_ARROW, /* Up arrow */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char usage;
|
||||
unsigned char modifier;
|
||||
unsigned char usage;
|
||||
unsigned char modifier;
|
||||
} KEYMAP;
|
||||
|
||||
#ifdef US_KEYBOARD
|
||||
|
|
|
@ -89,8 +89,8 @@
|
|||
#define MAX_HID_REPORT_SIZE (64)
|
||||
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint8_t data[MAX_HID_REPORT_SIZE];
|
||||
uint32_t length;
|
||||
uint8_t data[MAX_HID_REPORT_SIZE];
|
||||
} HID_REPORT;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,16 +20,19 @@
|
|||
#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,
|
||||
BLE_GATT_CHR_F_READ |
|
||||
BLE_GATT_CHR_F_WRITE,
|
||||
2, pCharacterisitic)
|
||||
{
|
||||
uint8_t data[2] = { 0, 0 };
|
||||
setValue(data, 2);
|
||||
uint8_t data[2] = { 0, 0 };
|
||||
setValue(data, 2);
|
||||
} // NimBLE2902
|
||||
|
||||
|
||||
|
@ -38,7 +41,7 @@ NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
|
|||
* @return The notifications value. True if notifications are enabled and false if not.
|
||||
*/
|
||||
bool NimBLE2902::getNotifications() {
|
||||
return (getValue()[0] & (1 << 0)) != 0;
|
||||
return (getValue()[0] & (1 << 0)) != 0;
|
||||
} // getNotifications
|
||||
|
||||
|
||||
|
@ -47,7 +50,7 @@ bool NimBLE2902::getNotifications() {
|
|||
* @return The indications value. True if indications are enabled and false if not.
|
||||
*/
|
||||
bool NimBLE2902::getIndications() {
|
||||
return (getValue()[0] & (1 << 1)) != 0;
|
||||
return (getValue()[0] & (1 << 1)) != 0;
|
||||
} // getIndications
|
||||
|
||||
|
||||
|
@ -56,9 +59,9 @@ bool NimBLE2902::getIndications() {
|
|||
* @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);
|
||||
uint8_t *pValue = getValue();
|
||||
if (flag) pValue[0] |= 1 << 1;
|
||||
else pValue[0] &= ~(1 << 1);
|
||||
} // setIndications
|
||||
|
||||
|
||||
|
@ -67,9 +70,10 @@ void NimBLE2902::setIndications(bool 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);
|
||||
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
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEDescriptor.h"
|
||||
|
||||
#include <map>
|
||||
|
@ -35,16 +38,17 @@
|
|||
*/
|
||||
class NimBLE2902: public NimBLEDescriptor {
|
||||
public:
|
||||
bool getNotifications();
|
||||
bool getIndications();
|
||||
void setNotifications(bool flag);
|
||||
void setIndications(bool flag);
|
||||
bool getNotifications();
|
||||
bool getIndications();
|
||||
void setNotifications(bool flag);
|
||||
void setIndications(bool flag);
|
||||
private:
|
||||
NimBLE2902(NimBLECharacteristic* pCharacterisitic);
|
||||
NimBLE2902(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
std::map<uint16_t, uint16_t> m_subscribedMap;
|
||||
|
||||
}; // NimBLE2902
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLE2902_H_ */
|
|
@ -19,21 +19,24 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLE2904.h"
|
||||
|
||||
|
||||
NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
|
||||
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904),
|
||||
BLE_GATT_CHR_F_READ,
|
||||
sizeof(BLE2904_Data),
|
||||
pCharacterisitic)
|
||||
BLE_GATT_CHR_F_READ,
|
||||
sizeof(BLE2904_Data),
|
||||
pCharacterisitic)
|
||||
{
|
||||
m_data.m_format = 0;
|
||||
m_data.m_exponent = 0;
|
||||
m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers
|
||||
m_data.m_unit = 0;
|
||||
m_data.m_description = 0;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_format = 0;
|
||||
m_data.m_exponent = 0;
|
||||
m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers
|
||||
m_data.m_unit = 0;
|
||||
m_data.m_description = 0;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
} // BLE2902
|
||||
|
||||
|
||||
|
@ -41,8 +44,8 @@ NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
|
|||
* @brief Set the description.
|
||||
*/
|
||||
void NimBLE2904::setDescription(uint16_t description) {
|
||||
m_data.m_description = description;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_description = description;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,8 +53,8 @@ void NimBLE2904::setDescription(uint16_t description) {
|
|||
* @brief Set the exponent.
|
||||
*/
|
||||
void NimBLE2904::setExponent(int8_t exponent) {
|
||||
m_data.m_exponent = exponent;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_exponent = exponent;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
} // setExponent
|
||||
|
||||
|
||||
|
@ -59,8 +62,8 @@ void NimBLE2904::setExponent(int8_t exponent) {
|
|||
* @brief Set the format.
|
||||
*/
|
||||
void NimBLE2904::setFormat(uint8_t format) {
|
||||
m_data.m_format = format;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_format = format;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
} // setFormat
|
||||
|
||||
|
||||
|
@ -68,8 +71,8 @@ void NimBLE2904::setFormat(uint8_t format) {
|
|||
* @brief Set the namespace.
|
||||
*/
|
||||
void NimBLE2904::setNamespace(uint8_t namespace_value) {
|
||||
m_data.m_namespace = namespace_value;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_namespace = namespace_value;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
} // setNamespace
|
||||
|
||||
|
||||
|
@ -79,8 +82,9 @@ void NimBLE2904::setNamespace(uint8_t namespace_value) {
|
|||
* @param [in] unit The type of units of this characteristic as defined by assigned numbers.
|
||||
*/
|
||||
void NimBLE2904::setUnit(uint16_t unit) {
|
||||
m_data.m_unit = unit;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
m_data.m_unit = unit;
|
||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||
} // setUnit
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif
|
|
@ -17,14 +17,17 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEDescriptor.h"
|
||||
|
||||
struct BLE2904_Data {
|
||||
uint8_t m_format;
|
||||
int8_t m_exponent;
|
||||
uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units
|
||||
uint8_t m_namespace;
|
||||
uint16_t m_description;
|
||||
uint8_t m_format;
|
||||
int8_t m_exponent;
|
||||
uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units
|
||||
uint8_t m_namespace;
|
||||
uint16_t m_description;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -38,45 +41,46 @@ struct BLE2904_Data {
|
|||
*/
|
||||
class NimBLE2904: public NimBLEDescriptor {
|
||||
public:
|
||||
static const uint8_t FORMAT_BOOLEAN = 1;
|
||||
static const uint8_t FORMAT_UINT2 = 2;
|
||||
static const uint8_t FORMAT_UINT4 = 3;
|
||||
static const uint8_t FORMAT_UINT8 = 4;
|
||||
static const uint8_t FORMAT_UINT12 = 5;
|
||||
static const uint8_t FORMAT_UINT16 = 6;
|
||||
static const uint8_t FORMAT_UINT24 = 7;
|
||||
static const uint8_t FORMAT_UINT32 = 8;
|
||||
static const uint8_t FORMAT_UINT48 = 9;
|
||||
static const uint8_t FORMAT_UINT64 = 10;
|
||||
static const uint8_t FORMAT_UINT128 = 11;
|
||||
static const uint8_t FORMAT_SINT8 = 12;
|
||||
static const uint8_t FORMAT_SINT12 = 13;
|
||||
static const uint8_t FORMAT_SINT16 = 14;
|
||||
static const uint8_t FORMAT_SINT24 = 15;
|
||||
static const uint8_t FORMAT_SINT32 = 16;
|
||||
static const uint8_t FORMAT_SINT48 = 17;
|
||||
static const uint8_t FORMAT_SINT64 = 18;
|
||||
static const uint8_t FORMAT_SINT128 = 19;
|
||||
static const uint8_t FORMAT_FLOAT32 = 20;
|
||||
static const uint8_t FORMAT_FLOAT64 = 21;
|
||||
static const uint8_t FORMAT_SFLOAT16 = 22;
|
||||
static const uint8_t FORMAT_SFLOAT32 = 23;
|
||||
static const uint8_t FORMAT_IEEE20601 = 24;
|
||||
static const uint8_t FORMAT_UTF8 = 25;
|
||||
static const uint8_t FORMAT_UTF16 = 26;
|
||||
static const uint8_t FORMAT_OPAQUE = 27;
|
||||
static const uint8_t FORMAT_BOOLEAN = 1;
|
||||
static const uint8_t FORMAT_UINT2 = 2;
|
||||
static const uint8_t FORMAT_UINT4 = 3;
|
||||
static const uint8_t FORMAT_UINT8 = 4;
|
||||
static const uint8_t FORMAT_UINT12 = 5;
|
||||
static const uint8_t FORMAT_UINT16 = 6;
|
||||
static const uint8_t FORMAT_UINT24 = 7;
|
||||
static const uint8_t FORMAT_UINT32 = 8;
|
||||
static const uint8_t FORMAT_UINT48 = 9;
|
||||
static const uint8_t FORMAT_UINT64 = 10;
|
||||
static const uint8_t FORMAT_UINT128 = 11;
|
||||
static const uint8_t FORMAT_SINT8 = 12;
|
||||
static const uint8_t FORMAT_SINT12 = 13;
|
||||
static const uint8_t FORMAT_SINT16 = 14;
|
||||
static const uint8_t FORMAT_SINT24 = 15;
|
||||
static const uint8_t FORMAT_SINT32 = 16;
|
||||
static const uint8_t FORMAT_SINT48 = 17;
|
||||
static const uint8_t FORMAT_SINT64 = 18;
|
||||
static const uint8_t FORMAT_SINT128 = 19;
|
||||
static const uint8_t FORMAT_FLOAT32 = 20;
|
||||
static const uint8_t FORMAT_FLOAT64 = 21;
|
||||
static const uint8_t FORMAT_SFLOAT16 = 22;
|
||||
static const uint8_t FORMAT_SFLOAT32 = 23;
|
||||
static const uint8_t FORMAT_IEEE20601 = 24;
|
||||
static const uint8_t FORMAT_UTF8 = 25;
|
||||
static const uint8_t FORMAT_UTF16 = 26;
|
||||
static const uint8_t FORMAT_OPAQUE = 27;
|
||||
|
||||
void setDescription(uint16_t);
|
||||
void setExponent(int8_t exponent);
|
||||
void setFormat(uint8_t format);
|
||||
void setNamespace(uint8_t namespace_value);
|
||||
void setUnit(uint16_t unit);
|
||||
void setDescription(uint16_t);
|
||||
void setExponent(int8_t exponent);
|
||||
void setFormat(uint8_t format);
|
||||
void setNamespace(uint8_t namespace_value);
|
||||
void setUnit(uint16_t unit);
|
||||
|
||||
private:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic);
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
BLE2904_Data m_data;
|
||||
BLE2904_Data m_data;
|
||||
}; // BLE2904
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLE2904_H_ */
|
|
@ -14,9 +14,13 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAddress";
|
||||
|
||||
/*************************************************
|
||||
NOTE: NimBLE addresses are in INVERSE ORDER!
|
||||
|
@ -43,26 +47,49 @@ NimBLEAddress::NimBLEAddress(ble_addr_t address) {
|
|||
*
|
||||
* @param [in] stringAddress The hex representation of the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(std::string stringAddress) {
|
||||
if (stringAddress.length() != 17) return;
|
||||
NimBLEAddress::NimBLEAddress(const std::string &stringAddress) {
|
||||
if (stringAddress.length() == 0) {
|
||||
memset(m_address, 0, 6);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringAddress.length() == 6) {
|
||||
std::reverse_copy(stringAddress.data(), stringAddress.data() + 6, m_address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stringAddress.length() != 17) {
|
||||
memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address
|
||||
NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
int data[6];
|
||||
sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]);
|
||||
m_address[0] = (uint8_t) data[0];
|
||||
m_address[1] = (uint8_t) data[1];
|
||||
m_address[2] = (uint8_t) data[2];
|
||||
m_address[3] = (uint8_t) data[3];
|
||||
m_address[4] = (uint8_t) data[4];
|
||||
m_address[5] = (uint8_t) data[5];
|
||||
if(sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]) != 6) {
|
||||
memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address
|
||||
NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str());
|
||||
}
|
||||
for(size_t index = 0; index < sizeof m_address; index++) {
|
||||
m_address[index] = data[index];
|
||||
}
|
||||
} // BLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Constructor for compatibility with bluedrioid esp library.
|
||||
* @param [in] esp_bd_addr_t struct containing the address.
|
||||
* @brief Constructor for compatibility with bluedroid esp library.
|
||||
* @param [in] uint8_t[6] or esp_bd_addr_t struct containing the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) {
|
||||
NimBLEUtils::memrcpy(m_address, address, 6);
|
||||
NimBLEAddress::NimBLEAddress(uint8_t address[6]) {
|
||||
std::reverse_copy(address, address + sizeof m_address, m_address);
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Constructor for address using a hex value. Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16"
|
||||
* @param [in] uint64_t containing the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(const uint64_t &address) {
|
||||
memcpy(m_address, &address, sizeof m_address);
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
|
@ -71,8 +98,8 @@ NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) {
|
|||
* @param [in] otherAddress The other address to compare against.
|
||||
* @return True if the addresses are equal.
|
||||
*/
|
||||
bool NimBLEAddress::equals(NimBLEAddress otherAddress) {
|
||||
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
|
||||
bool NimBLEAddress::equals(const NimBLEAddress &otherAddress) const {
|
||||
return *this == otherAddress;
|
||||
} // equals
|
||||
|
||||
|
||||
|
@ -80,7 +107,7 @@ bool NimBLEAddress::equals(NimBLEAddress otherAddress) {
|
|||
* @brief Return the native representation of the address.
|
||||
* @return The native representation of the address.
|
||||
*/
|
||||
uint8_t *NimBLEAddress::getNative() {
|
||||
const uint8_t *NimBLEAddress::getNative() const {
|
||||
return m_address;
|
||||
} // getNative
|
||||
|
||||
|
@ -96,13 +123,23 @@ uint8_t *NimBLEAddress::getNative() {
|
|||
*
|
||||
* @return The string representation of the address.
|
||||
*/
|
||||
std::string NimBLEAddress::toString() {
|
||||
auto size = 18;
|
||||
char *res = (char*)malloc(size);
|
||||
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]);
|
||||
std::string ret(res);
|
||||
free(res);
|
||||
return ret;
|
||||
|
||||
std::string NimBLEAddress::toString() const {
|
||||
return std::string(*this);
|
||||
} // toString
|
||||
|
||||
|
||||
bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
|
||||
return memcmp(rhs.m_address, m_address, sizeof m_address) == 0;
|
||||
}
|
||||
|
||||
bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
}
|
||||
|
||||
NimBLEAddress::operator std::string() const {
|
||||
char buffer[18];
|
||||
sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]);
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,22 +24,7 @@
|
|||
/**************************/
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef enum {
|
||||
BLE_ADDR_TYPE_PUBLIC = 0x00,
|
||||
BLE_ADDR_TYPE_RANDOM = 0x01,
|
||||
BLE_ADDR_TYPE_RPA_PUBLIC = 0x02,
|
||||
BLE_ADDR_TYPE_RPA_RANDOM = 0x03,
|
||||
} esp_nimble_addr_type_t;
|
||||
|
||||
typedef uint8_t esp_ble_addr_type_t ;
|
||||
|
||||
/// Bluetooth address length
|
||||
#define ESP_BD_ADDR_LEN 6
|
||||
|
||||
/// Bluetooth device address
|
||||
typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN];
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/**
|
||||
* @brief A %BLE device address.
|
||||
|
@ -49,11 +34,16 @@ typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN];
|
|||
class NimBLEAddress {
|
||||
public:
|
||||
NimBLEAddress(ble_addr_t address);
|
||||
NimBLEAddress(esp_bd_addr_t address);
|
||||
NimBLEAddress(std::string stringAddress);
|
||||
bool equals(NimBLEAddress otherAddress);
|
||||
uint8_t* getNative();
|
||||
std::string toString();
|
||||
NimBLEAddress(uint8_t address[6]);
|
||||
NimBLEAddress(const std::string &stringAddress);
|
||||
NimBLEAddress(const uint64_t &address);
|
||||
bool equals(const NimBLEAddress &otherAddress) const;
|
||||
const uint8_t* getNative() const;
|
||||
std::string toString() const;
|
||||
|
||||
bool operator ==(const NimBLEAddress & rhs) const;
|
||||
bool operator !=(const NimBLEAddress & rhs) const;
|
||||
operator std::string() const;
|
||||
|
||||
private:
|
||||
uint8_t m_address[6];
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -141,7 +144,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventual
|
|||
* @brief Check advertised serviced for existence required UUID
|
||||
* @return Return true if service is advertised
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(NimBLEUUID uuid){
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Comparing UUIDS: %s %s", m_serviceUUIDs[i].toString().c_str(), uuid.toString().c_str());
|
||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
||||
|
@ -441,6 +444,12 @@ void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
|
|||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
||||
// Don't add duplicates
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
if (m_serviceUUIDs[i].equals(serviceUUID)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
m_haveServiceUUID = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
|
||||
|
@ -542,5 +551,6 @@ void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t le
|
|||
m_payloadLength = length;
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEScan.h"
|
||||
#include "NimBLEUUID.h"
|
||||
|
@ -54,7 +57,7 @@ public:
|
|||
void setAddressType(uint8_t type);
|
||||
|
||||
|
||||
bool isAdvertisingService(NimBLEUUID uuid);
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
|
@ -92,7 +95,7 @@ private:
|
|||
bool m_haveTXPower;
|
||||
|
||||
|
||||
NimBLEAddress m_address = NimBLEAddress("\0\0\0\0\0\0");
|
||||
NimBLEAddress m_address = NimBLEAddress("");
|
||||
uint8_t m_advType;
|
||||
uint16_t m_appearance;
|
||||
int m_deviceType;
|
||||
|
@ -129,5 +132,6 @@ public:
|
|||
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0;
|
||||
};
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "NimBLEAdvertising.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -31,25 +35,25 @@ static const char* LOG_TAG = "NimBLEAdvertising";
|
|||
*/
|
||||
NimBLEAdvertising::NimBLEAdvertising() {
|
||||
memset(&m_advData, 0, sizeof m_advData);
|
||||
memset(&m_scanData, 0, sizeof m_scanData);
|
||||
memset(&m_advParams, 0, sizeof m_advParams);
|
||||
memset(&m_scanData, 0, sizeof m_scanData);
|
||||
memset(&m_advParams, 0, sizeof m_advParams);
|
||||
const char *name = ble_svc_gap_device_name();
|
||||
|
||||
m_advData.name = (uint8_t *)name;
|
||||
m_advData.name = (uint8_t *)name;
|
||||
m_advData.name_len = strlen(name);
|
||||
m_advData.name_is_complete = 1;
|
||||
m_scanData.tx_pwr_lvl_is_present = 1;
|
||||
m_scanData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
||||
m_advData.appearance = 0;
|
||||
m_advData.appearance_is_present = 0;
|
||||
m_advData.mfg_data_len = 0;
|
||||
m_advData.mfg_data = nullptr;
|
||||
m_advData.appearance = 0;
|
||||
m_advData.appearance_is_present = 0;
|
||||
m_advData.mfg_data_len = 0;
|
||||
m_advData.mfg_data = nullptr;
|
||||
|
||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
m_advParams.itvl_min = 0;
|
||||
m_advParams.itvl_max = 0;
|
||||
m_advParams.itvl_min = 0;
|
||||
m_advParams.itvl_max = 0;
|
||||
|
||||
} // NimBLEAdvertising
|
||||
|
||||
|
@ -58,8 +62,8 @@ NimBLEAdvertising::NimBLEAdvertising() {
|
|||
* @brief Add a service uuid to exposed list of services.
|
||||
* @param [in] serviceUUID The UUID of the service to expose.
|
||||
*/
|
||||
void NimBLEAdvertising::addServiceUUID(NimBLEUUID serviceUUID) {
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
|
@ -68,7 +72,7 @@ void NimBLEAdvertising::addServiceUUID(NimBLEUUID serviceUUID) {
|
|||
* @param [in] serviceUUID The string representation of the service to expose.
|
||||
*/
|
||||
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
||||
addServiceUUID(NimBLEUUID(serviceUUID));
|
||||
addServiceUUID(NimBLEUUID(serviceUUID));
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
|
@ -80,34 +84,34 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
m_advData.appearance = appearance;
|
||||
m_advData.appearance_is_present = 1;
|
||||
m_advData.appearance = appearance;
|
||||
m_advData.appearance_is_present = 1;
|
||||
} // setAppearance
|
||||
|
||||
void NimBLEAdvertising::setAdvertisementType(uint8_t adv_type){
|
||||
m_advParams.conn_mode = adv_type;
|
||||
m_advParams.conn_mode = adv_type;
|
||||
} // setAdvertisementType
|
||||
|
||||
void NimBLEAdvertising::setMinInterval(uint16_t mininterval) {
|
||||
m_advParams.itvl_min = mininterval;
|
||||
m_advParams.itvl_min = mininterval;
|
||||
} // setMinInterval
|
||||
|
||||
void NimBLEAdvertising::setMaxInterval(uint16_t maxinterval) {
|
||||
m_advParams.itvl_max = maxinterval;
|
||||
m_advParams.itvl_max = maxinterval;
|
||||
} // setMaxInterval
|
||||
|
||||
// These are dummy functions for now for compatibility
|
||||
void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
|
||||
//m_advData.min_interval = mininterval;
|
||||
//m_advData.min_interval = mininterval;
|
||||
} //
|
||||
|
||||
void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||
//m_advData.max_interval = maxinterval;
|
||||
//m_advData.max_interval = maxinterval;
|
||||
} //
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
void NimBLEAdvertising::setScanResponse(bool set) {
|
||||
m_scanResp = set;
|
||||
m_scanResp = set;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,27 +120,27 @@ void NimBLEAdvertising::setScanResponse(bool set) {
|
|||
* @param [in] connectWhitelistOnly If true, only allow connections from those on the white list.
|
||||
*/
|
||||
void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly);
|
||||
if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setScanFilter: scanRequestWhitelistOnly: %d, connectWhitelistOnly: %d", scanRequestWhitelistOnly, connectWhitelistOnly);
|
||||
if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_NONE;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_SCAN;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_CONN;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
if (scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||
m_advParams.filter_policy = BLE_HCI_ADV_FILT_BOTH;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanFilter");
|
||||
return;
|
||||
}
|
||||
} // setScanFilter
|
||||
|
||||
/**
|
||||
|
@ -145,15 +149,15 @@ void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connec
|
|||
*/
|
||||
|
||||
void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisementData) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData");
|
||||
int rc = ble_gap_adv_set_data(
|
||||
(uint8_t*)advertisementData.getPayload().data(),
|
||||
advertisementData.getPayload().length());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
m_customAdvData = true; // Set the flag that indicates we are using custom advertising data.
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setAdvertisementData");
|
||||
int rc = ble_gap_adv_set_data(
|
||||
(uint8_t*)advertisementData.getPayload().data(),
|
||||
advertisementData.getPayload().length());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
m_customAdvData = true; // Set the flag that indicates we are using custom advertising data.
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setAdvertisementData");
|
||||
} // setAdvertisementData
|
||||
|
||||
|
||||
|
@ -162,15 +166,15 @@ void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisem
|
|||
* @param [in] advertisementData The data to be advertised.
|
||||
*/
|
||||
void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertisementData) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData");
|
||||
int rc = ble_gap_adv_rsp_set_data(
|
||||
(uint8_t*)advertisementData.getPayload().data(),
|
||||
advertisementData.getPayload().length());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_rsp_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
m_customScanResponseData = true; // Set the flag that indicates we are using custom scan response data.
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData");
|
||||
int rc = ble_gap_adv_rsp_set_data(
|
||||
(uint8_t*)advertisementData.getPayload().data(),
|
||||
advertisementData.getPayload().length());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_rsp_set_data: %d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
m_customScanResponseData = true; // Set the flag that indicates we are using custom scan response data.
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setScanResponseData");
|
||||
} // setScanResponseData
|
||||
|
||||
|
||||
|
@ -180,7 +184,7 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEAdvertising::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData);
|
||||
|
||||
// If Host is not synced we cannot start advertising.
|
||||
if(!NimBLEDevice::m_synced) {
|
||||
|
@ -188,35 +192,37 @@ void NimBLEAdvertising::start() {
|
|||
return;
|
||||
}
|
||||
|
||||
if(NimBLEDevice::createServer()->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising");
|
||||
return;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||
if(pServer != nullptr) {
|
||||
if(!pServer->m_gattsStarted){
|
||||
pServer->start();
|
||||
} else if(pServer->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int numServices = m_serviceUUIDs.size();
|
||||
int numServices = m_serviceUUIDs.size();
|
||||
int rc = 0;
|
||||
uint8_t addressType;
|
||||
uint8_t payloadLen = 3; //start with 3 bytes for the flags data
|
||||
uint8_t payloadLen = 3; //start with 3 bytes for the flags data
|
||||
|
||||
// If already advertising just return
|
||||
if(ble_gap_adv_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLEServer* pServer = NimBLEDevice::createServer();
|
||||
if(!pServer->m_gattsStarted){
|
||||
pServer->start();
|
||||
}
|
||||
|
||||
if (!m_customAdvData && !m_advSvcsSet && numServices > 0) {
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) {
|
||||
int add = (m_advData.num_uuids16 > 0) ? 2 : 4;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids16_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
if (!m_customAdvData && !m_advSvcsSet && numServices > 0) {
|
||||
for (int i = 0; i < numServices; i++) {
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) {
|
||||
int add = (m_advData.num_uuids16 > 0) ? 2 : 4;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids16_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
|
||||
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
||||
|
@ -230,14 +236,14 @@ void NimBLEAdvertising::start() {
|
|||
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
|
||||
m_advData.uuids16_is_complete = 1;
|
||||
m_advData.num_uuids16++;
|
||||
}
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) {
|
||||
int add = (m_advData.num_uuids32 > 0) ? 4 : 6;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids32_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
}
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_32) {
|
||||
int add = (m_advData.num_uuids32 > 0) ? 4 : 6;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids32_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32,
|
||||
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
||||
|
@ -251,14 +257,14 @@ void NimBLEAdvertising::start() {
|
|||
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
|
||||
m_advData.uuids32_is_complete = 1;
|
||||
m_advData.num_uuids32++;
|
||||
}
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){
|
||||
int add = (m_advData.num_uuids128 > 0) ? 16 : 18;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids128_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
}
|
||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_128){
|
||||
int add = (m_advData.num_uuids128 > 0) ? 16 : 18;
|
||||
if((payloadLen + add) > 31){
|
||||
m_advData.uuids128_is_complete = 0;
|
||||
continue;
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128,
|
||||
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t)))) {
|
||||
|
@ -271,53 +277,53 @@ void NimBLEAdvertising::start() {
|
|||
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
|
||||
m_advData.uuids128_is_complete = 1;
|
||||
m_advData.num_uuids128++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if there is room for the name, if not put it in scan data
|
||||
if((payloadLen + m_advData.name_len) > 29) {
|
||||
if(m_scanResp){
|
||||
m_scanData.name = m_advData.name;
|
||||
m_scanData.name_len = m_advData.name_len;
|
||||
m_scanData.name_is_complete = m_advData.name_is_complete;
|
||||
m_advData.name = nullptr;
|
||||
m_advData.name_len = 0;
|
||||
} else {
|
||||
// if not using scan response just cut the name down
|
||||
// leaving 2 bytes for the data specifier.
|
||||
m_advData.name_len = (29 - payloadLen);
|
||||
}
|
||||
m_advData.name_is_complete = 0;
|
||||
}
|
||||
// check if there is room for the name, if not put it in scan data
|
||||
if((payloadLen + m_advData.name_len) > 29) {
|
||||
if(m_scanResp){
|
||||
m_scanData.name = m_advData.name;
|
||||
m_scanData.name_len = m_advData.name_len;
|
||||
m_scanData.name_is_complete = m_advData.name_is_complete;
|
||||
m_advData.name = nullptr;
|
||||
m_advData.name_len = 0;
|
||||
} else {
|
||||
// if not using scan response just cut the name down
|
||||
// leaving 2 bytes for the data specifier.
|
||||
m_advData.name_len = (29 - payloadLen);
|
||||
}
|
||||
m_advData.name_is_complete = 0;
|
||||
}
|
||||
|
||||
if(m_advData.name_len > 0) {
|
||||
payloadLen += (m_advData.name_len + 2);
|
||||
}
|
||||
if(m_advData.name_len > 0) {
|
||||
payloadLen += (m_advData.name_len + 2);
|
||||
}
|
||||
|
||||
if(m_scanResp) {
|
||||
// name length + type byte + length byte + tx power type + length + data
|
||||
if((m_scanData.name_len + 5) > 31) {
|
||||
// prioritize name data over tx power
|
||||
m_scanData.tx_pwr_lvl_is_present = 0;
|
||||
m_scanData.tx_pwr_lvl = 0;
|
||||
// limit name to 29 to leave room for the data specifiers
|
||||
if(m_scanData.name_len > 29) {
|
||||
m_scanData.name_len = 29;
|
||||
m_scanData.name_is_complete = false;
|
||||
}
|
||||
}
|
||||
if(m_scanResp) {
|
||||
// name length + type byte + length byte + tx power type + length + data
|
||||
if((m_scanData.name_len + 5) > 31) {
|
||||
// prioritize name data over tx power
|
||||
m_scanData.tx_pwr_lvl_is_present = 0;
|
||||
m_scanData.tx_pwr_lvl = 0;
|
||||
// limit name to 29 to leave room for the data specifiers
|
||||
if(m_scanData.name_len > 29) {
|
||||
m_scanData.name_len = 29;
|
||||
m_scanData.name_is_complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ble_gap_adv_rsp_set_fields(&m_scanData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
abort();
|
||||
}
|
||||
// if not using scan response and there is room,
|
||||
// throw the tx power data into the advertisment
|
||||
rc = ble_gap_adv_rsp_set_fields(&m_scanData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "error setting scan response data; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
abort();
|
||||
}
|
||||
// if not using scan response and there is room,
|
||||
// throw the tx power data into the advertisment
|
||||
} else if (payloadLen < 29) {
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||
}
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||
}
|
||||
|
||||
rc = ble_gap_adv_set_fields(&m_advData);
|
||||
if (rc != 0) {
|
||||
|
@ -352,14 +358,21 @@ void NimBLEAdvertising::start() {
|
|||
abort();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
|
||||
&m_advParams, NimBLEServer::handleGapEvent, NimBLEDevice::createServer()); //get a reference to the server (does not create a new one)
|
||||
&m_advParams,
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent : NULL,
|
||||
pServer);
|
||||
#else
|
||||
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
|
||||
&m_advParams, NULL,NULL);
|
||||
#endif
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
abort();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
||||
} // start
|
||||
|
||||
|
||||
|
@ -369,14 +382,14 @@ void NimBLEAdvertising::start() {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEAdvertising::stop() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||
int rc = ble_gap_adv_stop();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||
int rc = ble_gap_adv_stop();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
||||
} // stop
|
||||
|
||||
|
||||
|
@ -393,11 +406,11 @@ void NimBLEAdvertising::onHostReset() {
|
|||
* @brief Add data to the payload to be advertised.
|
||||
* @param [in] data The data to be added to the payload.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(std::string data) {
|
||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||
return;
|
||||
}
|
||||
m_payload.append(data);
|
||||
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||
return;
|
||||
}
|
||||
m_payload.append(data);
|
||||
} // addData
|
||||
|
||||
|
||||
|
@ -409,10 +422,10 @@ void NimBLEAdvertisementData::addData(std::string data) {
|
|||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
|
||||
*/
|
||||
void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
||||
char cdata[2];
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
|
||||
addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
|
||||
char cdata[2];
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
|
||||
addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
|
||||
} // setAppearance
|
||||
|
||||
|
||||
|
@ -420,36 +433,36 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
|||
* @brief Set the complete services.
|
||||
* @param [in] uuid The single service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices(NimBLEUUID uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07
|
||||
addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07
|
||||
addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
|
@ -470,11 +483,11 @@ void NimBLEAdvertisementData::setCompleteServices(NimBLEUUID uuid) {
|
|||
* * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE
|
||||
*/
|
||||
void NimBLEAdvertisementData::setFlags(uint8_t flag) {
|
||||
char cdata[3];
|
||||
cdata[0] = 2;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
|
||||
cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||
addData(std::string(cdata, 3));
|
||||
char cdata[3];
|
||||
cdata[0] = 2;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
|
||||
cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||
addData(std::string(cdata, 3));
|
||||
} // setFlag
|
||||
|
||||
|
||||
|
@ -482,13 +495,13 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) {
|
|||
* @brief Set manufacturer specific data.
|
||||
* @param [in] data Manufacturer data.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setManufacturerData(std::string data) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
||||
char cdata[2];
|
||||
cdata[0] = data.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||
addData(std::string(cdata, 2) + data);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
|
||||
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
||||
char cdata[2];
|
||||
cdata[0] = data.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||
addData(std::string(cdata, 2) + data);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
|
@ -496,13 +509,13 @@ void NimBLEAdvertisementData::setManufacturerData(std::string data) {
|
|||
* @brief Set the name.
|
||||
* @param [in] The complete name of the device.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setName(std::string name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
|
||||
void NimBLEAdvertisementData::setName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
|
||||
} // setName
|
||||
|
||||
|
||||
|
@ -510,36 +523,36 @@ void NimBLEAdvertisementData::setName(std::string name) {
|
|||
* @brief Set the partial services.
|
||||
* @param [in] uuid The single service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices(NimBLEUUID uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setPartialServices
|
||||
|
||||
|
||||
|
@ -548,36 +561,36 @@ void NimBLEAdvertisementData::setPartialServices(NimBLEUUID uuid) {
|
|||
* @param [in] uuid The UUID to set with the service data. Size of UUID will be used.
|
||||
* @param [in] data The data to be associated with the service data advert.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, std::string data) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x16] [UUID16] data
|
||||
cdata[0] = data.length() + 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
|
||||
break;
|
||||
}
|
||||
void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x16] [UUID16] data
|
||||
cdata[0] = data.length() + 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x20] [UUID32] data
|
||||
cdata[0] = data.length() + 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
// [Len] [0x20] [UUID32] data
|
||||
cdata[0] = data.length() + 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x21] [UUID128] data
|
||||
cdata[0] = data.length() + 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
|
||||
break;
|
||||
}
|
||||
case 128: {
|
||||
// [Len] [0x21] [UUID128] data
|
||||
cdata[0] = data.length() + 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setServiceData
|
||||
|
||||
|
||||
|
@ -585,13 +598,13 @@ void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, std::string data)
|
|||
* @brief Set the short name.
|
||||
* @param [in] The short name of the device.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setShortName(std::string name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
|
||||
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
|
||||
} // setShortName
|
||||
|
||||
|
||||
|
@ -600,7 +613,8 @@ void NimBLEAdvertisementData::setShortName(std::string name) {
|
|||
* @return The payload that is to be advertised.
|
||||
*/
|
||||
std::string NimBLEAdvertisementData::getPayload() {
|
||||
return m_payload;
|
||||
return m_payload;
|
||||
} // getPayload
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
#undef min
|
||||
|
@ -42,24 +45,24 @@
|
|||
* @brief Advertisement data set by the programmer to be published by the %BLE server.
|
||||
*/
|
||||
class NimBLEAdvertisementData {
|
||||
// Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will
|
||||
// be exposed on demand/request or as time permits.
|
||||
//
|
||||
// Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will
|
||||
// be exposed on demand/request or as time permits.
|
||||
//
|
||||
public:
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setCompleteServices(NimBLEUUID uuid);
|
||||
void setFlags(uint8_t);
|
||||
void setManufacturerData(std::string data);
|
||||
void setName(std::string name);
|
||||
void setPartialServices(NimBLEUUID uuid);
|
||||
void setServiceData(NimBLEUUID uuid, std::string data);
|
||||
void setShortName(std::string name);
|
||||
void addData(std::string data); // Add data to the payload.
|
||||
std::string getPayload(); // Retrieve the current advert payload.
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setCompleteServices(const NimBLEUUID &uuid);
|
||||
void setFlags(uint8_t);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setName(const std::string &name);
|
||||
void setPartialServices(const NimBLEUUID &uuid);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setShortName(const std::string &name);
|
||||
void addData(const std::string &data); // Add data to the payload.
|
||||
std::string getPayload(); // Retrieve the current advert payload.
|
||||
|
||||
private:
|
||||
friend class NimBLEAdvertising;
|
||||
std::string m_payload; // The payload of the advertisement.
|
||||
friend class NimBLEAdvertising;
|
||||
std::string m_payload; // The payload of the advertisement.
|
||||
}; // NimBLEAdvertisementData
|
||||
|
||||
|
||||
|
@ -70,36 +73,40 @@ private:
|
|||
*/
|
||||
class NimBLEAdvertising {
|
||||
public:
|
||||
NimBLEAdvertising();
|
||||
void addServiceUUID(NimBLEUUID serviceUUID);
|
||||
void addServiceUUID(const char* serviceUUID);
|
||||
void start();
|
||||
void stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
NimBLEAdvertising();
|
||||
void addServiceUUID(const NimBLEUUID &serviceUUID);
|
||||
void addServiceUUID(const char* serviceUUID);
|
||||
void start();
|
||||
void stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setAdvertisementType(uint8_t adv_type);
|
||||
void setMaxInterval(uint16_t maxinterval);
|
||||
void setMinInterval(uint16_t mininterval);
|
||||
void setAdvertisementData(NimBLEAdvertisementData& advertisementData);
|
||||
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
|
||||
void setScanResponseData(NimBLEAdvertisementData& advertisementData);
|
||||
void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM);
|
||||
void setMaxInterval(uint16_t maxinterval);
|
||||
void setMinInterval(uint16_t mininterval);
|
||||
void setAdvertisementData(NimBLEAdvertisementData& advertisementData);
|
||||
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
|
||||
void setScanResponseData(NimBLEAdvertisementData& advertisementData);
|
||||
void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM);
|
||||
|
||||
void setMinPreferred(uint16_t);
|
||||
void setMaxPreferred(uint16_t);
|
||||
void setScanResponse(bool);
|
||||
void setMinPreferred(uint16_t);
|
||||
void setMaxPreferred(uint16_t);
|
||||
void setScanResponse(bool);
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
|
||||
void onHostReset();
|
||||
ble_hs_adv_fields m_advData;
|
||||
ble_hs_adv_fields m_scanData;
|
||||
ble_gap_adv_params m_advParams;
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
bool m_customAdvData = false; // Are we using custom advertising data?
|
||||
bool m_customScanResponseData = false; // Are we using custom scan response data?
|
||||
bool m_scanResp = true;
|
||||
|
||||
ble_hs_adv_fields m_advData;
|
||||
ble_hs_adv_fields m_scanData;
|
||||
ble_gap_adv_params m_advParams;
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
bool m_customAdvData = false; // Are we using custom advertising data?
|
||||
bool m_customScanResponseData = false; // Are we using custom scan response data?
|
||||
bool m_scanResp = true;
|
||||
bool m_advSvcsSet = false;
|
||||
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_BLEADVERTISING_H_ */
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include <string.h>
|
||||
#include "NimBLEBeacon.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -22,71 +23,71 @@
|
|||
static const char* LOG_TAG = "NimBLEBeacon";
|
||||
|
||||
NimBLEBeacon::NimBLEBeacon() {
|
||||
m_beaconData.manufacturerId = 0x4c00;
|
||||
m_beaconData.subType = 0x02;
|
||||
m_beaconData.subTypeLength = 0x15;
|
||||
m_beaconData.major = 0;
|
||||
m_beaconData.minor = 0;
|
||||
m_beaconData.signalPower = 0;
|
||||
memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID));
|
||||
m_beaconData.manufacturerId = 0x4c00;
|
||||
m_beaconData.subType = 0x02;
|
||||
m_beaconData.subTypeLength = 0x15;
|
||||
m_beaconData.major = 0;
|
||||
m_beaconData.minor = 0;
|
||||
m_beaconData.signalPower = 0;
|
||||
memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID));
|
||||
} // NimBLEBeacon
|
||||
|
||||
std::string NimBLEBeacon::getData() {
|
||||
return std::string((char*) &m_beaconData, sizeof(m_beaconData));
|
||||
return std::string((char*) &m_beaconData, sizeof(m_beaconData));
|
||||
} // getData
|
||||
|
||||
uint16_t NimBLEBeacon::getMajor() {
|
||||
return m_beaconData.major;
|
||||
return m_beaconData.major;
|
||||
}
|
||||
|
||||
uint16_t NimBLEBeacon::getManufacturerId() {
|
||||
return m_beaconData.manufacturerId;
|
||||
return m_beaconData.manufacturerId;
|
||||
}
|
||||
|
||||
uint16_t NimBLEBeacon::getMinor() {
|
||||
return m_beaconData.minor;
|
||||
return m_beaconData.minor;
|
||||
}
|
||||
|
||||
NimBLEUUID NimBLEBeacon::getProximityUUID() {
|
||||
return NimBLEUUID(m_beaconData.proximityUUID, 16, false);
|
||||
return NimBLEUUID(m_beaconData.proximityUUID, 16, false);
|
||||
}
|
||||
|
||||
int8_t NimBLEBeacon::getSignalPower() {
|
||||
return m_beaconData.signalPower;
|
||||
return m_beaconData.signalPower;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
*/
|
||||
void NimBLEBeacon::setData(std::string data) {
|
||||
if (data.length() != sizeof(m_beaconData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||
void NimBLEBeacon::setData(const std::string &data) {
|
||||
if (data.length() != sizeof(m_beaconData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||
data.length(), sizeof(m_beaconData));
|
||||
return;
|
||||
}
|
||||
memcpy(&m_beaconData, data.data(), sizeof(m_beaconData));
|
||||
return;
|
||||
}
|
||||
memcpy(&m_beaconData, data.data(), sizeof(m_beaconData));
|
||||
} // setData
|
||||
|
||||
void NimBLEBeacon::setMajor(uint16_t major) {
|
||||
m_beaconData.major = ENDIAN_CHANGE_U16(major);
|
||||
m_beaconData.major = ENDIAN_CHANGE_U16(major);
|
||||
} // setMajor
|
||||
|
||||
void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) {
|
||||
m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId);
|
||||
m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId);
|
||||
} // setManufacturerId
|
||||
|
||||
void NimBLEBeacon::setMinor(uint16_t minor) {
|
||||
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
||||
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
||||
} // setMinior
|
||||
|
||||
void NimBLEBeacon::setProximityUUID(NimBLEUUID uuid) {
|
||||
uuid = uuid.to128();
|
||||
memcpy(m_beaconData.proximityUUID, uuid.getNative()->u128.value, 16);
|
||||
void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) {
|
||||
NimBLEUUID temp_uuid = uuid;
|
||||
temp_uuid.to128();
|
||||
memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16);
|
||||
} // setProximityUUID
|
||||
|
||||
void NimBLEBeacon::setSignalPower(int8_t signalPower) {
|
||||
m_beaconData.signalPower = signalPower;
|
||||
m_beaconData.signalPower = signalPower;
|
||||
} // setSignalPower
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#ifndef MAIN_NIMBLEBEACON_H_
|
||||
#define MAIN_NIMBLEBEACON_H_
|
||||
|
||||
#include "NimBLEUUID.h"
|
||||
/**
|
||||
* @brief Representation of a beacon.
|
||||
|
@ -22,29 +23,29 @@
|
|||
*/
|
||||
class NimBLEBeacon {
|
||||
private:
|
||||
struct {
|
||||
uint16_t manufacturerId;
|
||||
uint8_t subType;
|
||||
uint8_t subTypeLength;
|
||||
uint8_t proximityUUID[16];
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
int8_t signalPower;
|
||||
} __attribute__((packed)) m_beaconData;
|
||||
struct {
|
||||
uint16_t manufacturerId;
|
||||
uint8_t subType;
|
||||
uint8_t subTypeLength;
|
||||
uint8_t proximityUUID[16];
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
int8_t signalPower;
|
||||
} __attribute__((packed)) m_beaconData;
|
||||
public:
|
||||
NimBLEBeacon();
|
||||
std::string getData();
|
||||
uint16_t getMajor();
|
||||
uint16_t getMinor();
|
||||
uint16_t getManufacturerId();
|
||||
NimBLEUUID getProximityUUID();
|
||||
int8_t getSignalPower();
|
||||
void setData(std::string data);
|
||||
void setMajor(uint16_t major);
|
||||
void setMinor(uint16_t minor);
|
||||
void setManufacturerId(uint16_t manufacturerId);
|
||||
void setProximityUUID(NimBLEUUID uuid);
|
||||
void setSignalPower(int8_t signalPower);
|
||||
NimBLEBeacon();
|
||||
std::string getData();
|
||||
uint16_t getMajor();
|
||||
uint16_t getMinor();
|
||||
uint16_t getManufacturerId();
|
||||
NimBLEUUID getProximityUUID();
|
||||
int8_t getSignalPower();
|
||||
void setData(const std::string &data);
|
||||
void setMajor(uint16_t major);
|
||||
void setMinor(uint16_t minor);
|
||||
void setManufacturerId(uint16_t manufacturerId);
|
||||
void setProximityUUID(const NimBLEUUID &uuid);
|
||||
void setSignalPower(int8_t signalPower);
|
||||
}; // NimBLEBeacon
|
||||
|
||||
#endif /* MAIN_NIMBLEBEACON_H_ */
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLE2902.h"
|
||||
#include "NimBLE2904.h"
|
||||
|
@ -41,19 +44,19 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties
|
|||
* @param [in] uuid - UUID for the characteristic.
|
||||
* @param [in] properties - Properties for the characteristic.
|
||||
*/
|
||||
NimBLECharacteristic::NimBLECharacteristic(NimBLEUUID uuid, uint16_t properties, NimBLEService* pService) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_properties = properties;
|
||||
m_pCallbacks = &defaultCallback;
|
||||
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_properties = properties;
|
||||
m_pCallbacks = &defaultCallback;
|
||||
m_pService = pService;
|
||||
// Backward Compatibility - to be removed
|
||||
/* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
|
||||
setReadProperty((properties & PROPERTY_READ) != 0);
|
||||
setWriteProperty((properties & PROPERTY_WRITE) != 0);
|
||||
setNotifyProperty((properties & PROPERTY_NOTIFY) != 0);
|
||||
setIndicateProperty((properties & PROPERTY_INDICATE) != 0);
|
||||
setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0);
|
||||
/* setBroadcastProperty((properties & PROPERTY_BROADCAST) != 0);
|
||||
setReadProperty((properties & PROPERTY_READ) != 0);
|
||||
setWriteProperty((properties & PROPERTY_WRITE) != 0);
|
||||
setNotifyProperty((properties & PROPERTY_NOTIFY) != 0);
|
||||
setIndicateProperty((properties & PROPERTY_INDICATE) != 0);
|
||||
setWriteNoResponseProperty((properties & PROPERTY_WRITE_NR) != 0);
|
||||
*/
|
||||
///////////////////////////////////////////
|
||||
} // NimBLECharacteristic
|
||||
|
@ -71,14 +74,14 @@ NimBLECharacteristic::~NimBLECharacteristic() {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str());
|
||||
// Check that we don't add the same descriptor twice.
|
||||
if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one");
|
||||
//return;
|
||||
}
|
||||
m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addDescriptor(): Adding %s to %s", pDescriptor->toString().c_str(), toString().c_str());
|
||||
// Check that we don't add the same descriptor twice.
|
||||
if (m_descriptorMap.getByUUID(pDescriptor->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a new descriptor with the same UUID as a previous one");
|
||||
//return;
|
||||
}
|
||||
m_descriptorMap.setByUUID(pDescriptor->getUUID(), pDescriptor);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< addDescriptor()");
|
||||
} // addDescriptor
|
||||
|
||||
|
||||
|
@ -89,7 +92,7 @@ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor* pDescriptor) {
|
|||
* @return The new BLE descriptor.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) {
|
||||
return createDescriptor(NimBLEUUID(uuid), properties, max_len);
|
||||
return createDescriptor(NimBLEUUID(uuid), properties, max_len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,9 +102,9 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
|
|||
* @param [in] properties - The properties of the descriptor.
|
||||
* @return The new BLE descriptor.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32_t properties, uint16_t max_len) {
|
||||
NimBLEDescriptor* pDescriptor = nullptr;
|
||||
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
|
||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
||||
NimBLEDescriptor* pDescriptor = nullptr;
|
||||
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
|
||||
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
|
||||
assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set");
|
||||
}
|
||||
|
@ -113,14 +116,14 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32
|
|||
return pDescriptor;
|
||||
}
|
||||
|
||||
} else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) {
|
||||
pDescriptor = new NimBLE2904(this);
|
||||
} else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) {
|
||||
pDescriptor = new NimBLE2904(this);
|
||||
|
||||
} else {
|
||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
addDescriptor(pDescriptor);
|
||||
return pDescriptor;
|
||||
} else {
|
||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
addDescriptor(pDescriptor);
|
||||
return pDescriptor;
|
||||
} // createCharacteristic
|
||||
|
||||
|
||||
|
@ -130,7 +133,7 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32
|
|||
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descriptorUUID) {
|
||||
return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID));
|
||||
return m_descriptorMap.getByUUID(NimBLEUUID(descriptorUUID));
|
||||
} // getDescriptorByUUID
|
||||
|
||||
|
||||
|
@ -139,8 +142,8 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descript
|
|||
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
|
||||
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(NimBLEUUID descriptorUUID) {
|
||||
return m_descriptorMap.getByUUID(descriptorUUID);
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) {
|
||||
return m_descriptorMap.getByUUID(descriptorUUID);
|
||||
} // getDescriptorByUUID
|
||||
|
||||
|
||||
|
@ -149,17 +152,17 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(NimBLEUUID descripto
|
|||
* @return The handle of the characteristic.
|
||||
*/
|
||||
uint16_t NimBLECharacteristic::getHandle() {
|
||||
return m_handle;
|
||||
return m_handle;
|
||||
} // getHandle
|
||||
|
||||
/*
|
||||
void NimBLECharacteristic::setAccessPermissions(uint16_t perm) {
|
||||
m_permissions = perm;
|
||||
m_permissions = perm;
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t NimBLECharacteristic::getProperties() {
|
||||
return m_properties;
|
||||
return m_properties;
|
||||
} // getProperties
|
||||
|
||||
|
||||
|
@ -167,7 +170,7 @@ uint8_t NimBLECharacteristic::getProperties() {
|
|||
* @brief Get the service associated with this characteristic.
|
||||
*/
|
||||
NimBLEService* NimBLECharacteristic::getService() {
|
||||
return m_pService;
|
||||
return m_pService;
|
||||
} // getService
|
||||
|
||||
|
||||
|
@ -176,7 +179,7 @@ NimBLEService* NimBLECharacteristic::getService() {
|
|||
* @return The UUID of the characteristic.
|
||||
*/
|
||||
NimBLEUUID NimBLECharacteristic::getUUID() {
|
||||
return m_uuid;
|
||||
return m_uuid;
|
||||
} // getUUID
|
||||
|
||||
|
||||
|
@ -185,7 +188,7 @@ NimBLEUUID NimBLECharacteristic::getUUID() {
|
|||
* @return A pointer to storage containing the current characteristic value.
|
||||
*/
|
||||
std::string NimBLECharacteristic::getValue() {
|
||||
return m_value.getValue();
|
||||
return m_value.getValue();
|
||||
} // getValue
|
||||
|
||||
|
||||
|
@ -194,31 +197,40 @@ std::string NimBLECharacteristic::getValue() {
|
|||
* @return A pointer to storage containing the current characteristic data.
|
||||
*/
|
||||
uint8_t* NimBLECharacteristic::getData() {
|
||||
return m_value.getData();
|
||||
return m_value.getData();
|
||||
} // getData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the the current data length of the characteristic.
|
||||
* @return The length of the current characteristic data.
|
||||
*/
|
||||
size_t NimBLECharacteristic:: getDataLength() {
|
||||
return m_value.getLength();
|
||||
}
|
||||
|
||||
|
||||
int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
const ble_uuid_t *uuid;
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg;
|
||||
NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(),
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(),
|
||||
ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR ? "Read" : "Write");
|
||||
|
||||
uuid = ctxt->chr->uuid;
|
||||
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
|
||||
uuid = ctxt->chr->uuid;
|
||||
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
|
||||
switch(ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||
//NIMBLE_LOGD(LOG_TAG, "read char pkthdr len:%d flags:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_flags);
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8) {
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
|
||||
}
|
||||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8) {
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
|
||||
}
|
||||
rc = os_mbuf_append(ctxt->om, pCharacteristic->getData(), pCharacteristic->m_value.getLength());
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
@ -230,15 +242,15 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||
}
|
||||
|
||||
//pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len);
|
||||
pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len);
|
||||
os_mbuf *next;
|
||||
next = SLIST_NEXT(ctxt->om, om_next);
|
||||
while(next != NULL){
|
||||
//NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len);
|
||||
pCharacteristic->m_value.addPart(next->om_data, next->om_len);
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
pCharacteristic->m_value.commit();
|
||||
pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len);
|
||||
os_mbuf *next;
|
||||
next = SLIST_NEXT(ctxt->om, om_next);
|
||||
while(next != NULL){
|
||||
//NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len);
|
||||
pCharacteristic->m_value.addPart(next->om_data, next->om_len);
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
pCharacteristic->m_value.commit();
|
||||
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic);
|
||||
|
||||
return 0;
|
||||
|
@ -246,7 +258,7 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
@ -272,10 +284,10 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
|||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", event->subscribe.conn_handle, subVal);
|
||||
|
||||
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID((uint16_t)0x2902);
|
||||
if(p2902 == nullptr){
|
||||
ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str());
|
||||
if(p2902 == nullptr){
|
||||
ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s", getUUID().toString().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY);
|
||||
p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE);
|
||||
|
@ -307,9 +319,9 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
|||
* @return N/A
|
||||
*/
|
||||
void NimBLECharacteristic::indicate() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length());
|
||||
notify(false);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< indicate");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", m_value.getValue().length());
|
||||
notify(false);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< indicate");
|
||||
} // indicate
|
||||
|
||||
/**
|
||||
|
@ -319,16 +331,16 @@ void NimBLECharacteristic::indicate() {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLECharacteristic::notify(bool is_notification) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length());
|
||||
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", m_value.getValue().length());
|
||||
|
||||
assert(getService() != nullptr);
|
||||
assert(getService()->getServer() != nullptr);
|
||||
assert(getService() != nullptr);
|
||||
assert(getService()->getServer() != nullptr);
|
||||
|
||||
|
||||
if (getService()->getServer()->getConnectedCount() == 0) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients.");
|
||||
return;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify: No connected clients.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pCallbacks->onNotify(this);
|
||||
|
||||
|
@ -353,8 +365,8 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
}
|
||||
|
||||
if (length > _mtu - 3) {
|
||||
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((*it).second == 0) {
|
||||
//NIMBLE_LOGI(LOG_TAG, "Skipping unsubscribed client");
|
||||
|
@ -404,9 +416,9 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
m_pCallbacks->onStatus(this, NimBLECharacteristicCallbacks::Status::ERROR_GATT, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify");
|
||||
} // Notify
|
||||
|
||||
|
||||
|
@ -415,11 +427,11 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
* @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic.
|
||||
*/
|
||||
void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallback;
|
||||
}
|
||||
if (pCallbacks != nullptr){
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallback;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
// Backward compatibility - to be removed ////////////////////////////////
|
||||
|
@ -431,11 +443,11 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
|||
* @return N/A
|
||||
*/
|
||||
void NimBLECharacteristic::setBroadcastProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST);
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_BROADCAST);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_BROADCAST);
|
||||
}
|
||||
} // setBroadcastProperty
|
||||
|
||||
|
||||
|
@ -444,11 +456,11 @@ void NimBLECharacteristic::setBroadcastProperty(bool value) {
|
|||
* @param [in] value Set to true if we are to allow indicate messages.
|
||||
*/
|
||||
void NimBLECharacteristic::setIndicateProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE);
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_INDICATE);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_INDICATE);
|
||||
}
|
||||
} // setIndicateProperty
|
||||
|
||||
|
||||
|
@ -457,11 +469,11 @@ void NimBLECharacteristic::setIndicateProperty(bool value) {
|
|||
* @param [in] value Set to true if we are to allow notification messages.
|
||||
*/
|
||||
void NimBLECharacteristic::setNotifyProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY);
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_NOTIFY);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_NOTIFY);
|
||||
}
|
||||
} // setNotifyProperty
|
||||
|
||||
|
||||
|
@ -470,11 +482,11 @@ void NimBLECharacteristic::setNotifyProperty(bool value) {
|
|||
* @param [in] value Set to true if we are to allow reads.
|
||||
*/
|
||||
void NimBLECharacteristic::setReadProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_READ);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_READ);
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_READ);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_READ);
|
||||
}
|
||||
} // setReadProperty
|
||||
|
||||
|
||||
|
@ -483,11 +495,11 @@ void NimBLECharacteristic::setReadProperty(bool value) {
|
|||
* @param [in] value Set to true if we are to allow writes with no response.
|
||||
*/
|
||||
void NimBLECharacteristic::setWriteNoResponseProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP);
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE_NO_RSP);
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE_NO_RSP);
|
||||
}
|
||||
} // setWriteNoResponseProperty
|
||||
|
||||
|
||||
|
@ -496,11 +508,11 @@ void NimBLECharacteristic::setWriteNoResponseProperty(bool value) {
|
|||
* @param [in] value Set to true if we are to allow writes.
|
||||
*/
|
||||
void NimBLECharacteristic::setWriteProperty(bool value) {
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE );
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE );
|
||||
}
|
||||
if (value) {
|
||||
m_properties = (m_properties | BLE_GATT_CHR_F_WRITE );
|
||||
} else {
|
||||
m_properties = (m_properties & ~BLE_GATT_CHR_F_WRITE );
|
||||
}
|
||||
} // setWriteProperty
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -509,24 +521,24 @@ void NimBLECharacteristic::setWriteProperty(bool value) {
|
|||
* @param [in] data The data to set for the characteristic.
|
||||
* @param [in] length The length of the data in bytes.
|
||||
*/
|
||||
void NimBLECharacteristic::setValue(uint8_t* data, size_t length) {
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
||||
free(pHex);
|
||||
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
||||
free(pHex);
|
||||
|
||||
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
||||
return;
|
||||
}
|
||||
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
||||
return;
|
||||
}
|
||||
|
||||
m_value.setValue(data, length);
|
||||
m_value.setValue(data, length);
|
||||
|
||||
// if(m_handle != NULL_HANDLE) {
|
||||
//ble_gatts_chr_updated(m_handle);
|
||||
// ble_gattc_notify(getService()->getServer()->m_connId, m_handle);
|
||||
// }
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setValue");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setValue");
|
||||
} // setValue
|
||||
|
||||
|
||||
|
@ -537,43 +549,43 @@ void NimBLECharacteristic::setValue(uint8_t* data, size_t length) {
|
|||
* @param [in] Set the value of the characteristic.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLECharacteristic::setValue(std::string value) {
|
||||
setValue((uint8_t*)(value.data()), value.length());
|
||||
void NimBLECharacteristic::setValue(const std::string &value) {
|
||||
setValue((uint8_t*)(value.data()), value.length());
|
||||
} // setValue
|
||||
|
||||
void NimBLECharacteristic::setValue(uint16_t& data16) {
|
||||
uint8_t temp[2];
|
||||
temp[0] = data16;
|
||||
temp[1] = data16 >> 8;
|
||||
setValue(temp, 2);
|
||||
uint8_t temp[2];
|
||||
temp[0] = data16;
|
||||
temp[1] = data16 >> 8;
|
||||
setValue(temp, 2);
|
||||
} // setValue
|
||||
|
||||
void NimBLECharacteristic::setValue(uint32_t& data32) {
|
||||
uint8_t temp[4];
|
||||
temp[0] = data32;
|
||||
temp[1] = data32 >> 8;
|
||||
temp[2] = data32 >> 16;
|
||||
temp[3] = data32 >> 24;
|
||||
setValue(temp, 4);
|
||||
uint8_t temp[4];
|
||||
temp[0] = data32;
|
||||
temp[1] = data32 >> 8;
|
||||
temp[2] = data32 >> 16;
|
||||
temp[3] = data32 >> 24;
|
||||
setValue(temp, 4);
|
||||
} // setValue
|
||||
|
||||
void NimBLECharacteristic::setValue(int& data32) {
|
||||
uint8_t temp[4];
|
||||
temp[0] = data32;
|
||||
temp[1] = data32 >> 8;
|
||||
temp[2] = data32 >> 16;
|
||||
temp[3] = data32 >> 24;
|
||||
setValue(temp, 4);
|
||||
uint8_t temp[4];
|
||||
temp[0] = data32;
|
||||
temp[1] = data32 >> 8;
|
||||
temp[2] = data32 >> 16;
|
||||
temp[3] = data32 >> 24;
|
||||
setValue(temp, 4);
|
||||
} // setValue
|
||||
|
||||
void NimBLECharacteristic::setValue(float& data32) {
|
||||
float temp = data32;
|
||||
setValue((uint8_t*)&temp, 4);
|
||||
float temp = data32;
|
||||
setValue((uint8_t*)&temp, 4);
|
||||
} // setValue
|
||||
|
||||
void NimBLECharacteristic::setValue(double& data64) {
|
||||
double temp = data64;
|
||||
setValue((uint8_t*)&temp, 8);
|
||||
double temp = data64;
|
||||
setValue((uint8_t*)&temp, 8);
|
||||
} // setValue
|
||||
|
||||
|
||||
|
@ -582,18 +594,18 @@ void NimBLECharacteristic::setValue(double& data64) {
|
|||
* @return A string representation of the characteristic.
|
||||
*/
|
||||
std::string NimBLECharacteristic::toString() {
|
||||
std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x";
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
res += hex;
|
||||
res += " ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_READ ) res += "Read ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_WRITE) res += "Write ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP) res += "WriteNoResponse ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_BROADCAST) res += "Broadcast ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_NOTIFY) res += "Notify ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_INDICATE) res += "Indicate ";
|
||||
return res;
|
||||
std::string res = "UUID: " + m_uuid.toString() + ", handle : 0x";
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
res += hex;
|
||||
res += " ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_READ ) res += "Read ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_WRITE) res += "Write ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_WRITE_NO_RSP) res += "WriteNoResponse ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_BROADCAST) res += "Broadcast ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_NOTIFY) res += "Notify ";
|
||||
if (m_properties & BLE_GATT_CHR_PROP_INDICATE) res += "Indicate ";
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -605,7 +617,7 @@ NimBLECharacteristicCallbacks::~NimBLECharacteristicCallbacks() {}
|
|||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
|
||||
} // onRead
|
||||
|
||||
|
||||
|
@ -614,7 +626,7 @@ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic
|
|||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
|
||||
} // onWrite
|
||||
|
||||
|
||||
|
@ -623,7 +635,7 @@ void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristi
|
|||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacteristic) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default");
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onNotify: default");
|
||||
} // onNotify
|
||||
|
||||
|
||||
|
@ -634,7 +646,8 @@ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacterist
|
|||
* @param [in] code Additional code of underlying errors
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
||||
} // onStatus
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -16,6 +16,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
#undef min
|
||||
|
@ -57,21 +60,21 @@ class NimBLECharacteristicCallbacks;
|
|||
*/
|
||||
class NimBLEDescriptorMap {
|
||||
public:
|
||||
void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor);
|
||||
void setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor);
|
||||
// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor);
|
||||
NimBLEDescriptor* getByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getByUUID(NimBLEUUID uuid);
|
||||
// NimBLEDescriptor* getByHandle(uint16_t handle);
|
||||
std::string toString();
|
||||
NimBLEDescriptor* getFirst();
|
||||
NimBLEDescriptor* getNext();
|
||||
void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor);
|
||||
void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor);
|
||||
// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor);
|
||||
NimBLEDescriptor* getByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid);
|
||||
// NimBLEDescriptor* getByHandle(uint16_t handle);
|
||||
std::string toString();
|
||||
NimBLEDescriptor* getFirst();
|
||||
NimBLEDescriptor* getNext();
|
||||
uint8_t getSize();
|
||||
|
||||
private:
|
||||
std::map<NimBLEDescriptor*, std::string> m_uuidMap;
|
||||
// std::map<uint16_t, BLEDescriptor*> m_handleMap;
|
||||
std::map<NimBLEDescriptor*, std::string>::iterator m_iterator;
|
||||
std::map<NimBLEDescriptor*, std::string> m_uuidMap;
|
||||
// std::map<uint16_t, BLEDescriptor*> m_handleMap;
|
||||
std::map<NimBLEDescriptor*, std::string>::iterator m_iterator;
|
||||
};
|
||||
|
||||
|
||||
|
@ -83,84 +86,85 @@ private:
|
|||
*/
|
||||
class NimBLECharacteristic {
|
||||
public:
|
||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
NimBLEDescriptor* createDescriptor(NimBLEUUID uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
|
||||
NimBLEDescriptor* getDescriptorByUUID(NimBLEUUID descriptorUUID);
|
||||
NimBLEUUID getUUID();
|
||||
std::string getValue();
|
||||
uint8_t* getData();
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &descriptorUUID);
|
||||
NimBLEUUID getUUID();
|
||||
std::string getValue();
|
||||
uint8_t* getData();
|
||||
size_t getDataLength();
|
||||
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
// Backward Compatibility - to be removed
|
||||
void setBroadcastProperty(bool value);
|
||||
void setIndicateProperty(bool value);
|
||||
void setNotifyProperty(bool value);
|
||||
void setReadProperty(bool value);
|
||||
void setIndicateProperty(bool value);
|
||||
void setNotifyProperty(bool value);
|
||||
void setReadProperty(bool value);
|
||||
void setWriteProperty(bool value);
|
||||
void setWriteNoResponseProperty(bool value);
|
||||
void setWriteNoResponseProperty(bool value);
|
||||
//////////////////////////////////////////////////////
|
||||
void setValue(uint8_t* data, size_t size);
|
||||
void setValue(std::string value);
|
||||
void setValue(uint16_t& data16);
|
||||
void setValue(uint32_t& data32);
|
||||
void setValue(int& data32);
|
||||
void setValue(float& data32);
|
||||
void setValue(double& data64);
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
void setValue(uint16_t& data16);
|
||||
void setValue(uint32_t& data32);
|
||||
void setValue(int& data32);
|
||||
void setValue(float& data32);
|
||||
void setValue(double& data64);
|
||||
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
// void setAccessPermissions(uint16_t perm);
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
// void setAccessPermissions(uint16_t perm);
|
||||
|
||||
// Backward Compatibility - to be removed
|
||||
/* static const uint32_t PROPERTY_READ = 1<<0;
|
||||
static const uint32_t PROPERTY_WRITE = 1<<1;
|
||||
static const uint32_t PROPERTY_NOTIFY = 1<<2;
|
||||
static const uint32_t PROPERTY_BROADCAST = 1<<3;
|
||||
static const uint32_t PROPERTY_INDICATE = 1<<4;
|
||||
static const uint32_t PROPERTY_WRITE_NR = 1<<5;
|
||||
/* static const uint32_t PROPERTY_READ = 1<<0;
|
||||
static const uint32_t PROPERTY_WRITE = 1<<1;
|
||||
static const uint32_t PROPERTY_NOTIFY = 1<<2;
|
||||
static const uint32_t PROPERTY_BROADCAST = 1<<3;
|
||||
static const uint32_t PROPERTY_INDICATE = 1<<4;
|
||||
static const uint32_t PROPERTY_WRITE_NR = 1<<5;
|
||||
*/
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
// friend class NimBLEDescriptor;
|
||||
// friend class NimBLECharacteristicMap;
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
// friend class NimBLEDescriptor;
|
||||
// friend class NimBLECharacteristicMap;
|
||||
|
||||
NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(NimBLEUUID uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
virtual ~NimBLECharacteristic();
|
||||
NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
virtual ~NimBLECharacteristic();
|
||||
|
||||
NimBLEUUID m_uuid;
|
||||
NimBLEDescriptorMap m_descriptorMap;
|
||||
uint16_t m_handle;
|
||||
uint16_t m_properties;
|
||||
NimBLECharacteristicCallbacks* m_pCallbacks;
|
||||
NimBLEService* m_pService;
|
||||
NimBLEValue m_value;
|
||||
// uint16_t m_permissions;
|
||||
NimBLEUUID m_uuid;
|
||||
NimBLEDescriptorMap m_descriptorMap;
|
||||
uint16_t m_handle;
|
||||
uint16_t m_properties;
|
||||
NimBLECharacteristicCallbacks* m_pCallbacks;
|
||||
NimBLEService* m_pService;
|
||||
NimBLEValue m_value;
|
||||
// uint16_t m_permissions;
|
||||
|
||||
void addDescriptor(NimBLEDescriptor* pDescriptor);
|
||||
void addDescriptor(NimBLEDescriptor* pDescriptor);
|
||||
NimBLEService* getService();
|
||||
uint8_t getProperties();
|
||||
void setSubscribe(struct ble_gap_event *event);
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreConfEvt = FreeRTOS::Semaphore("ConfEvt");
|
||||
}; // NimBLECharacteristic
|
||||
|
||||
|
||||
|
@ -174,21 +178,23 @@ private:
|
|||
class NimBLECharacteristicCallbacks {
|
||||
public:
|
||||
typedef enum {
|
||||
SUCCESS_INDICATE,
|
||||
SUCCESS_NOTIFY,
|
||||
ERROR_INDICATE_DISABLED,
|
||||
ERROR_NOTIFY_DISABLED,
|
||||
ERROR_GATT,
|
||||
ERROR_NO_CLIENT,
|
||||
ERROR_INDICATE_TIMEOUT,
|
||||
ERROR_INDICATE_FAILURE
|
||||
}Status;
|
||||
SUCCESS_INDICATE,
|
||||
SUCCESS_NOTIFY,
|
||||
ERROR_INDICATE_DISABLED,
|
||||
ERROR_NOTIFY_DISABLED,
|
||||
ERROR_GATT,
|
||||
ERROR_NO_CLIENT,
|
||||
ERROR_INDICATE_TIMEOUT,
|
||||
ERROR_INDICATE_FAILURE
|
||||
}Status;
|
||||
|
||||
virtual ~NimBLECharacteristicCallbacks();
|
||||
virtual void onRead(NimBLECharacteristic* pCharacteristic);
|
||||
virtual void onWrite(NimBLECharacteristic* pCharacteristic);
|
||||
virtual ~NimBLECharacteristicCallbacks();
|
||||
virtual void onRead(NimBLECharacteristic* pCharacteristic);
|
||||
virtual void onWrite(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);
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/
|
|
@ -12,6 +12,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
|
@ -22,7 +25,7 @@
|
|||
* @return The characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLECharacteristicMap::getByHandle(uint16_t handle) {
|
||||
return m_handleMap.at(handle);
|
||||
return m_handleMap.at(handle);
|
||||
} // getByHandle
|
||||
|
||||
|
||||
|
@ -41,21 +44,21 @@ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const char* uuid) {
|
|||
* @param [in] UUID The UUID to look up the characteristic.
|
||||
* @return The characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(NimBLEUUID uuid) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
} // getByUUID
|
||||
|
||||
/**
|
||||
* @brief Get the number of characteristics in the map.
|
||||
*/
|
||||
uint8_t NimBLECharacteristicMap::getSize() {
|
||||
return (uint8_t)m_uuidMap.size();
|
||||
return (uint8_t)m_uuidMap.size();
|
||||
} // getSize
|
||||
|
||||
/**
|
||||
|
@ -63,11 +66,11 @@ uint8_t NimBLECharacteristicMap::getSize() {
|
|||
* @return The first characteristic in the map.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLECharacteristicMap::getFirst() {
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLECharacteristic* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLECharacteristic* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getFirst
|
||||
|
||||
|
||||
|
@ -76,10 +79,10 @@ NimBLECharacteristic* NimBLECharacteristicMap::getFirst() {
|
|||
* @return The next characteristic in the map.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLECharacteristicMap::getNext() {
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLECharacteristic* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLECharacteristic* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getNext
|
||||
|
||||
|
||||
|
@ -90,7 +93,7 @@ NimBLECharacteristic* NimBLECharacteristicMap::getNext() {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic* characteristic) {
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLECharacteristic*>(handle, characteristic));
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLECharacteristic*>(handle, characteristic));
|
||||
} // setByHandle
|
||||
|
||||
|
||||
|
@ -100,8 +103,8 @@ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic*
|
|||
* @param [in] characteristic The characteristic to cache.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, NimBLEUUID uuid) {
|
||||
m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString()));
|
||||
void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) {
|
||||
m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString()));
|
||||
} // setByUUID
|
||||
|
||||
|
||||
|
@ -110,19 +113,20 @@ void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, N
|
|||
* @return A string representation of the characteristic map.
|
||||
*/
|
||||
std::string NimBLECharacteristicMap::toString() {
|
||||
std::string res;
|
||||
int count = 0;
|
||||
char hex[5];
|
||||
for (auto &myPair: m_uuidMap) {
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return res;
|
||||
std::string res;
|
||||
int count = 0;
|
||||
char hex[5];
|
||||
for (auto &myPair: m_uuidMap) {
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLEClient.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -40,8 +43,8 @@ static NimBLEClientCallbacks defaultCallbacks;
|
|||
* Since there is a hierarchical relationship here, we will have the idea that from a NimBLERemoteService will own
|
||||
* zero or more remote characteristics and a NimBLERemoteCharacteristic will own zero or more remote NimBLEDescriptors.
|
||||
*
|
||||
* We will assume that a NimBLERemoteService contains a map that maps NimBLEUUIDs to the set of owned characteristics
|
||||
* and that a NimBLECharacteristic contains a map that maps NimBLEUUIDs to the set of owned descriptors.
|
||||
* We will assume that a NimBLERemoteService contains a vector of owned characteristics
|
||||
* and that a NimBLECharacteristic contains a vector of owned descriptors.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
@ -50,18 +53,17 @@ NimBLEClient::NimBLEClient()
|
|||
{
|
||||
m_pClientCallbacks = &defaultCallbacks;
|
||||
m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||
m_haveServices = false;
|
||||
m_isConnected = false;
|
||||
m_connectTimeout = 30000;
|
||||
m_connectTimeout = 30000;
|
||||
|
||||
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
||||
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
||||
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
||||
m_pConnParams.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN; // min_int = 0x10*1.25ms = 20ms
|
||||
m_pConnParams.itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX; // max_int = 0x20*1.25ms = 40ms
|
||||
m_pConnParams.latency = BLE_GAP_INITIAL_CONN_LATENCY; // number of packets allowed to skip (extends max interval)
|
||||
m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
|
||||
m_pConnParams.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN; // min_int = 0x10*1.25ms = 20ms
|
||||
m_pConnParams.itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX; // max_int = 0x20*1.25ms = 40ms
|
||||
m_pConnParams.latency = BLE_GAP_INITIAL_CONN_LATENCY; // number of packets allowed to skip (extends max interval)
|
||||
m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
|
||||
m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
|
||||
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
|
||||
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
|
||||
} // NimBLEClient
|
||||
|
||||
|
||||
|
@ -74,7 +76,7 @@ NimBLEClient::~NimBLEClient() {
|
|||
// Before we are finished with the client, we must release resources.
|
||||
clearServices();
|
||||
|
||||
if(m_deleteCallbacks) {
|
||||
if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) {
|
||||
delete m_pClientCallbacks;
|
||||
}
|
||||
|
||||
|
@ -87,11 +89,11 @@ NimBLEClient::~NimBLEClient() {
|
|||
void NimBLEClient::clearServices() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> clearServices");
|
||||
// Delete all the services.
|
||||
for (auto &myPair : m_servicesMap) {
|
||||
delete myPair.second;
|
||||
for(auto &it: m_servicesVector) {
|
||||
delete it;
|
||||
}
|
||||
m_servicesMap.clear();
|
||||
m_haveServices = false;
|
||||
m_servicesVector.clear();
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< clearServices");
|
||||
} // clearServices
|
||||
|
||||
|
@ -120,7 +122,7 @@ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices)
|
|||
* @param [in] address The address of the partner.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServices) {
|
||||
bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
||||
|
||||
if(!NimBLEDevice::m_synced) {
|
||||
|
@ -179,19 +181,7 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ
|
|||
clearServices();
|
||||
}
|
||||
|
||||
if (!m_haveServices) {
|
||||
if (!retrieveServices()) {
|
||||
// error getting services, make sure we disconnect and release any resources before returning
|
||||
disconnect();
|
||||
clearServices();
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGD(LOG_TAG, "Found %d services", getServices()->size());
|
||||
}
|
||||
}
|
||||
|
||||
m_pClientCallbacks->onConnect(this);
|
||||
m_pClientCallbacks->onConnect(this);
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< connect()");
|
||||
return true;
|
||||
|
@ -250,23 +240,23 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
|||
* @brief Set the connection paramaters to use when connecting to a server.
|
||||
*/
|
||||
void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
uint16_t scanInterval, uint16_t scanWindow)/*,
|
||||
uint16_t minConnTime, uint16_t maxConnTime)*/
|
||||
{
|
||||
|
||||
m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units
|
||||
m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units
|
||||
m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units
|
||||
m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval)
|
||||
m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval)
|
||||
m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
|
||||
// These are not used by NimBLE at this time - Must leave at defaults
|
||||
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
|
||||
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
|
||||
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
|
||||
|
||||
int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
|
||||
int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
|
||||
assert(rc == 0 && "Invalid Connection parameters");
|
||||
}
|
||||
|
||||
|
@ -277,12 +267,12 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
|
|||
void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout)
|
||||
{
|
||||
ble_gap_upd_params params;
|
||||
ble_gap_upd_params params;
|
||||
|
||||
params.latency = latency;
|
||||
params.itvl_max = maxInterval;
|
||||
params.itvl_min = minInterval;
|
||||
params.supervision_timeout = timeout;
|
||||
params.latency = latency;
|
||||
params.itvl_max = maxInterval;
|
||||
params.itvl_min = minInterval;
|
||||
params.supervision_timeout = timeout;
|
||||
// These are not used by NimBLE at this time - Must leave at defaults
|
||||
params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
|
||||
params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
|
||||
|
@ -344,6 +334,24 @@ int NimBLEClient::getRssi() {
|
|||
} // getRssi
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the beginning of the vector of remote service pointers.
|
||||
* @return An iterator to the beginning of the vector of remote service pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteService*>::iterator NimBLEClient::begin() {
|
||||
return m_servicesVector.begin();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the end of the vector of remote service pointers.
|
||||
* @return An iterator to the end of the vector of remote service pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteService*>::iterator NimBLEClient::end() {
|
||||
return m_servicesVector.end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service BLE Remote Service instance corresponding to the uuid.
|
||||
* @param [in] uuid The UUID of the service being sought.
|
||||
|
@ -359,29 +367,62 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
|
|||
* @param [in] uuid The UUID of the service being sought.
|
||||
* @return A reference to the Service or nullptr if don't know about it.
|
||||
*/
|
||||
NimBLERemoteService* NimBLEClient::getService(NimBLEUUID uuid) {
|
||||
NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
|
||||
|
||||
if (!m_haveServices) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string uuidStr = uuid.toString();
|
||||
for (auto &myPair : m_servicesMap) {
|
||||
if (myPair.first == uuidStr) {
|
||||
for(auto &it: m_servicesVector) {
|
||||
if(it->getUUID() == uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
|
||||
return myPair.second;
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
size_t prev_size = m_servicesVector.size();
|
||||
if(retrieveServices(&uuid)) {
|
||||
if(m_servicesVector.size() > prev_size) {
|
||||
return m_servicesVector.back();
|
||||
}
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getService: not found");
|
||||
return nullptr;
|
||||
} // getService
|
||||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the map of found services.
|
||||
* @Get a pointer to the vector of found services.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all services retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored services,
|
||||
* if vector is empty it will retrieve all services from the peripheral.
|
||||
* @return a pointer to the vector of available services.
|
||||
*/
|
||||
std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
|
||||
return &m_servicesMap;
|
||||
std::vector<NimBLERemoteService*>* NimBLEClient::getServices(bool refresh) {
|
||||
if(refresh) {
|
||||
clearServices();
|
||||
}
|
||||
|
||||
if(m_servicesVector.empty()) {
|
||||
if (!retrieveServices()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get services");
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGI(LOG_TAG, "Found %d services", m_servicesVector.size());
|
||||
}
|
||||
}
|
||||
return &m_servicesVector;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ Retrieves the full database of attributes that the peripheral has available.
|
||||
*/
|
||||
void NimBLEClient::discoverAttributes() {
|
||||
for(auto svc: *getServices(true)) {
|
||||
for(auto chr: *svc->getCharacteristics(true)) {
|
||||
chr->getDescriptors(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -392,7 +433,7 @@ std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
|
|||
* We then ask for the characteristics for each service found and their desciptors.
|
||||
* @return true on success otherwise false if an error occurred
|
||||
*/
|
||||
bool NimBLEClient::retrieveServices() {
|
||||
bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
|
||||
/**
|
||||
* Design
|
||||
* ------
|
||||
|
@ -401,6 +442,7 @@ bool NimBLEClient::retrieveServices() {
|
|||
*/
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveServices");
|
||||
int rc = 0;
|
||||
|
||||
if(!m_isConnected){
|
||||
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting");
|
||||
|
@ -409,26 +451,21 @@ bool NimBLEClient::retrieveServices() {
|
|||
|
||||
m_semaphoreSearchCmplEvt.take("retrieveServices");
|
||||
|
||||
int rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
|
||||
if(uuid_filter == nullptr) {
|
||||
rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
|
||||
} else {
|
||||
rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u,
|
||||
NimBLEClient::serviceDiscoveredCB, this);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_haveServices = false;
|
||||
m_semaphoreSearchCmplEvt.give();
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait until we have all the services
|
||||
// If sucessful, remember that we now have services.
|
||||
m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0);
|
||||
if(m_haveServices){
|
||||
for (auto &myPair : m_servicesMap) {
|
||||
if(!m_isConnected || !myPair.second->retrieveCharacteristics()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0){
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
|
||||
return true;
|
||||
}
|
||||
|
@ -449,7 +486,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
|||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_svc *service, void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d", error->status, conn_handle);
|
||||
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? service->start_handle : -1);
|
||||
|
||||
NimBLEClient *peer = (NimBLEClient*)arg;
|
||||
int rc=0;
|
||||
|
||||
|
@ -460,9 +499,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
|||
|
||||
switch (error->status) {
|
||||
case 0: {
|
||||
// Found a service - add it to the map
|
||||
// Found a service - add it to the vector
|
||||
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
|
||||
peer->m_servicesMap.insert(std::pair<std::string, NimBLERemoteService*>(pRemoteService->getUUID().toString(), pRemoteService));
|
||||
peer->m_servicesVector.push_back(pRemoteService);
|
||||
break;
|
||||
}
|
||||
case BLE_HS_EDONE:{
|
||||
|
@ -494,8 +533,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
|||
* @param [in] characteristicUUID The characteristic whose value we wish to read.
|
||||
* @returns characteristic value or an empty string if not found
|
||||
*/
|
||||
std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||
std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s",
|
||||
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||
|
||||
std::string ret = "";
|
||||
NimBLERemoteService* pService = getService(serviceUUID);
|
||||
|
@ -518,8 +558,11 @@ std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteri
|
|||
* @param [in] characteristicUUID The characteristic whose value we wish to write.
|
||||
* @returns true if successful otherwise false
|
||||
*/
|
||||
bool NimBLEClient::setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||
bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
||||
const std::string &value)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s",
|
||||
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||
|
||||
bool ret = false;
|
||||
NimBLERemoteService* pService = getService(serviceUUID);
|
||||
|
@ -656,23 +699,33 @@ uint16_t NimBLEClient::getMTU() {
|
|||
return 0;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle);
|
||||
if(!client->m_haveServices)
|
||||
return 0;
|
||||
|
||||
for(auto &sPair : client->m_servicesMap){
|
||||
for(auto &it: client->m_servicesVector) {
|
||||
// Dont waste cycles searching services without this handle in their range
|
||||
if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) {
|
||||
if(it->getEndHandle() < event->notify_rx.attr_handle) {
|
||||
continue;
|
||||
}
|
||||
auto cMap = sPair.second->getCharacteristicsByHandle();
|
||||
NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", sPair.second->getUUID().toString().c_str(),event->notify_rx.attr_handle);
|
||||
auto characteristic = cMap->find(event->notify_rx.attr_handle);
|
||||
if(characteristic != cMap->end()) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str());
|
||||
|
||||
if (characteristic->second->m_notifyCallback != nullptr) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str());
|
||||
characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication);
|
||||
auto cVector = &it->m_characteristicVector;
|
||||
NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d",
|
||||
it->getUUID().toString().c_str(),
|
||||
event->notify_rx.attr_handle);
|
||||
|
||||
auto characteristic = cVector->cbegin();
|
||||
for(; characteristic != cVector->cend(); ++characteristic) {
|
||||
if((*characteristic)->m_handle == event->notify_rx.attr_handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if(characteristic != cVector->cend()) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str());
|
||||
|
||||
if ((*characteristic)->m_notifyCallback != nullptr) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s",
|
||||
(*characteristic)->toString().c_str());
|
||||
(*characteristic)->m_notifyCallback(*characteristic, event->notify_rx.om->om_data,
|
||||
event->notify_rx.om->om_len,
|
||||
!event->notify_rx.indication);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -750,7 +803,6 @@ uint16_t NimBLEClient::getMTU() {
|
|||
event->mtu.conn_handle,
|
||||
event->mtu.value);
|
||||
client->m_semaphoreOpenEvt.give(0);
|
||||
//client->m_mtu = event->mtu.value;
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_MTU
|
||||
|
||||
|
@ -833,10 +885,10 @@ bool NimBLEClient::isConnected() {
|
|||
*/
|
||||
void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) {
|
||||
if (pClientCallbacks != nullptr){
|
||||
m_pClientCallbacks = pClientCallbacks;
|
||||
} else {
|
||||
m_pClientCallbacks = &defaultCallbacks;
|
||||
}
|
||||
m_pClientCallbacks = pClientCallbacks;
|
||||
} else {
|
||||
m_pClientCallbacks = &defaultCallbacks;
|
||||
}
|
||||
m_deleteCallbacks = deleteCallbacks;
|
||||
} // setClientCallbacks
|
||||
|
||||
|
@ -848,8 +900,9 @@ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, b
|
|||
std::string NimBLEClient::toString() {
|
||||
std::string res = "peer address: " + m_peerAddress.toString();
|
||||
res += "\nServices:\n";
|
||||
for (auto &myPair : m_servicesMap) {
|
||||
res += myPair.second->toString() + "\n";
|
||||
|
||||
for(auto &it: m_servicesVector) {
|
||||
res += it->toString() + "\n";
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -865,7 +918,7 @@ void NimBLEClientCallbacks::onDisconnect(NimBLEClient* pClient) {
|
|||
}
|
||||
|
||||
bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) {
|
||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default");
|
||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -890,4 +943,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){
|
|||
return true;
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
|
|
@ -14,16 +14,24 @@
|
|||
#ifndef MAIN_NIMBLECLIENT_H_
|
||||
#define MAIN_NIMBLECLIENT_H_
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLERemoteService.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
typedef struct {
|
||||
const NimBLEUUID *uuid;
|
||||
const void *attribute;
|
||||
} disc_filter_t;
|
||||
|
||||
class NimBLERemoteService;
|
||||
class NimBLEClientCallbacks;
|
||||
class NimBLEAdvertisedDevice;
|
||||
|
@ -33,58 +41,62 @@ class NimBLEAdvertisedDevice;
|
|||
*/
|
||||
class NimBLEClient {
|
||||
public:
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true); // Connect to the remote BLE Server
|
||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // Disconnect from the remote BLE Server
|
||||
NimBLEAddress getPeerAddress(); // Get the address of the remote BLE Server
|
||||
int getRssi(); // Get the RSSI of the remote BLE Server
|
||||
std::map<std::string, NimBLERemoteService*>* getServices(); // Get a map of the services offered by the remote BLE Server
|
||||
NimBLERemoteService* getService(const char* uuid); // Get a reference to a specified service offered by the remote BLE server.
|
||||
NimBLERemoteService* getService(NimBLEUUID uuid); // Get a reference to a specified service offered by the remote BLE server.
|
||||
std::string getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID); // Get the value of a given characteristic at a given service.
|
||||
bool setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value); // Set the value of a given characteristic at a given service.
|
||||
bool isConnected(); // Return true if we are connected.
|
||||
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks, bool deleteCallbacks = true);
|
||||
std::string toString(); // Return a string representation of this client.
|
||||
uint16_t getConnId();
|
||||
uint16_t getMTU();
|
||||
bool secureConnection();
|
||||
void setConnectTimeout(uint8_t timeout);
|
||||
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings
|
||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||
bool connect(const NimBLEAddress &address, uint8_t type = BLE_ADDR_PUBLIC,
|
||||
bool refreshServices = true);
|
||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
NimBLEAddress getPeerAddress();
|
||||
int getRssi();
|
||||
std::vector<NimBLERemoteService*>* getServices(bool refresh = false);
|
||||
std::vector<NimBLERemoteService*>::iterator begin();
|
||||
std::vector<NimBLERemoteService*>::iterator end();
|
||||
NimBLERemoteService* getService(const char* uuid);
|
||||
NimBLERemoteService* getService(const NimBLEUUID &uuid);
|
||||
std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID);
|
||||
bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
||||
const std::string &value);
|
||||
bool isConnected();
|
||||
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks,
|
||||
bool deleteCallbacks = true);
|
||||
std::string toString();
|
||||
uint16_t getConnId();
|
||||
uint16_t getMTU();
|
||||
bool secureConnection();
|
||||
void setConnectTimeout(uint8_t timeout);
|
||||
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
uint16_t scanInterval=16, uint16_t scanWindow=16);
|
||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void discoverAttributes();
|
||||
|
||||
private:
|
||||
NimBLEClient();
|
||||
~NimBLEClient();
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLERemoteService;
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
static int serviceDiscoveredCB(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg);
|
||||
void clearServices(); // Clear any existing services.
|
||||
bool retrieveServices(); //Retrieve services from the server
|
||||
// void onHostReset();
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLERemoteService;
|
||||
|
||||
NimBLEAddress m_peerAddress = NimBLEAddress("\0\0\0\0\0\0"); // The BD address of the remote server.
|
||||
uint16_t m_conn_id;
|
||||
bool m_haveServices = false; // Have we previously obtain the set of services from the remote server.
|
||||
bool m_isConnected = false; // Are we currently connected.
|
||||
bool m_waitingToConnect =false;
|
||||
bool m_deleteCallbacks = true;
|
||||
int32_t m_connectTimeout;
|
||||
//uint16_t m_mtu = 23;
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
static int serviceDiscoveredCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_svc *service,
|
||||
void *arg);
|
||||
void clearServices();
|
||||
bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr);
|
||||
|
||||
NimBLEAddress m_peerAddress = NimBLEAddress("");
|
||||
uint16_t m_conn_id;
|
||||
bool m_isConnected = false;
|
||||
bool m_waitingToConnect =false;
|
||||
bool m_deleteCallbacks = true;
|
||||
int32_t m_connectTimeout;
|
||||
NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
|
||||
|
||||
FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
||||
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
||||
|
||||
std::map<std::string, NimBLERemoteService*> m_servicesMap;
|
||||
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||
|
||||
private:
|
||||
friend class NimBLEClientCallbacks;
|
||||
|
@ -109,5 +121,6 @@ public:
|
|||
virtual bool onConfirmPIN(uint32_t pin);
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif /* MAIN_NIMBLECLIENT_H_ */
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLEDescriptor.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -30,7 +33,7 @@ static NimBLEDescriptorCallbacks defaultCallbacks;
|
|||
* @brief NimBLEDescriptor constructor.
|
||||
*/
|
||||
NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) {
|
||||
}
|
||||
|
||||
|
@ -38,13 +41,13 @@ NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16
|
|||
* @brief NimBLEDescriptor constructor.
|
||||
*/
|
||||
NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
NimBLECharacteristic* pCharacteristic)
|
||||
{
|
||||
m_uuid = uuid;
|
||||
m_value.attr_len = 0; // Initial length is 0.
|
||||
m_value.attr_max_len = max_len; // Maximum length of the data.
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = nullptr; // No initial characteristic.
|
||||
m_uuid = uuid;
|
||||
m_value.attr_len = 0; // Initial length is 0.
|
||||
m_value.attr_max_len = max_len; // Maximum length of the data.
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = nullptr; // No initial characteristic.
|
||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
|
||||
m_properties = 0;
|
||||
|
@ -81,7 +84,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
|
|||
* @brief NimBLEDescriptor destructor.
|
||||
*/
|
||||
NimBLEDescriptor::~NimBLEDescriptor() {
|
||||
free(m_value.attr_value); // Release the storage we created in the constructor.
|
||||
free(m_value.attr_value); // Release the storage we created in the constructor.
|
||||
} // ~NimBLEDescriptor
|
||||
|
||||
/**
|
||||
|
@ -89,7 +92,7 @@ NimBLEDescriptor::~NimBLEDescriptor() {
|
|||
* @return The handle for this descriptor.
|
||||
*/
|
||||
uint16_t NimBLEDescriptor::getHandle() {
|
||||
return m_handle;
|
||||
return m_handle;
|
||||
} // getHandle
|
||||
|
||||
|
||||
|
@ -98,7 +101,7 @@ uint16_t NimBLEDescriptor::getHandle() {
|
|||
* @return The length (in bytes) of the value of this descriptor.
|
||||
*/
|
||||
size_t NimBLEDescriptor::getLength() {
|
||||
return m_value.attr_len;
|
||||
return m_value.attr_len;
|
||||
} // getLength
|
||||
|
||||
|
||||
|
@ -106,7 +109,7 @@ size_t NimBLEDescriptor::getLength() {
|
|||
* @brief Get the UUID of the descriptor.
|
||||
*/
|
||||
NimBLEUUID NimBLEDescriptor::getUUID() {
|
||||
return m_uuid;
|
||||
return m_uuid;
|
||||
} // getUUID
|
||||
|
||||
|
||||
|
@ -115,7 +118,7 @@ NimBLEUUID NimBLEDescriptor::getUUID() {
|
|||
* @return A pointer to the value of this descriptor.
|
||||
*/
|
||||
uint8_t* NimBLEDescriptor::getValue() {
|
||||
return m_value.attr_value;
|
||||
return m_value.attr_value;
|
||||
} // getValue
|
||||
|
||||
|
||||
|
@ -125,13 +128,13 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||
{
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
|
||||
ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC ? "Read" : "Write");
|
||||
|
||||
uuid = ctxt->chr->uuid;
|
||||
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
|
||||
uuid = ctxt->chr->uuid;
|
||||
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
|
||||
switch(ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC: {
|
||||
pDescriptor->m_pCallbacks->onRead(pDescriptor);
|
||||
|
@ -151,7 +154,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
@ -162,10 +165,10 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
|||
*/
|
||||
void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallbacks;
|
||||
}
|
||||
m_pCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pCallbacks = &defaultCallbacks;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
|
@ -176,9 +179,9 @@ void NimBLEDescriptor::setCallbacks(NimBLEDescriptorCallbacks* pCallbacks) {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEDescriptor::setHandle(uint16_t handle) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle);
|
||||
m_handle = handle;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setHandle()");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle);
|
||||
m_handle = handle;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setHandle()");
|
||||
} // setHandle
|
||||
|
||||
|
||||
|
@ -187,13 +190,13 @@ void NimBLEDescriptor::setHandle(uint16_t handle) {
|
|||
* @param [in] data The data to set for the descriptor.
|
||||
* @param [in] length The length of the data in bytes.
|
||||
*/
|
||||
void NimBLEDescriptor::setValue(uint8_t* data, size_t length) {
|
||||
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
||||
return;
|
||||
}
|
||||
m_value.attr_len = length;
|
||||
memcpy(m_value.attr_value, data, length);
|
||||
void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
|
||||
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
||||
return;
|
||||
}
|
||||
m_value.attr_len = length;
|
||||
memcpy(m_value.attr_value, data, length);
|
||||
} // setValue
|
||||
|
||||
|
||||
|
@ -201,14 +204,14 @@ void NimBLEDescriptor::setValue(uint8_t* data, size_t length) {
|
|||
* @brief Set the value of the descriptor.
|
||||
* @param [in] value The value of the descriptor in string form.
|
||||
*/
|
||||
void NimBLEDescriptor::setValue(std::string value) {
|
||||
setValue((uint8_t*) value.data(), value.length());
|
||||
void NimBLEDescriptor::setValue(const std::string &value) {
|
||||
setValue((uint8_t*) value.data(), value.length());
|
||||
} // setValue
|
||||
|
||||
|
||||
/*
|
||||
void NimBLEDescriptor::setAccessPermissions(uint8_t perm) {
|
||||
m_permissions = perm;
|
||||
m_permissions = perm;
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -218,10 +221,10 @@ void NimBLEDescriptor::setAccessPermissions(uint8_t perm) {
|
|||
* @return A string representation of the descriptor.
|
||||
*/
|
||||
std::string NimBLEDescriptor::toString() {
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex;
|
||||
return res;
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", m_handle);
|
||||
std::string res = "UUID: " + m_uuid.toString() + ", handle: 0x" + hex;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -232,7 +235,7 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {}
|
|||
* @param [in] pDescriptor The descriptor that is the source of the event.
|
||||
*/
|
||||
void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default");
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default");
|
||||
} // onRead
|
||||
|
||||
|
||||
|
@ -241,8 +244,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
|
|||
* @param [in] pDescriptor The descriptor that is the source of the event.
|
||||
*/
|
||||
void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) {
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
|
||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
|
||||
} // onWrite
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
@ -43,44 +46,44 @@ class NimBLEDescriptorCallbacks;
|
|||
*/
|
||||
class NimBLEDescriptor {
|
||||
public:
|
||||
virtual ~NimBLEDescriptor();
|
||||
uint16_t getHandle(); // Get the handle of the descriptor.
|
||||
size_t getLength(); // Get the length of the value of the descriptor.
|
||||
NimBLEUUID getUUID(); // Get the UUID of the descriptor.
|
||||
uint8_t* getValue(); // Get a pointer to the value of the descriptor.
|
||||
// void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor.
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor.
|
||||
void setValue(uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data.
|
||||
void setValue(std::string value); // Set the value of the descriptor as a data buffer.
|
||||
virtual ~NimBLEDescriptor();
|
||||
uint16_t getHandle(); // Get the handle of the descriptor.
|
||||
size_t getLength(); // Get the length of the value of the descriptor.
|
||||
NimBLEUUID getUUID(); // Get the UUID of the descriptor.
|
||||
uint8_t* getValue(); // Get a pointer to the value of the descriptor.
|
||||
// void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor.
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor.
|
||||
void setValue(const uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data.
|
||||
void setValue(const std::string &value); // Set the value of the descriptor as a data buffer.
|
||||
|
||||
std::string toString(); // Convert the descriptor to a string representation.
|
||||
std::string toString(); // Convert the descriptor to a string representation.
|
||||
|
||||
private:
|
||||
friend class NimBLEDescriptorMap;
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEDescriptorMap;
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLE2902;
|
||||
friend class NimBLE2904;
|
||||
friend class NimBLE2902;
|
||||
friend class NimBLE2904;
|
||||
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_handle;
|
||||
NimBLEDescriptorCallbacks* m_pCallbacks;
|
||||
NimBLECharacteristic* m_pCharacteristic;
|
||||
uint8_t m_properties;
|
||||
attr_value_t m_value;
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_handle;
|
||||
NimBLEDescriptorCallbacks* m_pCallbacks;
|
||||
NimBLECharacteristic* m_pCharacteristic;
|
||||
uint8_t m_properties;
|
||||
attr_value_t m_value;
|
||||
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
void setHandle(uint16_t handle);
|
||||
void setHandle(uint16_t handle);
|
||||
}; // BLEDescriptor
|
||||
|
||||
|
||||
|
@ -93,9 +96,11 @@ private:
|
|||
*/
|
||||
class NimBLEDescriptorCallbacks {
|
||||
public:
|
||||
virtual ~NimBLEDescriptorCallbacks();
|
||||
virtual void onRead(NimBLEDescriptor* pDescriptor);
|
||||
virtual void onWrite(NimBLEDescriptor* pDescriptor);
|
||||
virtual ~NimBLEDescriptorCallbacks();
|
||||
virtual void onRead(NimBLEDescriptor* pDescriptor);
|
||||
virtual void onWrite(NimBLEDescriptor* pDescriptor);
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */
|
|
@ -13,6 +13,10 @@
|
|||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLEDescriptor.h"
|
||||
|
||||
|
@ -23,7 +27,7 @@
|
|||
* @return The descriptor. If not present, then nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) {
|
||||
return getByUUID(NimBLEUUID(uuid));
|
||||
return getByUUID(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,13 +36,13 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) {
|
|||
* @param [in] UUID The UUID to look up the descriptor.
|
||||
* @return The descriptor. If not present, then nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(NimBLEUUID uuid) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
} // getByUUID
|
||||
|
||||
|
||||
|
@ -49,7 +53,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(NimBLEUUID uuid) {
|
|||
*/
|
||||
/*
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) {
|
||||
return m_handleMap.at(handle);
|
||||
return m_handleMap.at(handle);
|
||||
} // getByHandle
|
||||
*/
|
||||
|
||||
|
@ -60,7 +64,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByHandle(uint16_t handle) {
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor){
|
||||
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid));
|
||||
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid));
|
||||
} // setByUUID
|
||||
|
||||
|
||||
|
@ -71,8 +75,8 @@ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescrip
|
|||
* @param [in] characteristic The descriptor to cache.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEDescriptorMap::setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor) {
|
||||
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString()));
|
||||
void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) {
|
||||
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString()));
|
||||
} // setByUUID
|
||||
|
||||
|
||||
|
@ -84,7 +88,7 @@ void NimBLEDescriptorMap::setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescript
|
|||
*/
|
||||
/*
|
||||
void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor) {
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLEDescriptor*>(handle, pDescriptor));
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLEDescriptor*>(handle, pDescriptor));
|
||||
} // setByHandle
|
||||
*/
|
||||
|
||||
|
@ -93,7 +97,7 @@ void NimBLEDescriptorMap::setByHandle(uint16_t handle, NimBLEDescriptor* pDescri
|
|||
* @brief Get the number of descriptors in the map.
|
||||
*/
|
||||
uint8_t NimBLEDescriptorMap::getSize() {
|
||||
return (uint8_t)m_uuidMap.size();
|
||||
return (uint8_t)m_uuidMap.size();
|
||||
} // getSize
|
||||
|
||||
|
||||
|
@ -102,18 +106,18 @@ uint8_t NimBLEDescriptorMap::getSize() {
|
|||
* @return A string representation of the descriptor map.
|
||||
*/
|
||||
std::string NimBLEDescriptorMap::toString() {
|
||||
std::string res;
|
||||
char hex[5];
|
||||
int count = 0;
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return res;
|
||||
std::string res;
|
||||
char hex[5];
|
||||
int count = 0;
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (count > 0) {res += "\n";}
|
||||
snprintf(hex, sizeof(hex), "%04x", myPair.first->getHandle());
|
||||
count++;
|
||||
res += "handle: 0x";
|
||||
res += hex;
|
||||
res += ", uuid: " + myPair.first->getUUID().toString();
|
||||
}
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -122,11 +126,11 @@ std::string NimBLEDescriptorMap::toString() {
|
|||
* @return The first descriptor in the map.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getFirst() {
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEDescriptor* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEDescriptor* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getFirst
|
||||
|
||||
|
||||
|
@ -135,9 +139,11 @@ NimBLEDescriptor* NimBLEDescriptorMap::getFirst() {
|
|||
* @return The next descriptor in the map.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLEDescriptorMap::getNext() {
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEDescriptor* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEDescriptor* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getNext
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -14,6 +14,7 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#include "NimBLEDevice.h"
|
||||
#include "NimBLEUtils.h"
|
||||
|
||||
|
@ -39,38 +40,37 @@ static const char* LOG_TAG = "NimBLEDevice";
|
|||
/**
|
||||
* Singletons for the NimBLEDevice.
|
||||
*/
|
||||
bool NimBLEDevice_initialized = false;
|
||||
bool initialized = false;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
|
||||
#endif
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
||||
#endif
|
||||
uint32_t NimBLEDevice::m_passkey = 123456;
|
||||
bool NimBLEDevice::m_synced = false;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
#endif
|
||||
|
||||
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
||||
ble_gap_event_listener NimBLEDevice::m_listener;
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||
#endif
|
||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||
|
||||
//std::map<uint16_t, conn_status_t> BLEDevice::m_connectedClientsMap;
|
||||
|
||||
//gattc_event_handler BLEDevice::m_customGattcHandler = nullptr;
|
||||
//gatts_event_handler BLEDevice::m_customGattsHandler = nullptr;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a new instance of a server.
|
||||
* @return A new instance of the server.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/* STATIC */ NimBLEServer* NimBLEDevice::createServer() {
|
||||
/*#ifndef CONFIG_GATTS_ENABLE // Check that BLE GATTS is enabled in make menuconfig
|
||||
NIMBLE_LOGE(LOG_TAG, "BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined");
|
||||
abort();
|
||||
#endif // CONFIG_GATTS_ENABLE
|
||||
*/
|
||||
if(NimBLEDevice::m_pServer == nullptr) {
|
||||
NimBLEDevice::m_pServer = new NimBLEServer();
|
||||
ble_gatts_reset();
|
||||
ble_gatts_reset();
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
}
|
||||
|
@ -79,22 +79,34 @@ NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
|||
} // createServer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the instance of the server.
|
||||
* @return A pointer to the server instance.
|
||||
*/
|
||||
/* STATIC */ NimBLEServer* NimBLEDevice::getServer() {
|
||||
return m_pServer;
|
||||
} // getServer
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
||||
if(m_bleAdvertising == nullptr) {
|
||||
m_bleAdvertising = new NimBLEAdvertising();
|
||||
}
|
||||
return m_bleAdvertising;
|
||||
if(m_bleAdvertising == nullptr) {
|
||||
m_bleAdvertising = new NimBLEAdvertising();
|
||||
}
|
||||
return m_bleAdvertising;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEDevice::startAdvertising() {
|
||||
getAdvertising()->start();
|
||||
getAdvertising()->start();
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
void NimBLEDevice::stopAdvertising() {
|
||||
getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
|
||||
|
||||
/**
|
||||
|
@ -102,19 +114,21 @@ void NimBLEDevice::stopAdvertising() {
|
|||
* @return The scanning object reference. This is a singleton object. The caller should not
|
||||
* try and release/delete it.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
/* STATIC */ NimBLEScan* NimBLEDevice::getScan() {
|
||||
if (m_pScan == nullptr) {
|
||||
m_pScan = new NimBLEScan();
|
||||
}
|
||||
return m_pScan;
|
||||
} // getScan
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
/**
|
||||
* @brief Creates a new client object and maintains a list of all client objects
|
||||
* each client can connect to 1 peripheral device.
|
||||
* @return A reference to the new client object.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
/* STATIC */ NimBLEClient* NimBLEDevice::createClient() {
|
||||
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)",
|
||||
|
@ -202,7 +216,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
* @param [in] a NimBLEAddress of the peer to search for.
|
||||
* @return A reference pointer to the client with the peer address.
|
||||
*/
|
||||
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(NimBLEAddress peer_addr) {
|
||||
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) {
|
||||
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
||||
if((*it)->getPeerAddress().equals(peer_addr)) {
|
||||
return (*it);
|
||||
|
@ -225,6 +239,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
return nullptr;
|
||||
} // getDisconnectedClient
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the transmission power.
|
||||
|
@ -251,26 +267,26 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) {
|
||||
|
||||
switch(esp_ble_tx_power_get(powerType)) {
|
||||
case ESP_PWR_LVL_N12:
|
||||
return -12;
|
||||
case ESP_PWR_LVL_N9:
|
||||
return -9;
|
||||
case ESP_PWR_LVL_N6:
|
||||
return -6;
|
||||
case ESP_PWR_LVL_N3:
|
||||
return -6;
|
||||
case ESP_PWR_LVL_N0:
|
||||
return 0;
|
||||
case ESP_PWR_LVL_P3:
|
||||
return 3;
|
||||
case ESP_PWR_LVL_P6:
|
||||
return 6;
|
||||
case ESP_PWR_LVL_P9:
|
||||
return 9;
|
||||
default:
|
||||
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
||||
}
|
||||
switch(esp_ble_tx_power_get(powerType)) {
|
||||
case ESP_PWR_LVL_N12:
|
||||
return -12;
|
||||
case ESP_PWR_LVL_N9:
|
||||
return -9;
|
||||
case ESP_PWR_LVL_N6:
|
||||
return -6;
|
||||
case ESP_PWR_LVL_N3:
|
||||
return -6;
|
||||
case ESP_PWR_LVL_N0:
|
||||
return 0;
|
||||
case ESP_PWR_LVL_P3:
|
||||
return 3;
|
||||
case ESP_PWR_LVL_P6:
|
||||
return 6;
|
||||
case ESP_PWR_LVL_P9:
|
||||
return 9;
|
||||
default:
|
||||
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
||||
}
|
||||
} // setPower
|
||||
|
||||
|
||||
|
@ -340,9 +356,12 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
m_synced = false;
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
if(m_pScan != nullptr) {
|
||||
m_pScan->onHostReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Not needed
|
||||
if(m_pServer != nullptr) {
|
||||
m_pServer->onHostReset();
|
||||
|
@ -352,9 +371,12 @@ void NimBLEDevice::stopAdvertising() {
|
|||
(*it)->onHostReset();
|
||||
}
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
if(m_bleAdvertising != nullptr) {
|
||||
m_bleAdvertising->onHostReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
|
||||
NimBLEUtils::returnCodeToString(reason));
|
||||
|
@ -379,14 +401,20 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
m_synced = true;
|
||||
|
||||
if(m_pScan != nullptr) {
|
||||
// Restart scanning with the last values sent, allow to clear results.
|
||||
m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB);
|
||||
}
|
||||
if(initialized) {
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
if(m_pScan != nullptr) {
|
||||
// Restart scanning with the last values sent, allow to clear results.
|
||||
m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_bleAdvertising != nullptr) {
|
||||
// Restart advertisng, parameters should already be set.
|
||||
m_bleAdvertising->start();
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
if(m_bleAdvertising != nullptr) {
|
||||
// Restart advertisng, parameters should already be set.
|
||||
m_bleAdvertising->start();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // onSync
|
||||
|
||||
|
@ -408,10 +436,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
* @brief Initialize the %BLE environment.
|
||||
* @param deviceName The device name of the device.
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::init(std::string deviceName) {
|
||||
if(!NimBLEDevice_initialized){
|
||||
NimBLEDevice_initialized = true; // Set the initialization flag to ensure we are only initialized once.
|
||||
|
||||
/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) {
|
||||
if(!initialized){
|
||||
int rc=0;
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
|
@ -459,7 +485,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
while(!m_synced){
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
//vTaskDelay(200 / portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue.
|
||||
|
||||
initialized = true; // Set the initialization flag to ensure we are only initialized once.
|
||||
} // init
|
||||
|
||||
|
||||
|
@ -476,7 +503,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||
}
|
||||
|
||||
NimBLEDevice_initialized = false;
|
||||
initialized = false;
|
||||
m_synced = false;
|
||||
}
|
||||
} // deinit
|
||||
|
||||
|
@ -485,7 +513,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
* @brief Check if the initialization is complete.
|
||||
*/
|
||||
bool NimBLEDevice::getInitialized() {
|
||||
return NimBLEDevice_initialized;
|
||||
return initialized;
|
||||
} // getInitialized
|
||||
|
||||
|
||||
|
@ -610,7 +638,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
* @brief Check if the device address is on our ignore list.
|
||||
* @return True if ignoring.
|
||||
*/
|
||||
/*STATIC*/ bool NimBLEDevice::isIgnored(NimBLEAddress address) {
|
||||
/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) {
|
||||
for(auto &it : m_ignoreList) {
|
||||
if(it.equals(address)){
|
||||
return true;
|
||||
|
@ -625,7 +653,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
* @brief Add a device to the ignore list.
|
||||
* @param Address of the device we want to ignore.
|
||||
*/
|
||||
/*STATIC*/ void NimBLEDevice::addIgnored(NimBLEAddress address) {
|
||||
/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) {
|
||||
m_ignoreList.push_back(address);
|
||||
}
|
||||
|
||||
|
@ -634,7 +662,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
* @brief Remove a device from the ignore list.
|
||||
* @param Address of the device we want to remove from the list.
|
||||
*/
|
||||
/*STATIC*/void NimBLEDevice::removeIgnored(NimBLEAddress address) {
|
||||
/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) {
|
||||
for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) {
|
||||
if((*it).equals(address)){
|
||||
m_ignoreList.erase(it);
|
||||
|
@ -659,20 +687,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
|
|||
} // setCustomGapHandler
|
||||
|
||||
|
||||
/**
|
||||
* @brief Backward compatibility for bluedroid gatt events.
|
||||
* NimBLe does not send GATT events
|
||||
*/
|
||||
/*
|
||||
void BLEDevice::setCustomGattcHandler(gattc_event_handler handler) {
|
||||
setCustomGapHandler(handler);
|
||||
}
|
||||
|
||||
void BLEDevice::setCustomGattsHandler(gatts_event_handler handler) {
|
||||
setCustomGapHandler(handler);
|
||||
}
|
||||
*/
|
||||
/**********************************************************/
|
||||
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
|
|
@ -17,11 +17,27 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#include "NimBLEScan.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#include "NimBLEAdvertising.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#include "NimBLEClient.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#include "NimBLEServer.h"
|
||||
#endif
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEAddress.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
|
||||
|
@ -50,11 +66,11 @@
|
|||
#define BLEAdvertising NimBLEAdvertising
|
||||
#define BLEServerCallbacks NimBLEServerCallbacks
|
||||
#define BLECharacteristicCallbacks NimBLECharacteristicCallbacks
|
||||
#define BLEAdvertisementData NimBLEAdvertisementData
|
||||
#define BLEDescriptor NimBLEDescriptor
|
||||
#define BLE2902 NimBLE2902
|
||||
#define BLE2904 NimBLE2904
|
||||
#define BLEDescriptorCallbacks NimBLEDescriptorCallbacks
|
||||
#define BLEAdvertisementData NimBLEAdvertisementData
|
||||
#define BLEDescriptor NimBLEDescriptor
|
||||
#define BLE2902 NimBLE2902
|
||||
#define BLE2904 NimBLE2904
|
||||
#define BLEDescriptorCallbacks NimBLEDescriptorCallbacks
|
||||
#define BLEBeacon NimBLEBeacon
|
||||
#define BLEEddystoneTLM NimBLEEddystoneTLM
|
||||
#define BLEEddystoneURL NimBLEEddystoneURL
|
||||
|
@ -69,24 +85,28 @@
|
|||
* @brief BLE functions.
|
||||
*/
|
||||
typedef int (*gap_event_handler)(ble_gap_event *event, void *arg);
|
||||
//typedef void (*gattc_event_handler)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param);
|
||||
//typedef void (*gatts_event_handler)(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param);
|
||||
|
||||
extern "C" void ble_store_config_init(void);
|
||||
|
||||
class NimBLEDevice {
|
||||
public:
|
||||
static void init(std::string deviceName); // Initialize the local BLE environment.
|
||||
static void init(const std::string &deviceName);
|
||||
static void deinit();
|
||||
static bool getInitialized();
|
||||
static NimBLEAddress getAddress();
|
||||
static std::string toString();
|
||||
static NimBLEScan* getScan(); // Get the scan object
|
||||
static NimBLEClient* createClient();
|
||||
static NimBLEServer* createServer();
|
||||
static bool deleteClient(NimBLEClient* pClient);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* getScan();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
static NimBLEServer* createServer();
|
||||
static NimBLEServer* getServer();
|
||||
#endif
|
||||
|
||||
static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
static void setCustomGapHandler(gap_event_handler handler);
|
||||
static void setSecurityAuth(bool bonding, bool mitm, bool sc);
|
||||
static void setSecurityAuth(uint8_t auth_req);
|
||||
|
@ -98,39 +118,69 @@ public:
|
|||
static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks);
|
||||
static int setMTU(uint16_t mtu);
|
||||
static uint16_t getMTU();
|
||||
static bool isIgnored(NimBLEAddress address);
|
||||
static void addIgnored(NimBLEAddress address);
|
||||
static void removeIgnored(NimBLEAddress address);
|
||||
static bool isIgnored(const NimBLEAddress &address);
|
||||
static void addIgnored(const NimBLEAddress &address);
|
||||
static void removeIgnored(const NimBLEAddress &address);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
static void startAdvertising();
|
||||
static void stopAdvertising();
|
||||
static void startAdvertising();
|
||||
static void stopAdvertising();
|
||||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
static NimBLEClient* createClient();
|
||||
static bool deleteClient(NimBLEClient* pClient);
|
||||
static NimBLEClient* getClientByID(uint16_t conn_id);
|
||||
static NimBLEClient* getClientByPeerAddress(NimBLEAddress peer_addr);
|
||||
static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr);
|
||||
static NimBLEClient* getDisconnectedClient();
|
||||
static size_t getClientListSize();
|
||||
static std::list<NimBLEClient*>* getClientList();
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class NimBLEServer;
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
friend class NimBLEClient;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
friend class NimBLEScan;
|
||||
friend class NimBLEAdvertising;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLECharacteristic;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
friend class NimBLEAdvertising;
|
||||
#endif
|
||||
|
||||
static void onReset(int reason);
|
||||
static void onSync(void);
|
||||
static void host_task(void *param);
|
||||
static int startSecurity( uint16_t conn_id);
|
||||
static int startSecurity(uint16_t conn_id);
|
||||
static bool m_synced;
|
||||
|
||||
static bool m_synced;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* m_pScan;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
static NimBLEServer* m_pServer;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* m_bleAdvertising;
|
||||
static ble_gap_event_listener m_listener;
|
||||
static uint32_t m_passkey;
|
||||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
static std::list <NimBLEClient*> m_cList;
|
||||
#endif
|
||||
static std::list <NimBLEAddress> m_ignoreList;
|
||||
static NimBLESecurityCallbacks* m_securityCallbacks;
|
||||
static uint32_t m_passkey;
|
||||
static ble_gap_event_listener m_listener;
|
||||
|
||||
public:
|
||||
static gap_event_handler m_customGapHandler;
|
||||
|
|
|
@ -26,41 +26,41 @@ static const char LOG_TAG[] = "NimBLEEddystoneTLM";
|
|||
|
||||
|
||||
NimBLEEddystoneTLM::NimBLEEddystoneTLM() {
|
||||
beaconUUID = 0xFEAA;
|
||||
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
|
||||
m_eddystoneData.version = 0;
|
||||
m_eddystoneData.volt = 3300; // 3300mV = 3.3V
|
||||
m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format
|
||||
m_eddystoneData.advCount = 0;
|
||||
m_eddystoneData.tmil = 0;
|
||||
beaconUUID = 0xFEAA;
|
||||
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
|
||||
m_eddystoneData.version = 0;
|
||||
m_eddystoneData.volt = 3300; // 3300mV = 3.3V
|
||||
m_eddystoneData.temp = (uint16_t) ((float) 23.00 * 256); // 8.8 fixed format
|
||||
m_eddystoneData.advCount = 0;
|
||||
m_eddystoneData.tmil = 0;
|
||||
} // NimBLEEddystoneTLM
|
||||
|
||||
std::string NimBLEEddystoneTLM::getData() {
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
} // getData
|
||||
|
||||
NimBLEUUID NimBLEEddystoneTLM::getUUID() {
|
||||
return NimBLEUUID(beaconUUID);
|
||||
return NimBLEUUID(beaconUUID);
|
||||
} // getUUID
|
||||
|
||||
uint8_t NimBLEEddystoneTLM::getVersion() {
|
||||
return m_eddystoneData.version;
|
||||
return m_eddystoneData.version;
|
||||
} // getVersion
|
||||
|
||||
uint16_t NimBLEEddystoneTLM::getVolt() {
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
|
||||
} // getVolt
|
||||
|
||||
float NimBLEEddystoneTLM::getTemp() {
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
|
||||
} // getTemp
|
||||
|
||||
uint32_t NimBLEEddystoneTLM::getCount() {
|
||||
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
|
||||
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
|
||||
} // getCount
|
||||
|
||||
uint32_t NimBLEEddystoneTLM::getTime() {
|
||||
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
|
||||
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
|
||||
} // getTime
|
||||
|
||||
std::string NimBLEEddystoneTLM::toString() {
|
||||
|
@ -116,37 +116,37 @@ std::string NimBLEEddystoneTLM::toString() {
|
|||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setData(std::string data) {
|
||||
if (data.length() != sizeof(m_eddystoneData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||
void NimBLEEddystoneTLM::setData(const std::string &data) {
|
||||
if (data.length() != sizeof(m_eddystoneData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||
data.length(), sizeof(m_eddystoneData));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
memcpy(&m_eddystoneData, data.data(), data.length());
|
||||
} // setData
|
||||
|
||||
void NimBLEEddystoneTLM::setUUID(NimBLEUUID l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
} // setUUID
|
||||
|
||||
void NimBLEEddystoneTLM::setVersion(uint8_t version) {
|
||||
m_eddystoneData.version = version;
|
||||
m_eddystoneData.version = version;
|
||||
} // setVersion
|
||||
|
||||
void NimBLEEddystoneTLM::setVolt(uint16_t volt) {
|
||||
m_eddystoneData.volt = volt;
|
||||
m_eddystoneData.volt = volt;
|
||||
} // setVolt
|
||||
|
||||
void NimBLEEddystoneTLM::setTemp(float temp) {
|
||||
m_eddystoneData.temp = (uint16_t)temp;
|
||||
m_eddystoneData.temp = (uint16_t)temp;
|
||||
} // setTemp
|
||||
|
||||
void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
|
||||
m_eddystoneData.advCount = advCount;
|
||||
m_eddystoneData.advCount = advCount;
|
||||
} // setCount
|
||||
|
||||
void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
|
||||
m_eddystoneData.tmil = tmil;
|
||||
m_eddystoneData.tmil = tmil;
|
||||
} // setTime
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,33 +27,33 @@
|
|||
*/
|
||||
class NimBLEEddystoneTLM {
|
||||
public:
|
||||
NimBLEEddystoneTLM();
|
||||
std::string getData();
|
||||
NimBLEUUID getUUID();
|
||||
uint8_t getVersion();
|
||||
uint16_t getVolt();
|
||||
float getTemp();
|
||||
uint32_t getCount();
|
||||
uint32_t getTime();
|
||||
std::string toString();
|
||||
void setData(std::string data);
|
||||
void setUUID(NimBLEUUID l_uuid);
|
||||
void setVersion(uint8_t version);
|
||||
void setVolt(uint16_t volt);
|
||||
void setTemp(float temp);
|
||||
void setCount(uint32_t advCount);
|
||||
void setTime(uint32_t tmil);
|
||||
NimBLEEddystoneTLM();
|
||||
std::string getData();
|
||||
NimBLEUUID getUUID();
|
||||
uint8_t getVersion();
|
||||
uint16_t getVolt();
|
||||
float getTemp();
|
||||
uint32_t getCount();
|
||||
uint32_t getTime();
|
||||
std::string toString();
|
||||
void setData(const std::string &data);
|
||||
void setUUID(const NimBLEUUID &l_uuid);
|
||||
void setVersion(uint8_t version);
|
||||
void setVolt(uint16_t volt);
|
||||
void setTemp(float temp);
|
||||
void setCount(uint32_t advCount);
|
||||
void setTime(uint32_t tmil);
|
||||
|
||||
private:
|
||||
uint16_t beaconUUID;
|
||||
struct {
|
||||
uint8_t frameType;
|
||||
uint8_t version;
|
||||
uint16_t volt;
|
||||
uint16_t temp;
|
||||
uint32_t advCount;
|
||||
uint32_t tmil;
|
||||
} __attribute__((packed)) m_eddystoneData;
|
||||
uint16_t beaconUUID;
|
||||
struct {
|
||||
uint8_t frameType;
|
||||
uint8_t version;
|
||||
uint16_t volt;
|
||||
uint16_t temp;
|
||||
uint32_t advCount;
|
||||
uint32_t tmil;
|
||||
} __attribute__((packed)) m_eddystoneData;
|
||||
|
||||
}; // NimBLEEddystoneTLM
|
||||
|
||||
|
|
|
@ -22,102 +22,102 @@
|
|||
static const char LOG_TAG[] = "NimBLEEddystoneURL";
|
||||
|
||||
NimBLEEddystoneURL::NimBLEEddystoneURL() {
|
||||
beaconUUID = 0xFEAA;
|
||||
lengthURL = 0;
|
||||
m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE;
|
||||
m_eddystoneData.advertisedTxPower = 0;
|
||||
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
|
||||
beaconUUID = 0xFEAA;
|
||||
lengthURL = 0;
|
||||
m_eddystoneData.frameType = EDDYSTONE_URL_FRAME_TYPE;
|
||||
m_eddystoneData.advertisedTxPower = 0;
|
||||
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
|
||||
} // BLEEddystoneURL
|
||||
|
||||
std::string NimBLEEddystoneURL::getData() {
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
} // getData
|
||||
|
||||
NimBLEUUID NimBLEEddystoneURL::getUUID() {
|
||||
return NimBLEUUID(beaconUUID);
|
||||
return NimBLEUUID(beaconUUID);
|
||||
} // getUUID
|
||||
|
||||
int8_t NimBLEEddystoneURL::getPower() {
|
||||
return m_eddystoneData.advertisedTxPower;
|
||||
return m_eddystoneData.advertisedTxPower;
|
||||
} // getPower
|
||||
|
||||
std::string NimBLEEddystoneURL::getURL() {
|
||||
return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url));
|
||||
return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url));
|
||||
} // getURL
|
||||
|
||||
std::string NimBLEEddystoneURL::getDecodedURL() {
|
||||
std::string decodedURL = "";
|
||||
std::string decodedURL = "";
|
||||
|
||||
switch (m_eddystoneData.url[0]) {
|
||||
case 0x00:
|
||||
decodedURL += "http://www.";
|
||||
break;
|
||||
case 0x01:
|
||||
decodedURL += "https://www.";
|
||||
break;
|
||||
case 0x02:
|
||||
decodedURL += "http://";
|
||||
break;
|
||||
case 0x03:
|
||||
decodedURL += "https://";
|
||||
break;
|
||||
default:
|
||||
decodedURL += m_eddystoneData.url[0];
|
||||
}
|
||||
switch (m_eddystoneData.url[0]) {
|
||||
case 0x00:
|
||||
decodedURL += "http://www.";
|
||||
break;
|
||||
case 0x01:
|
||||
decodedURL += "https://www.";
|
||||
break;
|
||||
case 0x02:
|
||||
decodedURL += "http://";
|
||||
break;
|
||||
case 0x03:
|
||||
decodedURL += "https://";
|
||||
break;
|
||||
default:
|
||||
decodedURL += m_eddystoneData.url[0];
|
||||
}
|
||||
|
||||
for (int i = 1; i < lengthURL; i++) {
|
||||
if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) {
|
||||
decodedURL += m_eddystoneData.url[i];
|
||||
} else {
|
||||
switch (m_eddystoneData.url[i]) {
|
||||
case 0x00:
|
||||
decodedURL += ".com/";
|
||||
break;
|
||||
case 0x01:
|
||||
decodedURL += ".org/";
|
||||
break;
|
||||
case 0x02:
|
||||
decodedURL += ".edu/";
|
||||
break;
|
||||
case 0x03:
|
||||
decodedURL += ".net/";
|
||||
break;
|
||||
case 0x04:
|
||||
decodedURL += ".info/";
|
||||
break;
|
||||
case 0x05:
|
||||
decodedURL += ".biz/";
|
||||
break;
|
||||
case 0x06:
|
||||
decodedURL += ".gov/";
|
||||
break;
|
||||
case 0x07:
|
||||
decodedURL += ".com";
|
||||
break;
|
||||
case 0x08:
|
||||
decodedURL += ".org";
|
||||
break;
|
||||
case 0x09:
|
||||
decodedURL += ".edu";
|
||||
break;
|
||||
case 0x0A:
|
||||
decodedURL += ".net";
|
||||
break;
|
||||
case 0x0B:
|
||||
decodedURL += ".info";
|
||||
break;
|
||||
case 0x0C:
|
||||
decodedURL += ".biz";
|
||||
break;
|
||||
case 0x0D:
|
||||
decodedURL += ".gov";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodedURL;
|
||||
for (int i = 1; i < lengthURL; i++) {
|
||||
if (m_eddystoneData.url[i] > 33 && m_eddystoneData.url[i] < 127) {
|
||||
decodedURL += m_eddystoneData.url[i];
|
||||
} else {
|
||||
switch (m_eddystoneData.url[i]) {
|
||||
case 0x00:
|
||||
decodedURL += ".com/";
|
||||
break;
|
||||
case 0x01:
|
||||
decodedURL += ".org/";
|
||||
break;
|
||||
case 0x02:
|
||||
decodedURL += ".edu/";
|
||||
break;
|
||||
case 0x03:
|
||||
decodedURL += ".net/";
|
||||
break;
|
||||
case 0x04:
|
||||
decodedURL += ".info/";
|
||||
break;
|
||||
case 0x05:
|
||||
decodedURL += ".biz/";
|
||||
break;
|
||||
case 0x06:
|
||||
decodedURL += ".gov/";
|
||||
break;
|
||||
case 0x07:
|
||||
decodedURL += ".com";
|
||||
break;
|
||||
case 0x08:
|
||||
decodedURL += ".org";
|
||||
break;
|
||||
case 0x09:
|
||||
decodedURL += ".edu";
|
||||
break;
|
||||
case 0x0A:
|
||||
decodedURL += ".net";
|
||||
break;
|
||||
case 0x0B:
|
||||
decodedURL += ".info";
|
||||
break;
|
||||
case 0x0C:
|
||||
decodedURL += ".biz";
|
||||
break;
|
||||
case 0x0D:
|
||||
decodedURL += ".gov";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return decodedURL;
|
||||
} // getDecodedURL
|
||||
|
||||
|
||||
|
@ -125,30 +125,30 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
|
|||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setData(std::string data) {
|
||||
if (data.length() > sizeof(m_eddystoneData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d",
|
||||
void NimBLEEddystoneURL::setData(const std::string &data) {
|
||||
if (data.length() > sizeof(m_eddystoneData)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d",
|
||||
data.length(), sizeof(m_eddystoneData));
|
||||
return;
|
||||
}
|
||||
memset(&m_eddystoneData, 0, sizeof(m_eddystoneData));
|
||||
memcpy(&m_eddystoneData, data.data(), data.length());
|
||||
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
|
||||
return;
|
||||
}
|
||||
memset(&m_eddystoneData, 0, sizeof(m_eddystoneData));
|
||||
memcpy(&m_eddystoneData, data.data(), data.length());
|
||||
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
|
||||
} // setData
|
||||
|
||||
void NimBLEEddystoneURL::setUUID(NimBLEUUID l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
} // setUUID
|
||||
|
||||
void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) {
|
||||
m_eddystoneData.advertisedTxPower = advertisedTxPower;
|
||||
m_eddystoneData.advertisedTxPower = advertisedTxPower;
|
||||
} // setPower
|
||||
|
||||
void NimBLEEddystoneURL::setURL(std::string url) {
|
||||
void NimBLEEddystoneURL::setURL(const std::string &url) {
|
||||
if (url.length() > sizeof(m_eddystoneData.url)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
|
||||
url.length(), sizeof(m_eddystoneData.url));
|
||||
return;
|
||||
return;
|
||||
}
|
||||
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
|
||||
memcpy(m_eddystoneData.url, url.data(), url.length());
|
||||
|
|
|
@ -27,25 +27,25 @@
|
|||
*/
|
||||
class NimBLEEddystoneURL {
|
||||
public:
|
||||
NimBLEEddystoneURL();
|
||||
std::string getData();
|
||||
NimBLEUUID getUUID();
|
||||
int8_t getPower();
|
||||
std::string getURL();
|
||||
std::string getDecodedURL();
|
||||
void setData(std::string data);
|
||||
void setUUID(NimBLEUUID l_uuid);
|
||||
void setPower(int8_t advertisedTxPower);
|
||||
void setURL(std::string url);
|
||||
NimBLEEddystoneURL();
|
||||
std::string getData();
|
||||
NimBLEUUID getUUID();
|
||||
int8_t getPower();
|
||||
std::string getURL();
|
||||
std::string getDecodedURL();
|
||||
void setData(const std::string &data);
|
||||
void setUUID(const NimBLEUUID &l_uuid);
|
||||
void setPower(int8_t advertisedTxPower);
|
||||
void setURL(const std::string &url);
|
||||
|
||||
private:
|
||||
uint16_t beaconUUID;
|
||||
uint8_t lengthURL;
|
||||
struct {
|
||||
uint8_t frameType;
|
||||
int8_t advertisedTxPower;
|
||||
uint8_t url[16];
|
||||
} __attribute__((packed)) m_eddystoneData;
|
||||
uint16_t beaconUUID;
|
||||
uint8_t lengthURL;
|
||||
struct {
|
||||
uint8_t frameType;
|
||||
int8_t advertisedTxPower;
|
||||
uint8_t url[16];
|
||||
} __attribute__((packed)) m_eddystoneData;
|
||||
|
||||
}; // NIMBLEEddystoneURL
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLERemoteCharacteristic.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -32,7 +35,9 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
|||
* ble_uuid_any_t uuid;
|
||||
* };
|
||||
*/
|
||||
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) {
|
||||
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService,
|
||||
const struct ble_gatt_chr *chr)
|
||||
{
|
||||
|
||||
switch (chr->uuid.u.type) {
|
||||
case BLE_UUID_TYPE_16:
|
||||
|
@ -48,11 +53,13 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
|||
m_uuid = nullptr;
|
||||
break;
|
||||
}
|
||||
m_handle = chr->val_handle;
|
||||
m_defHandle = chr->def_handle;
|
||||
m_charProp = chr->properties;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
m_handle = chr->val_handle;
|
||||
m_defHandle = chr->def_handle;
|
||||
m_charProp = chr->properties;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
m_rawData = nullptr;
|
||||
m_dataLen = 0;
|
||||
} // NimBLERemoteCharacteristic
|
||||
|
||||
|
||||
|
@ -61,7 +68,9 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
|||
*/
|
||||
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
||||
removeDescriptors(); // Release resources for any descriptor information we may have allocated.
|
||||
if(m_rawData != nullptr) free(m_rawData);
|
||||
if(m_rawData != nullptr) {
|
||||
free(m_rawData);
|
||||
}
|
||||
} // ~NimBLERemoteCharacteristic
|
||||
|
||||
/*
|
||||
|
@ -138,9 +147,12 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
const struct ble_gatt_dsc *dsc,
|
||||
void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", error->status, conn_handle);
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||
|
||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)arg;
|
||||
disc_filter_t *filter = (disc_filter_t*)arg;
|
||||
NimBLEUUID *uuid_filter = (NimBLEUUID*)filter->uuid;
|
||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)filter->attribute;
|
||||
int rc=0;
|
||||
|
||||
// Make sure the discovery is for this device
|
||||
|
@ -150,73 +162,149 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
|||
|
||||
switch (error->status) {
|
||||
case 0: {
|
||||
// Found a descriptor - add it to the map
|
||||
if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion");
|
||||
rc = BLE_HS_EDONE;
|
||||
break;
|
||||
}
|
||||
if(uuid_filter != nullptr) {
|
||||
if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Found");
|
||||
rc = BLE_HS_EDONE;
|
||||
}
|
||||
}
|
||||
// Found a descriptor - add it to the vector
|
||||
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
||||
characteristic->m_descriptorMap.insert(std::pair<std::string, NimBLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor));
|
||||
|
||||
break;
|
||||
}
|
||||
case BLE_HS_EDONE:{
|
||||
/* All descriptors in this characteristic discovered; */
|
||||
characteristic->m_semaphoreGetDescEvt.give(0);
|
||||
rc = 0;
|
||||
characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
if (rc != 0) {
|
||||
|
||||
/** If rc == BLE_HS_EDONE, release the semaphore with a success error code and stop the discovery process.
|
||||
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
||||
* If we get any other error code tell the application to abort by returning non-zero in the semaphore rc.
|
||||
*/
|
||||
if (rc == BLE_HS_EDONE) {
|
||||
characteristic->m_semaphoreGetDescEvt.give(0);
|
||||
} else if(rc != 0) {
|
||||
/* Error; abort discovery. */
|
||||
// pass non-zero to semaphore on error to indicate an error finding descriptors
|
||||
characteristic->m_semaphoreGetDescEvt.give(1);
|
||||
// pass error code to semaphore waiting
|
||||
characteristic->m_semaphoreGetDescEvt.give(rc);
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Populate the descriptors (if any) for this characteristic.
|
||||
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||
|
||||
int rc = 0;
|
||||
//removeDescriptors(); // Remove any existing descriptors.
|
||||
disc_filter_t filter;
|
||||
filter.uuid = uuid_filter;
|
||||
filter.attribute = this;
|
||||
|
||||
m_semaphoreGetDescEvt.take("retrieveDescriptors");
|
||||
|
||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
endHdl,
|
||||
getRemoteService()->getEndHandle(),
|
||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||
this);
|
||||
&filter);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_semaphoreGetDescEvt.give();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) {
|
||||
// if there was an error release the resources
|
||||
//removeDescriptors();
|
||||
if(m_semaphoreGetDescEvt.wait("retrieveDescriptors") != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size());
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size());
|
||||
} // getDescriptors
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the map of descriptors keyed by UUID.
|
||||
* @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor to find.
|
||||
* @return The Remote descriptor (if present) or null if not present.
|
||||
*/
|
||||
std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
|
||||
return &m_descriptorMap;
|
||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||
|
||||
for(auto &it: m_descriptorVector) {
|
||||
if(it->getUUID() == uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
size_t prev_size = m_descriptorVector.size();
|
||||
if(retrieveDescriptors(&uuid)) {
|
||||
if(m_descriptorVector.size() > prev_size) {
|
||||
return m_descriptorVector.back();
|
||||
}
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
||||
return nullptr;
|
||||
} // getDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the vector of found descriptors.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all descriptors for this characteristic retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored descriptors,
|
||||
* if the vector is empty it will retrieve all descriptors for this characteristic
|
||||
* from the peripheral.
|
||||
* @return a pointer to the vector of descriptors for this characteristic.
|
||||
*/
|
||||
std::vector<NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors(bool refresh) {
|
||||
if(refresh) {
|
||||
removeDescriptors();
|
||||
}
|
||||
|
||||
if(m_descriptorVector.empty()) {
|
||||
if (!retrieveDescriptors()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get descriptors");
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGI(LOG_TAG, "Found %d descriptor(s)", m_descriptorVector.size());
|
||||
}
|
||||
}
|
||||
return &m_descriptorVector;
|
||||
} // getDescriptors
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the beginning of the vector of remote descriptor pointers.
|
||||
* @return An iterator to the beginning of the vector of remote descriptor pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::begin() {
|
||||
return m_descriptorVector.begin();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the end of the vector of remote descriptor pointers.
|
||||
* @return An iterator to the end of the vector of remote descriptor pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::end() {
|
||||
return m_descriptorVector.end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the handle for this characteristic.
|
||||
* @return The handle for this characteristic.
|
||||
|
@ -234,25 +322,6 @@ uint16_t NimBLERemoteCharacteristic::getDefHandle() {
|
|||
} // getDefHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor to find.
|
||||
* @return The Remote descriptor (if present) or null if not present.
|
||||
*/
|
||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(NimBLEUUID uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||
std::string v = uuid.toString();
|
||||
for (auto &myPair : m_descriptorMap) {
|
||||
if (myPair.first == v) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
||||
return myPair.second;
|
||||
}
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
||||
return nullptr;
|
||||
} // getDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the remote service associated with this characteristic.
|
||||
* @return The remote service associated with this characteristic.
|
||||
|
@ -315,10 +384,13 @@ uint8_t NimBLERemoteCharacteristic::readUInt8() {
|
|||
* @return The value of the remote characteristic.
|
||||
*/
|
||||
std::string NimBLERemoteCharacteristic::readValue() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", getUUID().toString().c_str(), getHandle(), getHandle());
|
||||
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
|
||||
getUUID().toString().c_str(), getHandle(), getHandle());
|
||||
|
||||
int rc = 0;
|
||||
int retryCount = 1;
|
||||
// Clear the value before reading.
|
||||
m_value = "";
|
||||
|
||||
NimBLEClient* pClient = getRemoteService()->getClient();
|
||||
|
||||
|
@ -331,24 +403,27 @@ std::string NimBLERemoteCharacteristic::readValue() {
|
|||
do {
|
||||
m_semaphoreReadCharEvt.take("readValue");
|
||||
|
||||
rc = ble_gattc_read(pClient->getConnId(), m_handle,
|
||||
NimBLERemoteCharacteristic::onReadCB, this);
|
||||
|
||||
// long read experiment
|
||||
/* rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||
NimBLERemoteCharacteristic::onReadCB, this);
|
||||
*/
|
||||
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||
NimBLERemoteCharacteristic::onReadCB,
|
||||
this);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d", rc);
|
||||
m_semaphoreReadCharEvt.give();
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d, %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_semaphoreReadCharEvt.give(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
rc = m_semaphoreReadCharEvt.wait("readValue");
|
||||
switch(rc){
|
||||
case 0:
|
||||
case BLE_HS_EDONE:
|
||||
rc = 0;
|
||||
break;
|
||||
// Characteristic is not long-readable, return with what we have.
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||
NIMBLE_LOGI(LOG_TAG, "Attribute not long");
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||
|
@ -361,7 +436,7 @@ std::string NimBLERemoteCharacteristic::readValue() {
|
|||
} while(rc != 0 && retryCount--);
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
|
||||
return (rc == 0) ? m_value : "";
|
||||
return m_value;
|
||||
} // readValue
|
||||
|
||||
|
||||
|
@ -374,36 +449,25 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
|
|||
struct ble_gatt_attr *attr, void *arg)
|
||||
{
|
||||
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
||||
uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId();
|
||||
|
||||
// Make sure the discovery is for this device
|
||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
// Make sure the read is for this client
|
||||
if(conn_id != conn_handle) {
|
||||
return 0;
|
||||
}
|
||||
NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||
// long read experiment
|
||||
/* if(attr && (attr->om->om_len >= (ble_att_mtu(characteristic->getRemoteService()->getClient()->getConnId()) - 1))){
|
||||
|
||||
return 0;
|
||||
if(error->status == 0) {
|
||||
if(attr) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||
|
||||
characteristic->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if(characteristic->m_rawData != nullptr) {
|
||||
free(characteristic->m_rawData);
|
||||
}
|
||||
|
||||
if (error->status == 0) {
|
||||
characteristic->m_value = std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||
characteristic->m_rawData = (uint8_t*) calloc(attr->om->om_len, sizeof(uint8_t));
|
||||
memcpy(characteristic->m_rawData, attr->om->om_data, attr->om->om_len);
|
||||
characteristic->m_semaphoreReadCharEvt.give(0);
|
||||
} else {
|
||||
characteristic->m_rawData = nullptr;
|
||||
characteristic->m_value = "";
|
||||
characteristic->m_semaphoreReadCharEvt.give(error->status);
|
||||
}
|
||||
|
||||
// characteristic->m_semaphoreReadCharEvt.give(error->status);
|
||||
return 0; //1
|
||||
// Read complete release semaphore and let the app can continue.
|
||||
characteristic->m_semaphoreReadCharEvt.give(error->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,19 +507,18 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
|
|||
|
||||
|
||||
/**
|
||||
* @brief Delete the descriptors in the descriptor map.
|
||||
* We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
||||
* them. This method does just that.
|
||||
* @brief Delete the descriptors in the descriptor vector.
|
||||
* We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
||||
* them. This method does just that.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLERemoteCharacteristic::removeDescriptors() {
|
||||
// Iterate through all the descriptors releasing their storage and erasing them from the map.
|
||||
for (auto &myPair : m_descriptorMap) {
|
||||
m_descriptorMap.erase(myPair.first);
|
||||
delete myPair.second;
|
||||
// Iterate through all the descriptors releasing their storage and erasing them from the vector.
|
||||
for(auto &it: m_descriptorVector) {
|
||||
delete it;
|
||||
}
|
||||
m_descriptorMap.clear(); // Technically not neeeded, but just to be sure.
|
||||
m_descriptorVector.clear();
|
||||
} // removeCharacteristics
|
||||
|
||||
|
||||
|
@ -477,8 +540,8 @@ std::string NimBLERemoteCharacteristic::toString() {
|
|||
snprintf(val, sizeof(val), "%02x", m_charProp);
|
||||
res += val;
|
||||
|
||||
for (auto &myPair : m_descriptorMap) {
|
||||
res += "\n" + myPair.second->toString();
|
||||
for(auto &it: m_descriptorVector) {
|
||||
res += "\n" + it->toString();
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -491,7 +554,7 @@ std::string NimBLERemoteCharacteristic::toString() {
|
|||
* @param [in] response Do we expect a response?
|
||||
* @return false if not connected or cant perform write for some reason.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::writeValue(std::string newValue, bool response) {
|
||||
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
||||
} // writeValue
|
||||
|
||||
|
@ -516,14 +579,14 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) {
|
|||
* @param [in] response Whether we require a response from the write.
|
||||
* @return false if not connected or cant perform write for some reason.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) {
|
||||
bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) {
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length);
|
||||
|
||||
NimBLEClient* pClient = getRemoteService()->getClient();
|
||||
int rc = 0;
|
||||
int retryCount = 1;
|
||||
// uint16_t mtu;
|
||||
uint16_t mtu;
|
||||
|
||||
// Check to see that we are connected.
|
||||
if (!pClient->isConnected()) {
|
||||
|
@ -531,29 +594,30 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
|
|||
return false;
|
||||
}
|
||||
|
||||
// mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||
|
||||
if(/*!length > mtu &&*/ !response) {
|
||||
// Check if the data length is longer than we can write in 1 connection event.
|
||||
// If so we must do a long write which requires a response.
|
||||
if(length <= mtu && !response) {
|
||||
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
|
||||
return (rc==0);
|
||||
}
|
||||
|
||||
do {
|
||||
m_semaphoreWriteCharEvt.take("writeValue");
|
||||
// long write experiment
|
||||
/* if(length > mtu) {
|
||||
NIMBLE_LOGD(LOG_TAG,"long write");
|
||||
|
||||
if(length > mtu) {
|
||||
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
||||
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
||||
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
||||
NimBLERemoteCharacteristic::onWriteCB,
|
||||
this);
|
||||
} else {
|
||||
*/
|
||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||
data, length,
|
||||
NimBLERemoteCharacteristic::onWriteCB,
|
||||
this);
|
||||
// }
|
||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||
data, length,
|
||||
NimBLERemoteCharacteristic::onWriteCB,
|
||||
this);
|
||||
}
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write characteristic; rc=%d", rc);
|
||||
m_semaphoreWriteCharEvt.give();
|
||||
|
@ -564,6 +628,13 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
|
|||
|
||||
switch(rc){
|
||||
case 0:
|
||||
case BLE_HS_EDONE:
|
||||
rc = 0;
|
||||
break;
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||
NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu);
|
||||
retryCount++;
|
||||
length = mtu;
|
||||
break;
|
||||
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||
|
@ -592,20 +663,14 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
|||
{
|
||||
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
||||
|
||||
// Make sure the discovery is for this device
|
||||
// Make sure the discovery is for this device
|
||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||
|
||||
if (error->status == 0) {
|
||||
|
||||
characteristic->m_semaphoreWriteCharEvt.give(0);
|
||||
} else {
|
||||
|
||||
characteristic->m_semaphoreWriteCharEvt.give(error->status);
|
||||
}
|
||||
characteristic->m_semaphoreWriteCharEvt.give(error->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -613,19 +678,42 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
|||
|
||||
/**
|
||||
* @brief Read raw data from remote characteristic as hex bytes
|
||||
* @return return pointer data read
|
||||
* @return uint8_t pointer to the data read.
|
||||
*/
|
||||
uint8_t* NimBLERemoteCharacteristic::readRawData() {
|
||||
if(m_rawData != nullptr) {
|
||||
free(m_rawData);
|
||||
m_rawData = nullptr;
|
||||
}
|
||||
|
||||
m_dataLen = m_value.length();
|
||||
// If we have data copy it to rawData
|
||||
if(m_dataLen) {
|
||||
m_rawData = (uint8_t*) calloc(m_dataLen, sizeof(uint8_t));
|
||||
memcpy(m_rawData, m_value.data(), m_dataLen);
|
||||
}
|
||||
|
||||
return m_rawData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the length of the data read from the remote characteristic.
|
||||
* @return size_t length of the data in bytes.
|
||||
*/
|
||||
size_t NimBLERemoteCharacteristic::getDataLength() {
|
||||
return m_value.length();
|
||||
}
|
||||
|
||||
|
||||
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
||||
for (auto &dPair : m_descriptorMap) {
|
||||
dPair.second->releaseSemaphores();
|
||||
for (auto &it: m_descriptorVector) {
|
||||
it->releaseSemaphores();
|
||||
}
|
||||
m_semaphoreWriteCharEvt.give(1);
|
||||
m_semaphoreGetDescEvt.give(1);
|
||||
m_semaphoreReadCharEvt.give(1);
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -17,19 +17,20 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
//#include "NimBLEUUID.h"
|
||||
//#include "FreeRTOS.h"
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLERemoteService.h"
|
||||
#include "NimBLERemoteDescriptor.h"
|
||||
|
||||
//#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class NimBLERemoteService;
|
||||
class NimBLERemoteDescriptor;
|
||||
|
||||
|
||||
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
|
||||
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||
uint8_t* pData, size_t length, bool isNotify);
|
||||
|
||||
/**
|
||||
* @brief A model of a remote %BLE characteristic.
|
||||
|
@ -39,46 +40,57 @@ public:
|
|||
~NimBLERemoteCharacteristic();
|
||||
|
||||
// Public member functions
|
||||
bool canBroadcast();
|
||||
bool canIndicate();
|
||||
bool canNotify();
|
||||
bool canRead();
|
||||
bool canWrite();
|
||||
bool canWriteNoResponse();
|
||||
NimBLERemoteDescriptor* getDescriptor(NimBLEUUID uuid);
|
||||
std::map<std::string, NimBLERemoteDescriptor*>* getDescriptors();
|
||||
uint16_t getHandle();
|
||||
uint16_t getDefHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string readValue();
|
||||
uint8_t readUInt8();
|
||||
uint16_t readUInt16();
|
||||
uint32_t readUInt32();
|
||||
bool registerForNotify(notify_callback _callback, bool notifications = true, bool response = true);
|
||||
bool writeValue(uint8_t* data, size_t length, bool response = false);
|
||||
bool writeValue(std::string newValue, bool response = false);
|
||||
bool writeValue(uint8_t newValue, bool response = false);
|
||||
std::string toString();
|
||||
uint8_t* readRawData();
|
||||
NimBLERemoteService* getRemoteService();
|
||||
bool canBroadcast();
|
||||
bool canIndicate();
|
||||
bool canNotify();
|
||||
bool canRead();
|
||||
bool canWrite();
|
||||
bool canWriteNoResponse();
|
||||
std::vector<NimBLERemoteDescriptor*>::iterator begin();
|
||||
std::vector<NimBLERemoteDescriptor*>::iterator end();
|
||||
NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid);
|
||||
std::vector<NimBLERemoteDescriptor*>* getDescriptors(bool refresh = false);
|
||||
uint16_t getHandle();
|
||||
uint16_t getDefHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string readValue();
|
||||
uint8_t readUInt8();
|
||||
uint16_t readUInt16();
|
||||
uint32_t readUInt32();
|
||||
bool registerForNotify(notify_callback _callback,
|
||||
bool notifications = true,
|
||||
bool response = true);
|
||||
bool writeValue(const uint8_t* data,
|
||||
size_t length,
|
||||
bool response = false);
|
||||
bool writeValue(const std::string &newValue,
|
||||
bool response = false);
|
||||
bool writeValue(uint8_t newValue,
|
||||
bool response = false);
|
||||
std::string toString();
|
||||
uint8_t* readRawData();
|
||||
size_t getDataLength();
|
||||
NimBLERemoteService* getRemoteService();
|
||||
|
||||
private:
|
||||
|
||||
NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteservice, const struct ble_gatt_chr *chr);
|
||||
|
||||
friend class NimBLEClient;
|
||||
friend class NimBLERemoteService;
|
||||
friend class NimBLERemoteDescriptor;
|
||||
friend class NimBLEClient;
|
||||
friend class NimBLERemoteService;
|
||||
friend class NimBLERemoteDescriptor;
|
||||
|
||||
// Private member functions
|
||||
void removeDescriptors();
|
||||
bool retrieveDescriptors(uint16_t endHdl);
|
||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
||||
bool retrieveDescriptors(const NimBLEUUID *uuid_filter = nullptr);
|
||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
void releaseSemaphores();
|
||||
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
|
||||
// Private properties
|
||||
NimBLEUUID m_uuid;
|
||||
|
@ -90,11 +102,14 @@ private:
|
|||
FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt");
|
||||
std::string m_value;
|
||||
uint8_t* m_rawData = nullptr;
|
||||
uint8_t* m_rawData;
|
||||
size_t m_dataLen;
|
||||
notify_callback m_notifyCallback;
|
||||
|
||||
// We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID.
|
||||
std::map<std::string, NimBLERemoteDescriptor*> m_descriptorMap;
|
||||
}; // BLERemoteCharacteristic
|
||||
// We maintain a vector of descriptors owned by this characteristic.
|
||||
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
|
||||
}; // NimBLERemoteCharacteristic
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLERemoteDescriptor.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
static const char* LOG_TAG = "NimBLERemoteDescriptor";
|
||||
|
@ -25,7 +29,7 @@ static const char* LOG_TAG = "NimBLERemoteDescriptor";
|
|||
* @param [in] Reference to the struct that contains the descriptor information.
|
||||
*/
|
||||
NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic,
|
||||
const struct ble_gatt_dsc *dsc)
|
||||
const struct ble_gatt_dsc *dsc)
|
||||
{
|
||||
switch (dsc->uuid.u.type) {
|
||||
case BLE_UUID_TYPE_16:
|
||||
|
@ -83,22 +87,26 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
|||
struct ble_gatt_attr *attr, void *arg)
|
||||
{
|
||||
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg;
|
||||
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
|
||||
|
||||
// Make sure the discovery is for this device
|
||||
if(desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
if(conn_id != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||
|
||||
if (error->status == 0) {
|
||||
desc->m_value = std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||
desc->m_semaphoreReadDescrEvt.give(0);
|
||||
} else {
|
||||
desc->m_value = "";
|
||||
desc->m_semaphoreReadDescrEvt.give(error->status);
|
||||
if(error->status == 0){
|
||||
if(attr){
|
||||
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||
|
||||
desc->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Read complete release semaphore and let the app can continue.
|
||||
desc->m_semaphoreReadDescrEvt.give(error->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -106,10 +114,12 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
|||
std::string NimBLERemoteDescriptor::readValue() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
||||
|
||||
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
||||
|
||||
int rc = 0;
|
||||
int retryCount = 1;
|
||||
// Clear the value before reading.
|
||||
m_value = "";
|
||||
|
||||
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
||||
|
||||
// Check to see that we are connected.
|
||||
if (!pClient->isConnected()) {
|
||||
|
@ -120,12 +130,13 @@ std::string NimBLERemoteDescriptor::readValue() {
|
|||
do {
|
||||
m_semaphoreReadDescrEvt.take("ReadDescriptor");
|
||||
|
||||
rc = ble_gattc_read(pClient->getConnId(), m_handle,
|
||||
NimBLERemoteDescriptor::onReadCB, this);
|
||||
|
||||
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||
NimBLERemoteDescriptor::onReadCB,
|
||||
this);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Descriptor read failed, code: %d", rc);
|
||||
m_semaphoreReadDescrEvt.give();
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read descriptor; rc=%d, %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_semaphoreReadDescrEvt.give(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -133,8 +144,14 @@ std::string NimBLERemoteDescriptor::readValue() {
|
|||
|
||||
switch(rc){
|
||||
case 0:
|
||||
case BLE_HS_EDONE:
|
||||
rc = 0;
|
||||
break;
|
||||
// Descriptor is not long-readable, return with what we have.
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||
NIMBLE_LOGI(LOG_TAG, "Attribute not long");
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||
|
@ -146,9 +163,8 @@ std::string NimBLERemoteDescriptor::readValue() {
|
|||
}
|
||||
} while(rc != 0 && retryCount--);
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d, rc: %d", m_value.length(), rc);
|
||||
|
||||
return (rc == 0) ? m_value : "";
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d", m_value.length());
|
||||
return m_value;
|
||||
} // readValue
|
||||
|
||||
|
||||
|
@ -204,18 +220,14 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
|||
{
|
||||
NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)arg;
|
||||
|
||||
// Make sure the discovery is for this device
|
||||
// Make sure the discovery is for this device
|
||||
if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||
|
||||
if (error->status == 0) {
|
||||
descriptor->m_semaphoreDescWrite.give(0);
|
||||
} else {
|
||||
descriptor->m_semaphoreDescWrite.give(error->status);
|
||||
}
|
||||
descriptor->m_semaphoreDescWrite.give(error->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,7 +239,7 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
|||
* @param [in] length The length of the data to send.
|
||||
* @param [in] response True if we expect a response.
|
||||
*/
|
||||
bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response) {
|
||||
bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) {
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str());
|
||||
|
||||
|
@ -235,6 +247,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
|||
|
||||
int rc = 0;
|
||||
int retryCount = 1;
|
||||
uint16_t mtu;
|
||||
|
||||
// Check to see that we are connected.
|
||||
if (!pClient->isConnected()) {
|
||||
|
@ -242,18 +255,31 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!response) {
|
||||
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||
|
||||
// Check if the data length is longer than we can write in 1 connection event.
|
||||
// If so we must do a long write which requires a response.
|
||||
if(length <= mtu && !response) {
|
||||
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
|
||||
return (rc==0);
|
||||
return (rc == 0);
|
||||
}
|
||||
|
||||
do {
|
||||
m_semaphoreDescWrite.take("WriteDescriptor");
|
||||
|
||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||
data, length,
|
||||
NimBLERemoteDescriptor::onWriteCB,
|
||||
this);
|
||||
if(length > mtu) {
|
||||
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
||||
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
||||
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
||||
NimBLERemoteDescriptor::onWriteCB,
|
||||
this);
|
||||
} else {
|
||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||
data, length,
|
||||
NimBLERemoteDescriptor::onWriteCB,
|
||||
this);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write descriptor; rc=%d", rc);
|
||||
m_semaphoreDescWrite.give();
|
||||
|
@ -264,6 +290,13 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
|||
|
||||
switch(rc){
|
||||
case 0:
|
||||
case BLE_HS_EDONE:
|
||||
rc = 0;
|
||||
break;
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||
NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu);
|
||||
retryCount++;
|
||||
length = mtu;
|
||||
break;
|
||||
|
||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||
|
@ -278,7 +311,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
|||
} while(rc != 0 && retryCount--);
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor writeValue, rc: %d",rc);
|
||||
return (rc == 0); //true;
|
||||
return (rc == 0);
|
||||
} // writeValue
|
||||
|
||||
|
||||
|
@ -287,7 +320,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
|||
* @param [in] newValue The data to send to the remote descriptor.
|
||||
* @param [in] response True if we expect a response.
|
||||
*/
|
||||
bool NimBLERemoteDescriptor::writeValue(std::string newValue, bool response) {
|
||||
bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*) newValue.data(), newValue.length(), response);
|
||||
} // writeValue
|
||||
|
||||
|
@ -309,4 +342,6 @@ void NimBLERemoteDescriptor::releaseSemaphores() {
|
|||
m_semaphoreDescWrite.give(1);
|
||||
m_semaphoreReadDescrEvt.give(1);
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLERemoteCharacteristic.h"
|
||||
|
||||
class NimBLERemoteCharacteristic;
|
||||
|
@ -25,34 +28,40 @@ class NimBLERemoteCharacteristic;
|
|||
*/
|
||||
class NimBLERemoteDescriptor {
|
||||
public:
|
||||
uint16_t getHandle();
|
||||
uint16_t getHandle();
|
||||
NimBLERemoteCharacteristic* getRemoteCharacteristic();
|
||||
NimBLEUUID getUUID();
|
||||
std::string readValue(void);
|
||||
uint8_t readUInt8(void);
|
||||
uint16_t readUInt16(void);
|
||||
uint32_t readUInt32(void);
|
||||
std::string toString(void);
|
||||
bool writeValue(uint8_t* data, size_t length, bool response = false);
|
||||
bool writeValue(std::string newValue, bool response = false);
|
||||
bool writeValue(uint8_t newValue, bool response = false);
|
||||
NimBLEUUID getUUID();
|
||||
std::string readValue(void);
|
||||
uint8_t readUInt8(void);
|
||||
uint16_t readUInt16(void);
|
||||
uint32_t readUInt32(void);
|
||||
std::string toString(void);
|
||||
bool writeValue(const uint8_t* data, size_t length, bool response = false);
|
||||
bool writeValue(const std::string &newValue, bool response = false);
|
||||
bool writeValue(uint8_t newValue, bool response = false);
|
||||
|
||||
|
||||
private:
|
||||
friend class NimBLERemoteCharacteristic;
|
||||
NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, const struct ble_gatt_dsc *dsc);
|
||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
||||
void releaseSemaphores();
|
||||
friend class NimBLERemoteCharacteristic;
|
||||
|
||||
uint16_t m_handle; // Server handle of this descriptor.
|
||||
NimBLEUUID m_uuid; // UUID of this descriptor.
|
||||
std::string m_value; // Last received value of the descriptor.
|
||||
NimBLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated.
|
||||
NimBLERemoteDescriptor (NimBLERemoteCharacteristic* pRemoteCharacteristic,
|
||||
const struct ble_gatt_dsc *dsc);
|
||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
void releaseSemaphores();
|
||||
|
||||
uint16_t m_handle;
|
||||
NimBLEUUID m_uuid;
|
||||
std::string m_value;
|
||||
NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
|
||||
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
|
||||
FreeRTOS::Semaphore m_semaphoreDescWrite = FreeRTOS::Semaphore("WriteDescEvt");
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLERemoteService.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -28,7 +31,7 @@ static const char* LOG_TAG = "NimBLERemoteService";
|
|||
*/
|
||||
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) {
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, ">> BLERemoteService()");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> NimBLERemoteService()");
|
||||
m_pClient = pClient;
|
||||
switch (service->uuid.u.type) {
|
||||
case BLE_UUID_TYPE_16:
|
||||
|
@ -46,9 +49,7 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble
|
|||
}
|
||||
m_startHandle = service->start_handle;
|
||||
m_endHandle = service->end_handle;
|
||||
m_haveCharacteristics = false;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< BLERemoteService()");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteService()");
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,6 +62,24 @@ NimBLERemoteService::~NimBLERemoteService() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the beginning of the vector of remote characteristic pointers.
|
||||
* @return An iterator to the beginning of the vector of remote characteristic pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::begin() {
|
||||
return m_characteristicVector.begin();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the end of the vector of remote characteristic pointers.
|
||||
* @return An iterator to the end of the vector of remote characteristic pointers.
|
||||
*/
|
||||
std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::end() {
|
||||
return m_characteristicVector.end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the remote characteristic object for the characteristic UUID.
|
||||
* @param [in] uuid Remote characteristic uuid.
|
||||
|
@ -76,13 +95,17 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
|
|||
* @param [in] uuid Characteristic uuid.
|
||||
* @return Reference to the characteristic object, or nullptr if not found.
|
||||
*/
|
||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(NimBLEUUID uuid) {
|
||||
if (m_haveCharacteristics) {
|
||||
std::string v = uuid.toString();
|
||||
for (auto &myPair : m_characteristicMap) {
|
||||
if (myPair.first == v) {
|
||||
return myPair.second;
|
||||
}
|
||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
for(auto &it: m_characteristicVector) {
|
||||
if(it->getUUID() == uuid) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
size_t prev_size = m_characteristicVector.size();
|
||||
if(retrieveCharacteristics(&uuid)) {
|
||||
if(m_characteristicVector.size() > prev_size) {
|
||||
return m_characteristicVector.back();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +113,33 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(NimBLEUUID uu
|
|||
} // getCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the vector of found characteristics.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all characteristics for this service retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored characteristics,
|
||||
* if the vector is empty it will retrieve all characteristics of this service
|
||||
* from the peripheral.
|
||||
* @return a pointer to the vector of descriptors for this characteristic.
|
||||
*/
|
||||
|
||||
std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics(bool refresh) {
|
||||
if(refresh) {
|
||||
removeCharacteristics();
|
||||
}
|
||||
|
||||
if(m_characteristicVector.empty()) {
|
||||
if (!retrieveCharacteristics()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get characteristics");
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGI(LOG_TAG, "Found %d characteristics", m_characteristicVector.size());
|
||||
}
|
||||
}
|
||||
return &m_characteristicVector;
|
||||
} // getCharacteristics
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback for Characterisic discovery.
|
||||
*/
|
||||
|
@ -97,7 +147,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
|||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d", error->status, conn_handle);
|
||||
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? chr->val_handle : -1);
|
||||
|
||||
NimBLERemoteService *service = (NimBLERemoteService*)arg;
|
||||
int rc=0;
|
||||
|
@ -109,10 +160,9 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
|||
|
||||
switch (error->status) {
|
||||
case 0: {
|
||||
// Found a service - add it to the map
|
||||
// Found a service - add it to the vector
|
||||
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
||||
service->m_characteristicMap.insert(std::pair<std::string, NimBLERemoteCharacteristic*>(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic));
|
||||
service->m_characteristicMapByHandle.insert(std::pair<uint16_t, NimBLERemoteCharacteristic*>(chr->val_handle, pRemoteCharacteristic));
|
||||
service->m_characteristicVector.push_back(pRemoteCharacteristic);
|
||||
break;
|
||||
}
|
||||
case BLE_HS_EDONE:{
|
||||
|
@ -145,7 +195,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
|||
* This function will not return until we have all the characteristics.
|
||||
* @return N/A
|
||||
*/
|
||||
bool NimBLERemoteService::retrieveCharacteristics() {
|
||||
bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
|
||||
|
||||
int rc = 0;
|
||||
|
@ -153,48 +203,28 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
|||
|
||||
m_semaphoreGetCharEvt.take("retrieveCharacteristics");
|
||||
|
||||
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
|
||||
m_startHandle,
|
||||
m_endHandle,
|
||||
NimBLERemoteService::characteristicDiscCB,
|
||||
this);
|
||||
if(uuid_filter == nullptr) {
|
||||
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
|
||||
m_startHandle,
|
||||
m_endHandle,
|
||||
NimBLERemoteService::characteristicDiscCB,
|
||||
this);
|
||||
} else {
|
||||
rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(),
|
||||
m_startHandle,
|
||||
m_endHandle,
|
||||
&uuid_filter->getNative()->u,
|
||||
NimBLERemoteService::characteristicDiscCB,
|
||||
this);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_haveCharacteristics = false;
|
||||
m_semaphoreGetCharEvt.give();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0);
|
||||
if(m_haveCharacteristics){
|
||||
uint16_t endHdl = 0xFFFF;
|
||||
NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics", m_characteristicMapByHandle.size());
|
||||
for (auto it = m_characteristicMapByHandle.cbegin(); it != m_characteristicMapByHandle.cend(); ++it) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle());
|
||||
// The descriptor handle is between this characteristic val_handle and the next ones def_handle
|
||||
// so make the end of the scan at the handle before the next characteristic def_handle
|
||||
|
||||
// Make sure we don't go past the service end handle
|
||||
if(++it != m_characteristicMapByHandle.cend()){
|
||||
NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(),(*it).second->getDefHandle());
|
||||
|
||||
endHdl = (*it).second->getDefHandle()-1;
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGD(LOG_TAG, "END CHARS");
|
||||
endHdl = m_endHandle;
|
||||
}
|
||||
--it;
|
||||
|
||||
//If there is no handles between this characteristic and the next there is no descriptor so skip to the next
|
||||
if((*it).second->getHandle() != endHdl){
|
||||
if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics in service UUID: %s", chars->size(), myPair.first.c_str());
|
||||
}
|
||||
|
||||
if(m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0){
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||
return true;
|
||||
}
|
||||
|
@ -205,24 +235,6 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
|||
} // retrieveCharacteristics
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve a map of all the characteristics of this service.
|
||||
* @return A map of all the characteristics of this service.
|
||||
*/
|
||||
std::map<std::string, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics() {
|
||||
return &m_characteristicMap;
|
||||
} // getCharacteristics
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve a map of all the characteristics of this service.
|
||||
* @return A map of all the characteristics of this service.
|
||||
*/
|
||||
std::map<uint16_t, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristicsByHandle() {
|
||||
return &m_characteristicMapByHandle;
|
||||
} // getCharacteristicsByHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the client associated with this service.
|
||||
* @return A reference to the client associated with this service.
|
||||
|
@ -261,7 +273,7 @@ NimBLEUUID NimBLERemoteService::getUUID() {
|
|||
* @param [in] characteristicUuid The characteristic to read.
|
||||
* @returns a string containing the value or an empty string if not found or error.
|
||||
*/
|
||||
std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) {
|
||||
std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str());
|
||||
|
||||
std::string ret = "";
|
||||
|
@ -282,7 +294,7 @@ std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) {
|
|||
* @param [in] value The value to set.
|
||||
* @returns true on success, false if not found or error
|
||||
*/
|
||||
bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string value) {
|
||||
bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const std::string &value) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str());
|
||||
|
||||
bool ret = false;
|
||||
|
@ -298,20 +310,17 @@ bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string va
|
|||
|
||||
|
||||
/**
|
||||
* @brief Delete the characteristics in the characteristics map.
|
||||
* We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
||||
* them. This method does just that.
|
||||
* @brief Delete the characteristics in the characteristics vector.
|
||||
* We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleting
|
||||
* them. This method does just that.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLERemoteService::removeCharacteristics() {
|
||||
m_characteristicMap.clear(); // Clear the map
|
||||
|
||||
for (auto &myPair : m_characteristicMapByHandle) {
|
||||
delete myPair.second;
|
||||
for(auto &it: m_characteristicVector) {
|
||||
delete it;
|
||||
}
|
||||
m_characteristicMapByHandle.clear(); // Clear the map
|
||||
|
||||
m_characteristicVector.clear(); // Clear the vector
|
||||
} // removeCharacteristics
|
||||
|
||||
|
||||
|
@ -335,8 +344,8 @@ std::string NimBLERemoteService::toString() {
|
|||
res += " 0x";
|
||||
res += val;
|
||||
|
||||
for (auto &myPair : m_characteristicMap) {
|
||||
res += "\n" + myPair.second->toString();
|
||||
for (auto &it: m_characteristicVector) {
|
||||
res += "\n" + it->toString();
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -348,10 +357,11 @@ std::string NimBLERemoteService::toString() {
|
|||
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
||||
*/
|
||||
void NimBLERemoteService::releaseSemaphores() {
|
||||
for (auto &cPair : m_characteristicMapByHandle) {
|
||||
cPair.second->releaseSemaphores();
|
||||
for(auto &it: m_characteristicVector) {
|
||||
it->releaseSemaphores();
|
||||
}
|
||||
m_semaphoreGetCharEvt.give(1);
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -17,12 +17,15 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
|
||||
#include "NimBLEClient.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "NimBLERemoteCharacteristic.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class NimBLEClient;
|
||||
class NimBLERemoteCharacteristic;
|
||||
|
@ -36,19 +39,18 @@ public:
|
|||
virtual ~NimBLERemoteService();
|
||||
|
||||
// Public methods
|
||||
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference.
|
||||
NimBLERemoteCharacteristic* getCharacteristic(NimBLEUUID uuid); // Get the specified characteristic reference.
|
||||
// BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference.
|
||||
std::map<std::string, NimBLERemoteCharacteristic*>* getCharacteristics();
|
||||
std::map<uint16_t, NimBLERemoteCharacteristic*>* getCharacteristicsByHandle(); // Get the characteristics map.
|
||||
// void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap);
|
||||
|
||||
NimBLEClient* getClient(void); // Get a reference to the client associated with this service.
|
||||
uint16_t getHandle(); // Get the handle of this service.
|
||||
NimBLEUUID getUUID(void); // Get the UUID of this service.
|
||||
std::string getValue(NimBLEUUID characteristicUuid); // Get the value of a characteristic.
|
||||
bool setValue(NimBLEUUID characteristicUuid, std::string value); // Set the value of a characteristic.
|
||||
std::string toString(void);
|
||||
std::vector<NimBLERemoteCharacteristic*>::iterator begin();
|
||||
std::vector<NimBLERemoteCharacteristic*>::iterator end();
|
||||
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid);
|
||||
NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||
NimBLEClient* getClient(void);
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID(void);
|
||||
std::string getValue(const NimBLEUUID &characteristicUuid);
|
||||
bool setValue(const NimBLEUUID &characteristicUuid,
|
||||
const std::string &value);
|
||||
std::string toString(void);
|
||||
std::vector<NimBLERemoteCharacteristic*>* getCharacteristics(bool refresh = false);
|
||||
|
||||
private:
|
||||
// Private constructor ... never meant to be created by a user application.
|
||||
|
@ -59,31 +61,29 @@ private:
|
|||
friend class NimBLERemoteCharacteristic;
|
||||
|
||||
// Private methods
|
||||
bool retrieveCharacteristics(void); // Retrieve the characteristics from the BLE Server.
|
||||
bool retrieveCharacteristics(const NimBLEUUID *uuid_filter = nullptr);
|
||||
static int characteristicDiscCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg);
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr,
|
||||
void *arg);
|
||||
|
||||
uint16_t getStartHandle(); // Get the start handle for this service.
|
||||
uint16_t getEndHandle(); // Get the end handle for this service.
|
||||
uint16_t getStartHandle();
|
||||
uint16_t getEndHandle();
|
||||
void releaseSemaphores();
|
||||
void removeCharacteristics();
|
||||
|
||||
// Properties
|
||||
|
||||
// We maintain a map of characteristics owned by this service keyed by a string representation of the UUID.
|
||||
std::map<std::string, NimBLERemoteCharacteristic*> m_characteristicMap;
|
||||
// We maintain a vector of characteristics owned by this service.
|
||||
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
|
||||
|
||||
// We maintain a map of characteristics owned by this service keyed by a handle.
|
||||
std::map<uint16_t, NimBLERemoteCharacteristic*> m_characteristicMapByHandle;
|
||||
|
||||
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
|
||||
NimBLEClient* m_pClient;
|
||||
FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
|
||||
NimBLEUUID m_uuid; // The UUID of this service.
|
||||
uint16_t m_startHandle; // The starting handle of this service.
|
||||
uint16_t m_endHandle; // The ending handle of this service.
|
||||
}; // BLERemoteService
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_startHandle;
|
||||
uint16_t m_endHandle;
|
||||
}; // NimBLERemoteService
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
#include "NimBLEScan.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -63,7 +66,7 @@ NimBLEScan::NimBLEScan() {
|
|||
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
|
||||
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
|
||||
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
|
||||
m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||
m_stopped = true;
|
||||
m_wantDuplicates = false;
|
||||
|
@ -84,10 +87,10 @@ NimBLEScan::NimBLEScan() {
|
|||
switch(event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_DISC: {
|
||||
if(pScan->m_stopped) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results.");
|
||||
return 0;
|
||||
}
|
||||
if(pScan->m_stopped) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Scan stop called, ignoring results.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
|
||||
event->disc.length_data);
|
||||
|
@ -112,15 +115,17 @@ NimBLEScan::NimBLEScan() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||
|
||||
// If we've seen this device before get a pointer to it from the map
|
||||
auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString());
|
||||
if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) {
|
||||
advertisedDevice = (*it).second;
|
||||
// If we've seen this device before get a pointer to it from the vector
|
||||
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||
if(it->getAddress() == advertisedAddress) {
|
||||
advertisedDevice = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't seen this device before; create a new instance and insert it in the map.
|
||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||
// Otherwise just update the relevant parameters of the already known device.
|
||||
if(advertisedDevice == nullptr){
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
|
@ -128,7 +133,7 @@ NimBLEScan::NimBLEScan() {
|
|||
advertisedDevice->setAddress(advertisedAddress);
|
||||
//NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type));
|
||||
advertisedDevice->setAdvType(event->disc.event_type);
|
||||
pScan->m_scanResults.m_advertisedDevicesMap.insert(std::pair<std::string, NimBLEAdvertisedDevice*>(advertisedAddress.toString(), advertisedDevice));
|
||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
else{
|
||||
|
@ -141,7 +146,7 @@ NimBLEScan::NimBLEScan() {
|
|||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
// If not active scanning report the result to the listener.
|
||||
if(pScan->m_scan_params.passive) {
|
||||
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
// Otherwise wait for the scan response so we can report all of the data at once.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
|
@ -259,7 +264,7 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
|||
}
|
||||
|
||||
// if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals
|
||||
// then we should not clear map or we will connect the same device few times
|
||||
// then we should not clear vector or we will connect the same device few times
|
||||
if(!is_continue) {
|
||||
clearResults();
|
||||
}
|
||||
|
@ -325,11 +330,16 @@ void NimBLEScan::stop() {
|
|||
|
||||
|
||||
// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address
|
||||
void NimBLEScan::erase(NimBLEAddress address) {
|
||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
NimBLEAdvertisedDevice *advertisedDevice = m_scanResults.m_advertisedDevicesMap.find(address.toString())->second;
|
||||
m_scanResults.m_advertisedDevicesMap.erase(address.toString());
|
||||
delete advertisedDevice;
|
||||
|
||||
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||
if((*it)->getAddress() == address) {
|
||||
delete *it;
|
||||
m_scanResults.m_advertisedDevicesVector.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -356,10 +366,10 @@ NimBLEScanResults NimBLEScan::getResults() {
|
|||
* @brief Clear the results of the scan.
|
||||
*/
|
||||
void NimBLEScan::clearResults() {
|
||||
for(auto _dev : m_scanResults.m_advertisedDevicesMap){
|
||||
delete _dev.second;
|
||||
for(auto &it: m_scanResults.m_advertisedDevicesVector) {
|
||||
delete it;
|
||||
}
|
||||
m_scanResults.m_advertisedDevicesMap.clear();
|
||||
m_scanResults.m_advertisedDevicesVector.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -379,7 +389,7 @@ void NimBLEScanResults::dump() {
|
|||
* @return The number of devices found in the last scan.
|
||||
*/
|
||||
int NimBLEScanResults::getCount() {
|
||||
return m_advertisedDevicesMap.size();
|
||||
return m_advertisedDevicesVector.size();
|
||||
} // getCount
|
||||
|
||||
|
||||
|
@ -390,14 +400,43 @@ int NimBLEScanResults::getCount() {
|
|||
* @return The device at the specified index.
|
||||
*/
|
||||
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
||||
uint32_t x = 0;
|
||||
NimBLEAdvertisedDevice dev = *m_advertisedDevicesMap.begin()->second;
|
||||
for (auto it = m_advertisedDevicesMap.begin(); it != m_advertisedDevicesMap.end(); it++) {
|
||||
dev = *it->second;
|
||||
if (x==i) break;
|
||||
x++;
|
||||
}
|
||||
return dev;
|
||||
return *m_advertisedDevicesVector[i];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the beginning of the vector of advertised device pointers.
|
||||
* @return An iterator to the beginning of the vector of advertised device pointers.
|
||||
*/
|
||||
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::begin() {
|
||||
return m_advertisedDevicesVector.begin();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get iterator to the end of the vector of advertised device pointers.
|
||||
* @return An iterator to the end of the vector of advertised device pointers.
|
||||
*/
|
||||
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::end() {
|
||||
return m_advertisedDevicesVector.end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to the specified device at the given address.
|
||||
* If the address is not found a nullptr is returned.
|
||||
* @param [in] address The address of the device.
|
||||
* @return A pointer to the device at the specified address.
|
||||
*/
|
||||
NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &address) {
|
||||
for(size_t index = 0; index < m_advertisedDevicesVector.size(); index++) {
|
||||
if(m_advertisedDevicesVector[index]->getAddress() == address) {
|
||||
return m_advertisedDevicesVector[index];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -16,17 +16,21 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class NimBLEDevice;
|
||||
class NimBLEScan;
|
||||
class NimBLEAdvertisedDevice;
|
||||
class NimBLEAdvertisedDeviceCallbacks;
|
||||
class NimBLEAddress;
|
||||
|
||||
/**
|
||||
* @brief The result of having performed a scan.
|
||||
|
@ -37,13 +41,16 @@ class NimBLEAdvertisedDeviceCallbacks;
|
|||
*/
|
||||
class NimBLEScanResults {
|
||||
public:
|
||||
void dump();
|
||||
int getCount();
|
||||
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
||||
void dump();
|
||||
int getCount();
|
||||
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
||||
std::vector<NimBLEAdvertisedDevice*>::iterator begin();
|
||||
std::vector<NimBLEAdvertisedDevice*>::iterator end();
|
||||
NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address);
|
||||
|
||||
private:
|
||||
friend NimBLEScan;
|
||||
std::map<std::string, NimBLEAdvertisedDevice*> m_advertisedDevicesMap;
|
||||
std::vector<NimBLEAdvertisedDevice*> m_advertisedDevicesVector;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -62,7 +69,7 @@ public:
|
|||
void stop();
|
||||
void clearResults();
|
||||
NimBLEScanResults getResults();
|
||||
void erase(NimBLEAddress address);
|
||||
void erase(const NimBLEAddress &address);
|
||||
|
||||
|
||||
private:
|
||||
|
@ -82,6 +89,6 @@ private:
|
|||
uint32_t m_duration;
|
||||
};
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLE_SCAN_H_ */
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEServer.h"
|
||||
#include "NimBLE2902.h"
|
||||
#include "NimBLEUtils.h"
|
||||
|
@ -32,10 +35,10 @@ static NimBLEServerCallbacks defaultCallbacks;
|
|||
* the BLEDevice class.
|
||||
*/
|
||||
NimBLEServer::NimBLEServer() {
|
||||
m_connId = BLE_HS_CONN_HANDLE_NONE;
|
||||
m_connId = BLE_HS_CONN_HANDLE_NONE;
|
||||
m_svcChgChrHdl = 0xffff;
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
} // BLEServer
|
||||
|
||||
|
||||
|
@ -48,7 +51,7 @@ NimBLEServer::NimBLEServer() {
|
|||
* @return A reference to the new service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::createService(const char* uuid) {
|
||||
return createService(NimBLEUUID(uuid));
|
||||
return createService(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,21 +65,21 @@ NimBLEService* NimBLEServer::createService(const char* uuid) {
|
|||
* @param [in] inst_id With multiple services with the same UUID we need to provide inst_id value different for each service.
|
||||
* @return A reference to the new service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::createService(NimBLEUUID uuid, uint32_t numHandles, uint8_t inst_id) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
|
||||
NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
|
||||
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if (m_serviceMap.getByUUID(uuid) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
|
||||
uuid.toString().c_str());
|
||||
}
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if (m_serviceMap.getByUUID(uuid) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Attempt to create a new service with uuid %s but a service with that UUID already exists.",
|
||||
uuid.toString().c_str());
|
||||
}
|
||||
|
||||
NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
|
||||
pService->m_instId = inst_id;
|
||||
m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
|
||||
NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
|
||||
pService->m_instId = inst_id;
|
||||
m_serviceMap.setByUUID(uuid, pService); // Save a reference to this service being on this server.
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< createService");
|
||||
return pService;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< createService");
|
||||
return pService;
|
||||
} // createService
|
||||
|
||||
|
||||
|
@ -86,7 +89,7 @@ NimBLEService* NimBLEServer::createService(NimBLEUUID uuid, uint32_t numHandles,
|
|||
* @return A reference to the service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
||||
return m_serviceMap.getByUUID(uuid);
|
||||
return m_serviceMap.getByUUID(uuid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,8 +98,8 @@ NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
|||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the service object.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(NimBLEUUID uuid) {
|
||||
return m_serviceMap.getByUUID(uuid);
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
|
||||
return m_serviceMap.getByUUID(uuid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -106,7 +109,7 @@ NimBLEService* NimBLEServer::getServiceByUUID(NimBLEUUID uuid) {
|
|||
* @return An advertising object.
|
||||
*/
|
||||
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
||||
return BLEDevice::getAdvertising();
|
||||
return BLEDevice::getAdvertising();
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,7 +119,7 @@ NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
|||
* @return Client connection id.
|
||||
*/
|
||||
uint16_t NimBLEServer::getConnId() {
|
||||
return m_connId;
|
||||
return m_connId;
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,10 +128,10 @@ uint16_t NimBLEServer::getConnId() {
|
|||
* services and characteristics / descriptors for the NimBLE host to register them.
|
||||
*/
|
||||
void NimBLEServer::start() {
|
||||
if(m_gattsStarted) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Gatt server already started");
|
||||
return;
|
||||
}
|
||||
if(m_gattsStarted) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Gatt server already started");
|
||||
return;
|
||||
}
|
||||
|
||||
int rc = ble_gatts_start();
|
||||
if (rc != 0) {
|
||||
|
@ -180,7 +183,7 @@ void NimBLEServer::start() {
|
|||
pService = m_serviceMap.getNext();
|
||||
}
|
||||
|
||||
m_gattsStarted = true;
|
||||
m_gattsStarted = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,7 +212,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||
* @return The number of connected clients.
|
||||
*/
|
||||
uint32_t NimBLEServer::getConnectedCount() {
|
||||
return m_connectedServersMap.size();
|
||||
return m_connectedServersMap.size();
|
||||
} // getConnectedCount
|
||||
|
||||
|
||||
|
@ -222,15 +225,15 @@ uint32_t NimBLEServer::getConnectedCount() {
|
|||
*
|
||||
*/
|
||||
/*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEServer* server = (NimBLEServer*)arg;
|
||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
||||
NimBLEUtils::gapEventToString(event->type));
|
||||
NimBLEServer* server = (NimBLEServer*)arg;
|
||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
||||
NimBLEUtils::gapEventToString(event->type));
|
||||
int rc = 0;
|
||||
struct ble_gap_conn_desc desc;
|
||||
|
||||
switch(event->type) {
|
||||
switch(event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_CONNECT: {
|
||||
case BLE_GAP_EVENT_CONNECT: {
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising */
|
||||
NIMBLE_LOGC(LOG_TAG, "Connection failed");
|
||||
|
@ -250,7 +253,7 @@ uint32_t NimBLEServer::getConnectedCount() {
|
|||
}
|
||||
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_CONNECT
|
||||
} // BLE_GAP_EVENT_CONNECT
|
||||
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT: {
|
||||
|
@ -407,11 +410,11 @@ uint32_t NimBLEServer::getConnectedCount() {
|
|||
return 0;
|
||||
} // BLE_GAP_EVENT_PASSKEY_ACTION
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< handleGATTServerEvent");
|
||||
return 0;
|
||||
} // handleGATTServerEvent
|
||||
|
||||
|
@ -427,10 +430,10 @@ uint32_t NimBLEServer::getConnectedCount() {
|
|||
*/
|
||||
void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
m_pServerCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
}
|
||||
m_pServerCallbacks = pCallbacks;
|
||||
} else {
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
|
@ -439,9 +442,9 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) {
|
|||
*/
|
||||
/*
|
||||
void BLEServer::removeService(BLEService* service) {
|
||||
service->stop();
|
||||
service->executeDelete();
|
||||
m_serviceMap.removeService(service);
|
||||
service->stop();
|
||||
service->executeDelete();
|
||||
m_serviceMap.removeService(service);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -453,9 +456,9 @@ void BLEServer::removeService(BLEService* service) {
|
|||
* retrieving the advertising object and invoking start upon it.
|
||||
*/
|
||||
void NimBLEServer::startAdvertising() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> startAdvertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
NIMBLE_LOGD(LOG_TAG, "<< startAdvertising");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> startAdvertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
NIMBLE_LOGD(LOG_TAG, "<< startAdvertising");
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
|
@ -463,9 +466,9 @@ void NimBLEServer::startAdvertising() {
|
|||
* @brief Stop advertising.
|
||||
*/
|
||||
void NimBLEServer::stopAdvertising() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising");
|
||||
NimBLEDevice::stopAdvertising();
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stopAdvertising");
|
||||
NimBLEDevice::stopAdvertising();
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stopAdvertising");
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
|
@ -475,39 +478,39 @@ void NimBLEServer::stopAdvertising() {
|
|||
*/
|
||||
/*
|
||||
bool BLEServer::connect(BLEAddress address) {
|
||||
esp_bd_addr_t addr;
|
||||
memcpy(&addr, address.getNative(), 6);
|
||||
// Perform the open connection request against the target BLE Server.
|
||||
m_semaphoreOpenEvt.take("connect");
|
||||
esp_err_t errRc = ::esp_ble_gatts_open(
|
||||
getGattsIf(),
|
||||
addr, // address
|
||||
1 // direct connection
|
||||
);
|
||||
if (errRc != ESP_OK) {
|
||||
ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
|
||||
return false;
|
||||
}
|
||||
esp_bd_addr_t addr;
|
||||
memcpy(&addr, address.getNative(), 6);
|
||||
// Perform the open connection request against the target BLE Server.
|
||||
m_semaphoreOpenEvt.take("connect");
|
||||
esp_err_t errRc = ::esp_ble_gatts_open(
|
||||
getGattsIf(),
|
||||
addr, // address
|
||||
1 // direct connection
|
||||
);
|
||||
if (errRc != ESP_OK) {
|
||||
ESP_LOGE(LOG_TAG, "esp_ble_gattc_open: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
|
||||
ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK);
|
||||
return rc == ESP_GATT_OK;
|
||||
uint32_t rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
|
||||
ESP_LOGD(LOG_TAG, "<< connect(), rc=%d", rc==ESP_GATT_OK);
|
||||
return rc == ESP_GATT_OK;
|
||||
} // connect
|
||||
*/
|
||||
|
||||
|
||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
} // onConnect
|
||||
|
||||
|
||||
void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onConnect(): Default");
|
||||
} // onConnect
|
||||
|
||||
|
||||
void NimBLEServerCallbacks::onDisconnect(NimBLEServer* pServer) {
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onDisconnect(): Default");
|
||||
} // onDisconnect
|
||||
|
||||
uint32_t NimBLEServerCallbacks::onPassKeyRequest(){
|
||||
|
@ -533,14 +536,14 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){
|
|||
|
||||
/* multi connect support */
|
||||
void NimBLEServer::updatePeerMTU(uint16_t conn_id, uint16_t mtu) {
|
||||
const std::map<uint16_t, conn_status_t>::iterator it = m_connectedServersMap.find(conn_id);
|
||||
if (it != m_connectedServersMap.end()) {
|
||||
it->second.mtu = mtu;
|
||||
}
|
||||
const std::map<uint16_t, conn_status_t>::iterator it = m_connectedServersMap.find(conn_id);
|
||||
if (it != m_connectedServersMap.end()) {
|
||||
it->second.mtu = mtu;
|
||||
}
|
||||
}
|
||||
|
||||
std::map<uint16_t, conn_status_t> NimBLEServer::getPeerDevices() {
|
||||
return m_connectedServersMap;
|
||||
return m_connectedServersMap;
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,17 +561,17 @@ uint16_t NimBLEServer::getPeerMTU(uint16_t conn_id) {
|
|||
}
|
||||
|
||||
void NimBLEServer::addPeerDevice(void* peer, bool _client, uint16_t conn_id) {
|
||||
conn_status_t status = {
|
||||
.peer_device = peer,
|
||||
.connected = true,
|
||||
.mtu = 23
|
||||
};
|
||||
conn_status_t status = {
|
||||
.peer_device = peer,
|
||||
.connected = true,
|
||||
.mtu = 23
|
||||
};
|
||||
|
||||
m_connectedServersMap.insert(std::pair<uint16_t, conn_status_t>(conn_id, status));
|
||||
m_connectedServersMap.insert(std::pair<uint16_t, conn_status_t>(conn_id, status));
|
||||
}
|
||||
|
||||
void NimBLEServer::removePeerDevice(uint16_t conn_id, bool _client) {
|
||||
m_connectedServersMap.erase(conn_id);
|
||||
m_connectedServersMap.erase(conn_id);
|
||||
}
|
||||
/* multi connect support */
|
||||
|
||||
|
@ -581,12 +584,12 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
|||
uint16_t latency, uint16_t timeout,
|
||||
uint16_t minConnTime, uint16_t maxConnTime)
|
||||
{
|
||||
ble_gap_upd_params params;
|
||||
ble_gap_upd_params params;
|
||||
|
||||
params.latency = latency;
|
||||
params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
params.latency = latency;
|
||||
params.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
params.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
params.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
params.min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
|
||||
params.max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
|
||||
|
||||
|
@ -605,4 +608,6 @@ void NimBLEServer::onHostReset() {
|
|||
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "NimBLEAdvertising.h"
|
||||
|
@ -24,7 +27,6 @@
|
|||
#include "NimBLESecurity.h"
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
|
||||
#include <map>
|
||||
|
||||
class NimBLEService;
|
||||
|
@ -46,10 +48,10 @@ class NimBLEServiceMap {
|
|||
public:
|
||||
// NimBLEService* getByHandle(uint16_t handle);
|
||||
NimBLEService* getByUUID(const char* uuid);
|
||||
NimBLEService* getByUUID(NimBLEUUID uuid, uint8_t inst_id = 0);
|
||||
NimBLEService* getByUUID(const NimBLEUUID &uuid, uint8_t inst_id = 0);
|
||||
// void setByHandle(uint16_t handle, NimBLEService* service);
|
||||
void setByUUID(const char* uuid, NimBLEService* service);
|
||||
void setByUUID(NimBLEUUID uuid, NimBLEService* service);
|
||||
void setByUUID(const NimBLEUUID &uuid, NimBLEService* service);
|
||||
std::string toString();
|
||||
NimBLEService* getFirst();
|
||||
NimBLEService* getNext();
|
||||
|
@ -70,7 +72,7 @@ class NimBLEServer {
|
|||
public:
|
||||
uint32_t getConnectedCount();
|
||||
NimBLEService* createService(const char* uuid);
|
||||
NimBLEService* createService(NimBLEUUID uuid, uint32_t numHandles=15, uint8_t inst_id=0);
|
||||
NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, uint8_t inst_id=0);
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks);
|
||||
void startAdvertising();
|
||||
|
@ -78,7 +80,7 @@ public:
|
|||
void start();
|
||||
// void removeService(BLEService* service);
|
||||
NimBLEService* getServiceByUUID(const char* uuid);
|
||||
NimBLEService* getServiceByUUID(NimBLEUUID uuid);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
||||
int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
// bool connect(BLEAddress address);
|
||||
void updateConnParams(uint16_t conn_handle,
|
||||
|
@ -106,7 +108,7 @@ private:
|
|||
// BLEAdvertising m_bleAdvertising;
|
||||
uint16_t m_connId;
|
||||
uint16_t m_svcChgChrHdl;
|
||||
bool m_gattsStarted;
|
||||
bool m_gattsStarted;
|
||||
|
||||
std::map<uint16_t, conn_status_t> m_connectedServersMap;
|
||||
std::map<uint16_t, NimBLECharacteristic*> m_notifyChrMap;
|
||||
|
@ -114,7 +116,7 @@ private:
|
|||
NimBLEServiceMap m_serviceMap;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
|
@ -150,5 +152,6 @@ public:
|
|||
}; // BLEServerCallbacks
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLESERVER_H_ */
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -43,11 +46,11 @@ NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer
|
|||
* @param [in] uuid The UUID of the service.
|
||||
* @param [in] numHandles The maximum number of handles associated with the service.
|
||||
*/
|
||||
NimBLEService::NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* pServer) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_pServer = pServer;
|
||||
m_numHandles = numHandles;
|
||||
NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) {
|
||||
m_uuid = uuid;
|
||||
m_handle = NULL_HANDLE;
|
||||
m_pServer = pServer;
|
||||
m_numHandles = numHandles;
|
||||
} // NimBLEService
|
||||
|
||||
|
||||
|
@ -56,10 +59,10 @@ NimBLEService::NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer*
|
|||
* @return N/A.
|
||||
*/
|
||||
void NimBLEService::dump() {
|
||||
NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x",
|
||||
m_uuid.toString().c_str(),
|
||||
m_handle);
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str());
|
||||
NIMBLE_LOGD(LOG_TAG, "Service: uuid:%s, handle: 0x%.2x",
|
||||
m_uuid.toString().c_str(),
|
||||
m_handle);
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristics:\n%s", m_characteristicMap.toString().c_str());
|
||||
} // dump
|
||||
|
||||
|
||||
|
@ -68,7 +71,7 @@ void NimBLEService::dump() {
|
|||
* @return the UUID of the service.
|
||||
*/
|
||||
NimBLEUUID NimBLEService::getUUID() {
|
||||
return m_uuid;
|
||||
return m_uuid;
|
||||
} // getUUID
|
||||
|
||||
|
||||
|
@ -80,39 +83,40 @@ NimBLEUUID NimBLEService::getUUID() {
|
|||
*/
|
||||
|
||||
bool NimBLEService::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
int rc = 0;
|
||||
// Nimble requires an array of services to be sent to the api
|
||||
// Since we are adding 1 at a time we create an array of 2 and set the type
|
||||
// of the second service to 0 to indicate the end of the array.
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
int rc = 0;
|
||||
// Nimble requires an array of services to be sent to the api
|
||||
// Since we are adding 1 at a time we create an array of 2 and set the type
|
||||
// of the second service to 0 to indicate the end of the array.
|
||||
ble_gatt_svc_def* svc = new ble_gatt_svc_def[2];
|
||||
ble_gatt_chr_def* pChr_a = nullptr;
|
||||
ble_gatt_chr_def* pChr_a = nullptr;
|
||||
ble_gatt_dsc_def* pDsc_a = nullptr;
|
||||
|
||||
svc[0].type = BLE_GATT_SVC_TYPE_PRIMARY;
|
||||
svc[0].uuid = &m_uuid.getNative()->u;
|
||||
svc[0].includes = NULL;
|
||||
svc[0].includes = NULL;
|
||||
|
||||
uint8_t numChrs = m_characteristicMap.getSize();
|
||||
uint8_t numChrs = m_characteristicMap.getSize();
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str());
|
||||
NIMBLE_LOGD(LOG_TAG,"Adding %d characteristics for service %s", numChrs, toString().c_str());
|
||||
|
||||
if(!numChrs){
|
||||
svc[0].characteristics = NULL;
|
||||
}else{
|
||||
if(!numChrs){
|
||||
svc[0].characteristics = NULL;
|
||||
}else{
|
||||
// Nimble requires the last characteristic to have it's uuid = 0 to indicate the end
|
||||
// of the characteristics for the service. We create 1 extra and set it to null
|
||||
// for this purpose.
|
||||
pChr_a = new ble_gatt_chr_def[numChrs+1];
|
||||
NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst();
|
||||
pChr_a = new ble_gatt_chr_def[numChrs+1];
|
||||
NimBLECharacteristic* pCharacteristic = m_characteristicMap.getFirst();
|
||||
|
||||
for(uint8_t i=0; i < numChrs; i++) {
|
||||
for(uint8_t i=0; i < numChrs; i++) {
|
||||
uint8_t numDscs = pCharacteristic->m_descriptorMap.getSize();
|
||||
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)) {
|
||||
if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) &&
|
||||
pCharacteristic->getDescriptorByUUID("2902") != nullptr) {
|
||||
numDscs--;
|
||||
}
|
||||
}
|
||||
|
@ -144,21 +148,21 @@ bool NimBLEService::start() {
|
|||
pChr_a[i].descriptors = pDsc_a;
|
||||
}
|
||||
|
||||
pChr_a[i].uuid = &pCharacteristic->m_uuid.getNative()->u;
|
||||
pChr_a[i].uuid = &pCharacteristic->m_uuid.getNative()->u;
|
||||
pChr_a[i].access_cb = NimBLECharacteristic::handleGapEvent;
|
||||
pChr_a[i].arg = pCharacteristic;
|
||||
pChr_a[i].flags = pCharacteristic->m_properties;
|
||||
pChr_a[i].min_key_size = 0;
|
||||
pChr_a[i].val_handle = &pCharacteristic->m_handle;
|
||||
pCharacteristic = m_characteristicMap.getNext();
|
||||
}
|
||||
pCharacteristic = m_characteristicMap.getNext();
|
||||
}
|
||||
|
||||
pChr_a[numChrs].uuid = NULL;
|
||||
svc[0].characteristics = pChr_a;
|
||||
}
|
||||
pChr_a[numChrs].uuid = NULL;
|
||||
svc[0].characteristics = pChr_a;
|
||||
}
|
||||
|
||||
// end of services must indicate to api with type = 0
|
||||
svc[1].type = 0;
|
||||
// end of services must indicate to api with type = 0
|
||||
svc[1].type = 0;
|
||||
|
||||
rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)svc);
|
||||
if (rc != 0) {
|
||||
|
@ -173,7 +177,7 @@ bool NimBLEService::start() {
|
|||
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< start()");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< start()");
|
||||
return true;
|
||||
} // start
|
||||
|
||||
|
@ -183,13 +187,13 @@ bool NimBLEService::start() {
|
|||
* @param [in] handle The handle associated with the service.
|
||||
*/
|
||||
void NimBLEService::setHandle(uint16_t handle) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str());
|
||||
if (m_handle != NULL_HANDLE) {
|
||||
NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle);
|
||||
return;
|
||||
}
|
||||
m_handle = handle;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setHandle");
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setHandle - Handle=0x%.2x, service UUID=%s)", handle, getUUID().toString().c_str());
|
||||
if (m_handle != NULL_HANDLE) {
|
||||
NIMBLE_LOGE(LOG_TAG, "!!! Handle is already set %.2x", m_handle);
|
||||
return;
|
||||
}
|
||||
m_handle = handle;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< setHandle");
|
||||
} // setHandle
|
||||
|
||||
|
||||
|
@ -198,7 +202,7 @@ void NimBLEService::setHandle(uint16_t handle) {
|
|||
* @return The handle associated with this service.
|
||||
*/
|
||||
uint16_t NimBLEService::getHandle() {
|
||||
return m_handle;
|
||||
return m_handle;
|
||||
} // getHandle
|
||||
|
||||
|
||||
|
@ -207,26 +211,26 @@ uint16_t NimBLEService::getHandle() {
|
|||
* @param [in] pCharacteristic A pointer to the characteristic to be added.
|
||||
*/
|
||||
void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
|
||||
// We maintain a mapping of characteristics owned by this service. These are managed by the
|
||||
// BLECharacteristicMap class instance found in m_characteristicMap. We add the characteristic
|
||||
// to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF).
|
||||
// We maintain a mapping of characteristics owned by this service. These are managed by the
|
||||
// BLECharacteristicMap class instance found in m_characteristicMap. We add the characteristic
|
||||
// to the map and then ask the service to add the characteristic at the BLE level (ESP-IDF).
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addCharacteristic()");
|
||||
NIMBLE_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s",
|
||||
pCharacteristic->getUUID().toString().c_str(),
|
||||
toString().c_str());
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addCharacteristic()");
|
||||
NIMBLE_LOGD(LOG_TAG, "Adding characteristic: uuid=%s to service: %s",
|
||||
pCharacteristic->getUUID().toString().c_str(),
|
||||
toString().c_str());
|
||||
|
||||
// Check that we don't add the same characteristic twice.
|
||||
if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one");
|
||||
//return;
|
||||
}
|
||||
// Check that we don't add the same characteristic twice.
|
||||
if (m_characteristicMap.getByUUID(pCharacteristic->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a new characteristic with the same UUID as a previous one");
|
||||
//return;
|
||||
}
|
||||
|
||||
// Remember this characteristic in our map of characteristics. At this point, we can lookup by UUID
|
||||
// but not by handle. The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT.
|
||||
m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID());
|
||||
// Remember this characteristic in our map of characteristics. At this point, we can lookup by UUID
|
||||
// but not by handle. The handle is allocated to us on the ESP_GATTS_ADD_CHAR_EVT.
|
||||
m_characteristicMap.setByUUID(pCharacteristic, pCharacteristic->getUUID());
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()");
|
||||
NIMBLE_LOGD(LOG_TAG, "<< addCharacteristic()");
|
||||
} // addCharacteristic
|
||||
|
||||
|
||||
|
@ -237,7 +241,7 @@ void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
|
|||
* @return The new BLE characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint32_t properties) {
|
||||
return createCharacteristic(NimBLEUUID(uuid), properties);
|
||||
return createCharacteristic(NimBLEUUID(uuid), properties);
|
||||
}
|
||||
|
||||
|
||||
|
@ -247,21 +251,21 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
|
|||
* @param [in] properties - The properties of the characteristic.
|
||||
* @return The new BLE characteristic.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::createCharacteristic(NimBLEUUID uuid, uint32_t properties) {
|
||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||
addCharacteristic(pCharacteristic);
|
||||
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||
addCharacteristic(pCharacteristic);
|
||||
//pCharacteristic->executeCreate(this);
|
||||
return pCharacteristic;
|
||||
return pCharacteristic;
|
||||
} // createCharacteristic
|
||||
|
||||
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(NimBLEUUID uuid) {
|
||||
return m_characteristicMap.getByUUID(uuid);
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
return m_characteristicMap.getByUUID(uuid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,12 +277,12 @@ NimBLECharacteristic* NimBLEService::getCharacteristic(NimBLEUUID uuid) {
|
|||
* @return A string representation of this service.
|
||||
*/
|
||||
std::string NimBLEService::toString() {
|
||||
std::string res = "UUID: " + getUUID().toString();
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", getHandle());
|
||||
res += ", handle: 0x";
|
||||
res += hex;
|
||||
return res;
|
||||
std::string res = "UUID: " + getUUID().toString();
|
||||
char hex[5];
|
||||
snprintf(hex, sizeof(hex), "%04x", getHandle());
|
||||
res += ", handle: 0x";
|
||||
res += hex;
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -287,7 +291,8 @@ std::string NimBLEService::toString() {
|
|||
* @return The BLEServer associated with this service.
|
||||
*/
|
||||
NimBLEServer* NimBLEService::getServer() {
|
||||
return m_pServer;
|
||||
return m_pServer;
|
||||
} // getServer
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
|
@ -17,6 +17,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLEServer.h"
|
||||
#include "NimBLEUUID.h"
|
||||
|
@ -31,21 +34,21 @@ class NimBLECharacteristic;
|
|||
*/
|
||||
class NimBLECharacteristicMap {
|
||||
public:
|
||||
void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid);
|
||||
void setByUUID(NimBLECharacteristic* pCharacteristic, NimBLEUUID uuid);
|
||||
void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic);
|
||||
NimBLECharacteristic* getByUUID(const char* uuid);
|
||||
NimBLECharacteristic* getByUUID(NimBLEUUID uuid);
|
||||
NimBLECharacteristic* getByHandle(uint16_t handle);
|
||||
NimBLECharacteristic* getFirst();
|
||||
NimBLECharacteristic* getNext();
|
||||
uint8_t getSize();
|
||||
std::string toString();
|
||||
void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid);
|
||||
void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid);
|
||||
void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic);
|
||||
NimBLECharacteristic* getByUUID(const char* uuid);
|
||||
NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid);
|
||||
NimBLECharacteristic* getByHandle(uint16_t handle);
|
||||
NimBLECharacteristic* getFirst();
|
||||
NimBLECharacteristic* getNext();
|
||||
uint8_t getSize();
|
||||
std::string toString();
|
||||
|
||||
private:
|
||||
std::map<NimBLECharacteristic*, std::string> m_uuidMap;
|
||||
std::map<uint16_t, NimBLECharacteristic*> m_handleMap;
|
||||
std::map<NimBLECharacteristic*, std::string>::iterator m_iterator;
|
||||
std::map<NimBLECharacteristic*, std::string> m_uuidMap;
|
||||
std::map<uint16_t, NimBLECharacteristic*> m_handleMap;
|
||||
std::map<NimBLECharacteristic*, std::string>::iterator m_iterator;
|
||||
};
|
||||
|
||||
|
||||
|
@ -55,42 +58,43 @@ private:
|
|||
*/
|
||||
class NimBLEService {
|
||||
public:
|
||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
NimBLECharacteristic* createCharacteristic(NimBLEUUID uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid,
|
||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
void dump();
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
||||
NimBLECharacteristic* getCharacteristic(NimBLEUUID uuid);
|
||||
NimBLEUUID getUUID();
|
||||
NimBLEServer* getServer();
|
||||
bool start();
|
||||
// void stop();
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
uint8_t m_instId = 0;
|
||||
void dump();
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||
NimBLEUUID getUUID();
|
||||
NimBLEServer* getServer();
|
||||
bool start();
|
||||
// void stop();
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
uint8_t m_instId = 0;
|
||||
|
||||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
|
||||
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
|
||||
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLECharacteristicMap m_characteristicMap;
|
||||
uint16_t m_handle;
|
||||
NimBLEServer* m_pServer = nullptr;
|
||||
NimBLEUUID m_uuid;
|
||||
NimBLECharacteristicMap m_characteristicMap;
|
||||
uint16_t m_handle;
|
||||
NimBLEServer* m_pServer = nullptr;
|
||||
NimBLEUUID m_uuid;
|
||||
|
||||
uint16_t m_numHandles;
|
||||
void setHandle(uint16_t handle);
|
||||
uint16_t m_numHandles;
|
||||
void setHandle(uint16_t handle);
|
||||
}; // BLEService
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif /* MAIN_NIMBLESERVICE_H_ */
|
|
@ -14,6 +14,9 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEService.h"
|
||||
|
||||
|
||||
|
@ -23,7 +26,7 @@
|
|||
* @return The characteristic.
|
||||
*/
|
||||
NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) {
|
||||
return getByUUID(NimBLEUUID(uuid));
|
||||
return getByUUID(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,14 +34,14 @@ NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) {
|
|||
* @param [in] UUID The UUID to look up the service.
|
||||
* @return The characteristic.
|
||||
*/
|
||||
NimBLEService* NimBLEServiceMap::getByUUID(NimBLEUUID uuid, uint8_t inst_id) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
//return m_uuidMap.at(uuid.toString());
|
||||
return nullptr;
|
||||
NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_id) {
|
||||
for (auto &myPair : m_uuidMap) {
|
||||
if (myPair.first->getUUID().equals(uuid)) {
|
||||
return myPair.first;
|
||||
}
|
||||
}
|
||||
//return m_uuidMap.at(uuid.toString());
|
||||
return nullptr;
|
||||
} // getByUUID
|
||||
|
||||
|
||||
|
@ -49,7 +52,7 @@ NimBLEService* NimBLEServiceMap::getByUUID(NimBLEUUID uuid, uint8_t inst_id) {
|
|||
*/
|
||||
/*
|
||||
NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) {
|
||||
return m_handleMap.at(handle);
|
||||
return m_handleMap.at(handle);
|
||||
} // getByHandle
|
||||
*/
|
||||
|
||||
|
@ -59,8 +62,8 @@ NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) {
|
|||
* @param [in] characteristic The service to cache.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEServiceMap::setByUUID(NimBLEUUID uuid, NimBLEService* service) {
|
||||
m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString()));
|
||||
void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) {
|
||||
m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString()));
|
||||
} // setByUUID
|
||||
|
||||
|
||||
|
@ -72,7 +75,7 @@ void NimBLEServiceMap::setByUUID(NimBLEUUID uuid, NimBLEService* service) {
|
|||
*/
|
||||
/*
|
||||
void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) {
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLEService*>(handle, service));
|
||||
m_handleMap.insert(std::pair<uint16_t, NimBLEService*>(handle, service));
|
||||
} // setByHandle
|
||||
*/
|
||||
|
||||
|
@ -81,15 +84,15 @@ void NimBLEServiceMap::setByHandle(uint16_t handle, NimBLEService* service) {
|
|||
* @return A string representation of the service map.
|
||||
*/
|
||||
std::string NimBLEServiceMap::toString() {
|
||||
std::string res;
|
||||
//char hex[5];
|
||||
for (auto &myPair: m_uuidMap) {
|
||||
// res += "handle: 0x";
|
||||
// snprintf(hex, sizeof(hex), "%04x", myPair.first);
|
||||
// res += hex;
|
||||
res += ", uuid: " + myPair.second + "\n";
|
||||
}
|
||||
return res;
|
||||
std::string res;
|
||||
//char hex[5];
|
||||
for (auto &myPair: m_uuidMap) {
|
||||
// res += "handle: 0x";
|
||||
// snprintf(hex, sizeof(hex), "%04x", myPair.first);
|
||||
// res += hex;
|
||||
res += ", uuid: " + myPair.second + "\n";
|
||||
}
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
|
||||
|
@ -98,40 +101,45 @@ std::string NimBLEServiceMap::toString() {
|
|||
* @return The first service in the map.
|
||||
*/
|
||||
NimBLEService* NimBLEServiceMap::getFirst() {
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEService* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
m_iterator = m_uuidMap.begin();
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEService* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getFirst
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the next service in the map.
|
||||
* @return The next service in the map.
|
||||
*/
|
||||
NimBLEService* NimBLEServiceMap::getNext() {
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEService* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
if (m_iterator == m_uuidMap.end()) return nullptr;
|
||||
NimBLEService* pRet = m_iterator->first;
|
||||
m_iterator++;
|
||||
return pRet;
|
||||
} // getNext
|
||||
|
||||
|
||||
/**
|
||||
* @brief Removes service from maps.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEServiceMap::removeService(NimBLEService* service) {
|
||||
//m_handleMap.erase(service->getHandle());
|
||||
m_uuidMap.erase(service);
|
||||
//m_handleMap.erase(service->getHandle());
|
||||
m_uuidMap.erase(service);
|
||||
} // removeService
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns the amount of registered services
|
||||
* @return amount of registered services
|
||||
*/
|
||||
int NimBLEServiceMap::getRegisteredServiceCount(){
|
||||
//return m_handleMap.size();
|
||||
//return m_handleMap.size();
|
||||
return m_uuidMap.size();
|
||||
}
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
|
@ -18,6 +18,8 @@
|
|||
#include "NimBLEUUID.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static const char* LOG_TAG = "NimBLEUUID";
|
||||
|
||||
|
||||
|
@ -38,54 +40,29 @@ static const char* LOG_TAG = "NimBLEUUID";
|
|||
*
|
||||
* @param [in] value The string to build a UUID from.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(std::string value) {
|
||||
NimBLEUUID::NimBLEUUID(const std::string &value) {
|
||||
m_valueSet = true;
|
||||
if (value.length() == 4) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
m_uuid.u16.value = 0;
|
||||
for(int i=0;i<value.length();){
|
||||
uint8_t MSB = value.c_str()[i];
|
||||
uint8_t LSB = value.c_str()[i+1];
|
||||
|
||||
if(MSB > '9') MSB -= 7;
|
||||
if(LSB > '9') LSB -= 7;
|
||||
m_uuid.u16.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(2-i)*4;
|
||||
i+=2;
|
||||
}
|
||||
m_uuid.u16.value = strtoul(value.c_str(), NULL, 16);
|
||||
}
|
||||
else if (value.length() == 8) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
m_uuid.u32.value = 0;
|
||||
for(int i=0;i<value.length();){
|
||||
uint8_t MSB = value.c_str()[i];
|
||||
uint8_t LSB = value.c_str()[i+1];
|
||||
|
||||
if(MSB > '9') MSB -= 7;
|
||||
if(LSB > '9') LSB -= 7;
|
||||
m_uuid.u32.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(6-i)*4;
|
||||
i+=2;
|
||||
}
|
||||
m_uuid.u32.value = strtoul(value.c_str(), NULL, 16);
|
||||
}
|
||||
else if (value.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be investigated (lack of time)
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
NimBLEUtils::memrcpy(m_uuid.u128.value, (uint8_t*)value.data(), 16);
|
||||
else if (value.length() == 16) {
|
||||
*this = NimBLEUUID((uint8_t*)value.data(), 16, true);
|
||||
}
|
||||
else if (value.length() == 36) {
|
||||
// If the length of the string is 36 bytes then we will assume it is a long hex string in
|
||||
// UUID format.
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
int n = 0;
|
||||
for(int i=0;i<value.length();){
|
||||
if(value.c_str()[i] == '-')
|
||||
i++;
|
||||
uint8_t MSB = value.c_str()[i];
|
||||
uint8_t LSB = value.c_str()[i+1];
|
||||
|
||||
if(MSB > '9') MSB -= 7;
|
||||
if(LSB > '9') LSB -= 7;
|
||||
m_uuid.u128.value[15-n++] = ((MSB&0x0F) <<4) | (LSB & 0x0F);
|
||||
i+=2;
|
||||
}
|
||||
char * position = const_cast<char *>(value.c_str());
|
||||
uint32_t first = strtoul(position, &position, 16);
|
||||
uint16_t second = strtoul(position + 1, &position, 16);
|
||||
uint16_t third = strtoul(position + 1, &position, 16);
|
||||
uint16_t fourth = strtoul(position + 1, &position, 16);
|
||||
uint64_t fifth = strtoull(position + 1, NULL, 16);
|
||||
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||
}
|
||||
else {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
||||
|
@ -101,7 +78,7 @@ static const char* LOG_TAG = "NimBLEUUID";
|
|||
* @param [in] size The size of the data.
|
||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||
/*** TODO: change this to use the Nimble function for various lenght UUIDs:
|
||||
int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len);
|
||||
***/
|
||||
|
@ -110,8 +87,9 @@ NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
|
|||
return;
|
||||
}
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
|
||||
if (msbFirst) {
|
||||
NimBLEUtils::memrcpy(m_uuid.u128.value, pData, 16);
|
||||
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
||||
} else {
|
||||
memcpy(m_uuid.u128.value, pData, 16);
|
||||
}
|
||||
|
@ -148,14 +126,33 @@ NimBLEUUID::NimBLEUUID(uint32_t uuid) {
|
|||
*
|
||||
* @param [in] uuid The native UUID.
|
||||
*/
|
||||
|
||||
NimBLEUUID::NimBLEUUID(ble_uuid128_t* uuid) {
|
||||
NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(m_uuid.u128.value, uuid->value, 16);
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from the 128bit value using hex parts instead of string,
|
||||
* instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes
|
||||
* BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6)
|
||||
*
|
||||
* @param [in] first The first 32bit of the UUID.
|
||||
* @param [in] second The next 16bit of the UUID.
|
||||
* @param [in] third The next 16bit of the UUID.
|
||||
* @param [in] fourth The last 64bit of the UUID, combining the last 2 parts of the string equivalent
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) {
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(m_uuid.u128.value + 12, &first, 4);
|
||||
memcpy(m_uuid.u128.value + 10, &second, 2);
|
||||
memcpy(m_uuid.u128.value + 8, &third, 2);
|
||||
memcpy(m_uuid.u128.value, &fourth, 8);
|
||||
m_valueSet = true;
|
||||
}
|
||||
|
||||
|
||||
NimBLEUUID::NimBLEUUID() {
|
||||
m_valueSet = false;
|
||||
} // NimBLEUUID
|
||||
|
@ -165,7 +162,7 @@ NimBLEUUID::NimBLEUUID() {
|
|||
* @brief Get the number of bits in this uuid.
|
||||
* @return The number of bits in the UUID. One of 16, 32 or 128.
|
||||
*/
|
||||
uint8_t NimBLEUUID::bitSize() {
|
||||
uint8_t NimBLEUUID::bitSize() const {
|
||||
if (!m_valueSet) return 0;
|
||||
return m_uuid.u.type;
|
||||
} // bitSize
|
||||
|
@ -177,11 +174,8 @@ uint8_t NimBLEUUID::bitSize() {
|
|||
* @param [in] uuid The UUID to compare against.
|
||||
* @return True if the UUIDs are equal and false otherwise.
|
||||
*/
|
||||
bool NimBLEUUID::equals(NimBLEUUID uuid) {
|
||||
if(ble_uuid_cmp(&m_uuid.u, &uuid.getNative()->u) == 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool NimBLEUUID::equals(const NimBLEUUID &uuid) const {
|
||||
return *this == uuid;
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,8 +188,7 @@ bool NimBLEUUID::equals(NimBLEUUID uuid) {
|
|||
* NNNNNNNN
|
||||
* <UUID>
|
||||
*/
|
||||
|
||||
NimBLEUUID NimBLEUUID::fromString(std::string _uuid) {
|
||||
NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) {
|
||||
uint8_t start = 0;
|
||||
if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
||||
start = 2;
|
||||
|
@ -220,7 +213,7 @@ NimBLEUUID NimBLEUUID::fromString(std::string _uuid) {
|
|||
*
|
||||
* @return The native UUID value or NULL if not set.
|
||||
*/
|
||||
ble_uuid_any_t* NimBLEUUID::getNative() {
|
||||
const ble_uuid_any_t* NimBLEUUID::getNative() const {
|
||||
if (m_valueSet == false) {
|
||||
NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!");
|
||||
return nullptr;
|
||||
|
@ -235,47 +228,20 @@ ble_uuid_any_t* NimBLEUUID::getNative() {
|
|||
* A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method
|
||||
* will convert 16 or 32 bit representations to the full 128bit.
|
||||
*/
|
||||
NimBLEUUID NimBLEUUID::to128() {
|
||||
const NimBLEUUID &NimBLEUUID::to128() {
|
||||
// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
|
||||
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we are 16 bit or 32 bit, then set the 4 bytes of the variable part of the UUID.
|
||||
// If we are 16 bit or 32 bit, then set the other bytes of the UUID.
|
||||
if (m_uuid.u.type == BLE_UUID_TYPE_16) {
|
||||
uint16_t temp = m_uuid.u16.value;
|
||||
m_uuid.u128.value[15] = 0;
|
||||
m_uuid.u128.value[14] = 0;
|
||||
m_uuid.u128.value[13] = (temp >> 8) & 0xff;
|
||||
m_uuid.u128.value[12] = temp & 0xff;
|
||||
|
||||
*this = NimBLEUUID(m_uuid.u16.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||
}
|
||||
else if (m_uuid.u.type == BLE_UUID_TYPE_32) {
|
||||
uint32_t temp = m_uuid.u32.value;
|
||||
m_uuid.u128.value[15] = (temp >> 24) & 0xff;
|
||||
m_uuid.u128.value[14] = (temp >> 16) & 0xff;
|
||||
m_uuid.u128.value[13] = (temp >> 8) & 0xff;
|
||||
m_uuid.u128.value[12] = temp & 0xff;
|
||||
*this = NimBLEUUID(m_uuid.u32.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||
}
|
||||
|
||||
// Set the fixed parts of the UUID.
|
||||
m_uuid.u128.value[11] = 0x00;
|
||||
m_uuid.u128.value[10] = 0x00;
|
||||
|
||||
m_uuid.u128.value[9] = 0x10;
|
||||
m_uuid.u128.value[8] = 0x00;
|
||||
|
||||
m_uuid.u128.value[7] = 0x80;
|
||||
m_uuid.u128.value[6] = 0x00;
|
||||
|
||||
m_uuid.u128.value[5] = 0x00;
|
||||
m_uuid.u128.value[4] = 0x80;
|
||||
m_uuid.u128.value[3] = 0x5f;
|
||||
m_uuid.u128.value[2] = 0x9b;
|
||||
m_uuid.u128.value[1] = 0x34;
|
||||
m_uuid.u128.value[0] = 0xfb;
|
||||
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
return *this;
|
||||
} // to128
|
||||
|
||||
|
@ -290,12 +256,32 @@ NimBLEUUID NimBLEUUID::to128() {
|
|||
*
|
||||
* @return A string representation of the UUID.
|
||||
*/
|
||||
std::string NimBLEUUID::toString() {
|
||||
if (!m_valueSet) return "<NULL>"; // If we have no value, nothing to format.
|
||||
std::string NimBLEUUID::toString() const {
|
||||
return std::string(*this);
|
||||
} // toString
|
||||
|
||||
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0;
|
||||
}
|
||||
|
||||
return m_valueSet == rhs.m_valueSet;
|
||||
}
|
||||
|
||||
|
||||
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
}
|
||||
|
||||
|
||||
NimBLEUUID::operator std::string() const {
|
||||
if (!m_valueSet) return std::string(); // If we have no value, nothing to format.
|
||||
|
||||
char buf[BLE_UUID_STR_LEN];
|
||||
|
||||
return ble_uuid_to_str(&m_uuid.u, buf);
|
||||
} // toString
|
||||
}
|
||||
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -30,18 +30,23 @@
|
|||
*/
|
||||
class NimBLEUUID {
|
||||
public:
|
||||
NimBLEUUID(std::string uuid);
|
||||
NimBLEUUID(const std::string &uuid);
|
||||
NimBLEUUID(uint16_t uuid);
|
||||
NimBLEUUID(uint32_t uuid);
|
||||
NimBLEUUID(ble_uuid128_t* uuid);
|
||||
NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst);
|
||||
NimBLEUUID(const ble_uuid128_t* uuid);
|
||||
NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst);
|
||||
NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth);
|
||||
NimBLEUUID();
|
||||
uint8_t bitSize(); // Get the number of bits in this uuid.
|
||||
bool equals(NimBLEUUID uuid);
|
||||
ble_uuid_any_t* getNative();
|
||||
NimBLEUUID to128();
|
||||
std::string toString();
|
||||
static NimBLEUUID fromString(std::string uuid); // Create a NimBLEUUID from a string
|
||||
uint8_t bitSize() const; // Get the number of bits in this uuid.
|
||||
bool equals(const NimBLEUUID &uuid) const;
|
||||
const ble_uuid_any_t* getNative() const;
|
||||
const NimBLEUUID & to128();
|
||||
std::string toString() const;
|
||||
static NimBLEUUID fromString(const std::string &uuid); // Create a NimBLEUUID from a string
|
||||
|
||||
bool operator ==(const NimBLEUUID & rhs) const;
|
||||
bool operator !=(const NimBLEUUID & rhs) const;
|
||||
operator std::string() const;
|
||||
|
||||
private:
|
||||
ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps.
|
||||
|
|
|
@ -11,38 +11,10 @@
|
|||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
#include "nimconfig.h"
|
||||
|
||||
static const char* LOG_TAG = "NimBLEUtils";
|
||||
|
||||
/**
|
||||
* @brief Copy memory from source to target but in reverse order.
|
||||
*
|
||||
* When we move memory from one location it is normally:
|
||||
*
|
||||
* ```
|
||||
* [0][1][2]...[n] -> [0][1][2]...[n]
|
||||
* ```
|
||||
*
|
||||
* with this function, it is:
|
||||
*
|
||||
* ```
|
||||
* [0][1][2]...[n] -> [n][n-1][n-2]...[0]
|
||||
* ```
|
||||
*
|
||||
* @param [in] target The target of the copy
|
||||
* @param [in] source The source of the copy
|
||||
* @param [in] size The number of bytes to copy
|
||||
*/
|
||||
void NimBLEUtils::memrcpy(uint8_t* target, uint8_t* source, uint32_t size) {
|
||||
assert(size > 0);
|
||||
target += (size - 1); // Point target to the last byte of the target data
|
||||
while (size > 0) {
|
||||
*target = *source;
|
||||
target--;
|
||||
source++;
|
||||
size--;
|
||||
}
|
||||
} // memrcpy
|
||||
|
||||
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
||||
/* Check connection interval min */
|
||||
|
@ -78,6 +50,7 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
|||
|
||||
|
||||
const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||
switch(rc) {
|
||||
case 0:
|
||||
return "SUCCESS";
|
||||
|
@ -355,19 +328,22 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
|
|||
return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process.";
|
||||
case (0x0500+BLE_SM_ERR_CROSS_TRANS ):
|
||||
return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.";
|
||||
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||
return "";
|
||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert the BLE Advertising Data flags to a string.
|
||||
* @param adFlags The flags to convert
|
||||
* @return std::string A string representation of the advertising flags.
|
||||
*/
|
||||
|
||||
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
switch(advType) {
|
||||
case BLE_HCI_ADV_TYPE_ADV_IND : //0
|
||||
return "Undirected - Connectable / Scannable";
|
||||
|
@ -382,7 +358,9 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
|||
default:
|
||||
return "Unknown flag";
|
||||
}
|
||||
|
||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
return "";
|
||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
} // adFlagsToString
|
||||
|
||||
|
||||
|
@ -394,7 +372,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
|||
* @param [in] length The length of the data to convert.
|
||||
* @return A pointer to the formatted buffer.
|
||||
*/
|
||||
char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length) {
|
||||
char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t length) {
|
||||
// Guard against too much data.
|
||||
if (length > 100) length = 100;
|
||||
|
||||
|
@ -422,17 +400,20 @@ char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length
|
|||
} // buildHexData
|
||||
|
||||
|
||||
|
||||
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert a BT GAP event type to a string representation.
|
||||
* @param [in] eventType The type of event.
|
||||
* @return A string representation of the event type.
|
||||
*/
|
||||
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
switch (eventType) {
|
||||
case BLE_GAP_EVENT_CONNECT : //0
|
||||
return "BLE_GAP_EVENT_CONNECT ";
|
||||
|
@ -507,6 +488,9 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
|||
NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
|
||||
return "Unknown event type";
|
||||
}
|
||||
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
return "";
|
||||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
} // gapEventToString
|
||||
|
||||
|
||||
|
|
|
@ -25,10 +25,9 @@ class NimBLEUtils {
|
|||
public:
|
||||
static void dumpGapEvent(ble_gap_event *event, void *arg);
|
||||
static const char* gapEventToString(uint8_t eventType);
|
||||
static char* buildHexData(uint8_t* target, uint8_t* source, uint8_t length);
|
||||
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
|
||||
static const char* advTypeToString(uint8_t advType);
|
||||
static const char* returnCodeToString(int rc);
|
||||
static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size);
|
||||
static int checkConnParams(ble_gap_conn_params* params);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,15 +14,18 @@
|
|||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEValue.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
static const char* LOG_TAG="NimBLEValue";
|
||||
|
||||
NimBLEValue::NimBLEValue() {
|
||||
m_accumulation = "";
|
||||
m_value = "";
|
||||
m_readOffset = 0;
|
||||
m_accumulation = "";
|
||||
m_value = "";
|
||||
m_readOffset = 0;
|
||||
} // NimBLEValue
|
||||
|
||||
|
||||
|
@ -31,9 +34,9 @@ NimBLEValue::NimBLEValue() {
|
|||
* The accumulation is a growing set of data that is added to until a commit or cancel.
|
||||
* @param [in] part A message part being added.
|
||||
*/
|
||||
void NimBLEValue::addPart(std::string part) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
|
||||
m_accumulation += part;
|
||||
void NimBLEValue::addPart(const std::string &part) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
|
||||
m_accumulation += part;
|
||||
} // addPart
|
||||
|
||||
|
||||
|
@ -43,9 +46,9 @@ void NimBLEValue::addPart(std::string part) {
|
|||
* @param [in] pData A message part being added.
|
||||
* @param [in] length The number of bytes being added.
|
||||
*/
|
||||
void NimBLEValue::addPart(uint8_t* pData, size_t length) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length);
|
||||
m_accumulation += std::string((char*) pData, length);
|
||||
void NimBLEValue::addPart(const uint8_t* pData, size_t length) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length);
|
||||
m_accumulation += std::string((char*) pData, length);
|
||||
} // addPart
|
||||
|
||||
|
||||
|
@ -53,9 +56,9 @@ void NimBLEValue::addPart(uint8_t* pData, size_t length) {
|
|||
* @brief Cancel the current accumulation.
|
||||
*/
|
||||
void NimBLEValue::cancel() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> cancel");
|
||||
m_accumulation = "";
|
||||
m_readOffset = 0;
|
||||
NIMBLE_LOGD(LOG_TAG, ">> cancel");
|
||||
m_accumulation = "";
|
||||
m_readOffset = 0;
|
||||
} // cancel
|
||||
|
||||
|
||||
|
@ -66,12 +69,12 @@ void NimBLEValue::cancel() {
|
|||
* we now have the complete message and commit the change as a unit.
|
||||
*/
|
||||
void NimBLEValue::commit() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> commit");
|
||||
// If there is nothing to commit, do nothing.
|
||||
if (m_accumulation.length() == 0) return;
|
||||
setValue(m_accumulation);
|
||||
m_accumulation = "";
|
||||
m_readOffset = 0;
|
||||
NIMBLE_LOGD(LOG_TAG, ">> commit");
|
||||
// If there is nothing to commit, do nothing.
|
||||
if (m_accumulation.length() == 0) return;
|
||||
setValue(m_accumulation);
|
||||
m_accumulation = "";
|
||||
m_readOffset = 0;
|
||||
} // commit
|
||||
|
||||
|
||||
|
@ -80,7 +83,7 @@ void NimBLEValue::commit() {
|
|||
* @return A pointer to the data.
|
||||
*/
|
||||
uint8_t* NimBLEValue::getData() {
|
||||
return (uint8_t*) m_value.data();
|
||||
return (uint8_t*) m_value.data();
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,7 +92,7 @@ uint8_t* NimBLEValue::getData() {
|
|||
* @return The length of the data in bytes.
|
||||
*/
|
||||
size_t NimBLEValue::getLength() {
|
||||
return m_value.length();
|
||||
return m_value.length();
|
||||
} // getLength
|
||||
|
||||
|
||||
|
@ -98,7 +101,7 @@ size_t NimBLEValue::getLength() {
|
|||
* @return The read offset into the read.
|
||||
*/
|
||||
uint16_t NimBLEValue::getReadOffset() {
|
||||
return m_readOffset;
|
||||
return m_readOffset;
|
||||
} // getReadOffset
|
||||
|
||||
|
||||
|
@ -106,7 +109,7 @@ uint16_t NimBLEValue::getReadOffset() {
|
|||
* @brief Get the current value.
|
||||
*/
|
||||
std::string NimBLEValue::getValue() {
|
||||
return m_value;
|
||||
return m_value;
|
||||
} // getValue
|
||||
|
||||
|
||||
|
@ -115,15 +118,15 @@ std::string NimBLEValue::getValue() {
|
|||
* @param [in] readOffset The offset into the read.
|
||||
*/
|
||||
void NimBLEValue::setReadOffset(uint16_t readOffset) {
|
||||
m_readOffset = readOffset;
|
||||
m_readOffset = readOffset;
|
||||
} // setReadOffset
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the current value.
|
||||
*/
|
||||
void NimBLEValue::setValue(std::string value) {
|
||||
m_value = value;
|
||||
void NimBLEValue::setValue(const std::string &value) {
|
||||
m_value = value;
|
||||
} // setValue
|
||||
|
||||
|
||||
|
@ -132,9 +135,9 @@ void NimBLEValue::setValue(std::string value) {
|
|||
* @param [in] pData The data for the current value.
|
||||
* @param [in] The length of the new current value.
|
||||
*/
|
||||
void NimBLEValue::setValue(uint8_t* pData, size_t length) {
|
||||
m_value = std::string((char*) pData, length);
|
||||
void NimBLEValue::setValue(const uint8_t* pData, size_t length) {
|
||||
m_value = std::string((char*) pData, length);
|
||||
} // setValue
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
|
@ -16,6 +16,10 @@
|
|||
#define MAIN_BLEVALUE_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
|
@ -23,24 +27,26 @@
|
|||
*/
|
||||
class NimBLEValue {
|
||||
public:
|
||||
NimBLEValue();
|
||||
void addPart(std::string part);
|
||||
void addPart(uint8_t* pData, size_t length);
|
||||
void cancel();
|
||||
void commit();
|
||||
uint8_t* getData();
|
||||
size_t getLength();
|
||||
uint16_t getReadOffset();
|
||||
std::string getValue();
|
||||
void setReadOffset(uint16_t readOffset);
|
||||
void setValue(std::string value);
|
||||
void setValue(uint8_t* pData, size_t length);
|
||||
NimBLEValue();
|
||||
void addPart(const std::string &part);
|
||||
void addPart(const uint8_t* pData, size_t length);
|
||||
void cancel();
|
||||
void commit();
|
||||
uint8_t* getData();
|
||||
size_t getLength();
|
||||
uint16_t getReadOffset();
|
||||
std::string getValue();
|
||||
void setReadOffset(uint16_t readOffset);
|
||||
void setValue(const std::string &value);
|
||||
void setValue(const uint8_t* pData, size_t length);
|
||||
|
||||
private:
|
||||
std::string m_accumulation;
|
||||
uint16_t m_readOffset;
|
||||
std::string m_value;
|
||||
std::string m_accumulation;
|
||||
uint16_t m_readOffset;
|
||||
std::string m_value;
|
||||
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif /* MAIN_BLEVALUE_H_ */
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
||||
|
||||
#ifndef __ESP_NIMBLE_CFG__
|
||||
#define __ESP_NIMBLE_CFG__
|
||||
#include "nimconfig.h"
|
||||
|
@ -470,7 +468,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_FLOW_CTRL_TX_ON_DISCONNECT
|
||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
|
|
|
@ -98,8 +98,8 @@ struct hci_conn_update;
|
|||
|
||||
#define BLE_GAP_INITIAL_CONN_LATENCY 0
|
||||
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
|
||||
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
|
||||
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
|
||||
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
|
||||
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
|
||||
|
||||
#define BLE_GAP_ROLE_MASTER 0
|
||||
#define BLE_GAP_ROLE_SLAVE 1
|
||||
|
@ -1783,6 +1783,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
|
|||
*/
|
||||
int ble_gap_unpair_oldest_peer(void);
|
||||
|
||||
/**
|
||||
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
|
||||
* peer received in input parameters is not deleted.
|
||||
*
|
||||
* @param peer_addr Address of the peer (not to be deleted)
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host HCI return code if the controller
|
||||
* rejected the request;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
|
||||
|
||||
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
|
||||
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
|
||||
|
||||
|
@ -1886,20 +1900,6 @@ struct ble_gap_event_listener {
|
|||
SLIST_ENTRY(ble_gap_event_listener) link;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that current
|
||||
* peer is not deleted.
|
||||
*
|
||||
* @param peer_addr Address of the current peer (not to be deleted)
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host HCI return code if the controller
|
||||
* rejected the request;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer);
|
||||
|
||||
/**
|
||||
* Registers listener for GAP events
|
||||
*
|
||||
|
|
|
@ -288,8 +288,6 @@ int ble_store_clear(void);
|
|||
|
||||
/*** Utility functions. */
|
||||
|
||||
int ble_store_clean_old_cccds(const ble_addr_t *curr_peer);
|
||||
|
||||
int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs,
|
||||
int *out_num_peers,
|
||||
int max_peers);
|
||||
|
|
|
@ -330,11 +330,8 @@ static inline void net_buf_simple_restore(struct os_mbuf *buf,
|
|||
buf->om_len = state->len;
|
||||
}
|
||||
|
||||
static inline void sys_memcpy_swap(void *destination, const void *source, size_t length)
|
||||
static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||
{
|
||||
u8_t *dst = destination;
|
||||
const u8_t *src = source;
|
||||
|
||||
__ASSERT(((src < dst && (src + length) <= dst) ||
|
||||
(src > dst && (dst + length) <= src)),
|
||||
"Source and destination buffers must not overlap");
|
||||
|
@ -342,7 +339,7 @@ static inline void sys_memcpy_swap(void *destination, const void *source, size_t
|
|||
src += length - 1;
|
||||
|
||||
for (; length > 0; length--) {
|
||||
*dst++ = *src--;
|
||||
*((u8_t *)dst++) = *((u8_t *)src--);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,31 +41,43 @@ modlog_dummy(const char *msg, ...)
|
|||
#endif
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
/// Uncomment these and comment out the 3 defines below to see NimBLE messages in Arduino.
|
||||
/*
|
||||
#define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \
|
||||
if (LOG_LOCAL_LEVEL >= level) esp_log_write(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "nimconfig.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||
|
||||
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
*/
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_DEBUG, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_DEBUG, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_INFO, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_INFO, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_WARN, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_WARN, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
|
||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
||||
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ void ble_gap_preempt(void);
|
|||
void ble_gap_preempt_done(void);
|
||||
|
||||
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
|
||||
void ble_gap_reset_state(int reason);
|
||||
int32_t ble_gap_timer(void);
|
||||
|
||||
int ble_gap_init(void);
|
||||
|
|
|
@ -33,6 +33,10 @@ int ble_hs_id_use_addr(uint8_t addr_type);
|
|||
void ble_hs_id_reset(void);
|
||||
void ble_hs_id_rnd_reset(void);
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type);
|
||||
int ble_hs_id_set_pseudo_rnd(const uint8_t *);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,9 @@ int ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addrtype,
|
|||
const uint8_t *irk);
|
||||
int ble_hs_pvcy_ensure_started(void);
|
||||
int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode);
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
bool ble_hs_pvcy_enabled(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
/*
|
||||
* An entry in the resolving list.
|
||||
*/
|
||||
struct ble_hs_resolv_entry {
|
||||
uint8_t rl_addr_type;
|
||||
uint8_t rl_local_irk[16];
|
||||
uint8_t rl_peer_irk[16];
|
||||
uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
|
||||
/* Persist peer records in NVS. XXX Need to handle this in `store` module */
|
||||
int ble_store_persist_peer_records(void);
|
||||
#endif
|
||||
|
||||
struct ble_hs_peer_sec {
|
||||
ble_addr_t peer_addr;
|
||||
uint8_t irk[16];
|
||||
uint8_t irk_present: 1;
|
||||
};
|
||||
/*
|
||||
* BLE host peer device record, this helps in storing peer RPA before bond is
|
||||
* created and IRKs are exchanged.
|
||||
*/
|
||||
struct ble_hs_dev_records {
|
||||
bool rec_used;
|
||||
uint8_t pseudo_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rand_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t identity_addr[BLE_DEV_ADDR_LEN];
|
||||
struct ble_hs_peer_sec peer_sec;
|
||||
};
|
||||
|
||||
/* Add a device to the resolving list */
|
||||
int ble_hs_resolv_list_add(uint8_t *cmdbuf);
|
||||
int ble_hs_gen_own_rpa_random(void);
|
||||
uint8_t *ble_hs_get_rpa_local(void);
|
||||
|
||||
/* Remove a device from the resolving list */
|
||||
int ble_hs_resolv_list_rmv(uint8_t, uint8_t *);
|
||||
/* Clear the resolving list and peer dev record */
|
||||
void ble_hs_resolv_list_clear_all(void);
|
||||
|
||||
/* Address resolution enable command */
|
||||
void ble_hs_resolv_enable(bool);
|
||||
|
||||
/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */
|
||||
struct ble_hs_resolv_entry *
|
||||
ble_hs_resolv_list_find(uint8_t *addr);
|
||||
|
||||
/* Returns true if host based RPA (privacy) is enabled */
|
||||
bool ble_host_rpa_enabled(void);
|
||||
|
||||
/* Searches peer device records (RPA) and fetches matching RL, peer_address
|
||||
* into input parameters if RL is found */
|
||||
void
|
||||
ble_rpa_replace_peer_params_with_rl(uint8_t *, uint8_t *, struct ble_hs_resolv_entry **);
|
||||
|
||||
int ble_rpa_resolv_add_peer_rec(uint8_t *);
|
||||
|
||||
struct ble_hs_dev_records *ble_rpa_get_peer_dev_records(void);
|
||||
int ble_rpa_get_num_peer_dev_records(void);
|
||||
void ble_rpa_set_num_peer_dev_records(int);
|
||||
int ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *);
|
||||
struct ble_hs_dev_records *ble_rpa_find_peer_dev_rec(uint8_t *);
|
||||
|
||||
/* Set the resolvable private address timeout */
|
||||
int ble_hs_resolv_set_rpa_tmo(uint16_t);
|
||||
|
||||
/* Resolve a resolvable private address */
|
||||
int ble_hs_resolv_rpa(uint8_t *rpa, uint8_t *irk);
|
||||
|
||||
/* Initialize resolv*/
|
||||
void ble_hs_resolv_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -399,6 +399,7 @@ int ble_sm_slave_initiate(uint16_t conn_handle);
|
|||
int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size,
|
||||
const uint8_t *ltk, uint16_t ediv,
|
||||
uint64_t rand_val, int auth);
|
||||
int ble_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data);
|
||||
int ble_sm_init(void);
|
||||
|
||||
#define BLE_SM_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \
|
||||
|
@ -419,6 +420,9 @@ int ble_sm_init(void);
|
|||
|
||||
#define ble_sm_init() 0
|
||||
|
||||
#define ble_sm_alg_encrypt(key, plaintext, enc_data) \
|
||||
BLE_HS_ENOTSUP
|
||||
|
||||
#endif
|
||||
|
||||
struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle);
|
||||
|
|
|
@ -66,11 +66,10 @@ ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
|||
|
||||
ble_hs_lock();
|
||||
|
||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
|
||||
&chan);
|
||||
if (chan == NULL) {
|
||||
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
|
||||
&chan);
|
||||
if (rc != 0) {
|
||||
os_mbuf_free_chain(txom);
|
||||
rc = BLE_HS_ENOTCONN;
|
||||
} else {
|
||||
ble_att_truncate_to_mtu(chan, txom);
|
||||
rc = ble_l2cap_tx(conn, chan, txom);
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
@ -1855,7 +1853,6 @@ ble_gap_update_timer(void)
|
|||
ble_hs_unlock();
|
||||
|
||||
if (entry != NULL) {
|
||||
ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
|
||||
ble_gap_update_entry_free(entry);
|
||||
}
|
||||
} while (entry != NULL);
|
||||
|
@ -5303,8 +5300,7 @@ ble_gap_unpair_oldest_peer(void)
|
|||
}
|
||||
|
||||
if (num_peers == 0) {
|
||||
return BLE_HS_ENOENT;
|
||||
//return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_gap_unpair(&oldest_peer_id_addr);
|
||||
|
@ -5316,14 +5312,14 @@ ble_gap_unpair_oldest_peer(void)
|
|||
}
|
||||
|
||||
int
|
||||
ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer)
|
||||
ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
|
||||
{
|
||||
ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers;
|
||||
int rc, i;
|
||||
|
||||
rc = ble_store_util_bonded_peers(
|
||||
&oldest_peer_id_addr[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -5333,21 +5329,16 @@ ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer)
|
|||
}
|
||||
|
||||
for (i = 0; i < num_peers; i++) {
|
||||
if (memcmp(curr_peer, &oldest_peer_id_addr[i], sizeof (ble_addr_t)) != 0) {
|
||||
if (ble_addr_cmp(peer_addr, &peer_id_addrs[i]) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < num_peers) {
|
||||
rc = ble_gap_unpair(&oldest_peer_id_addr[i]);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
if (i >= num_peers) {
|
||||
return BLE_HS_ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ble_gap_unpair(&peer_id_addrs[i]);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5371,7 +5362,8 @@ ble_gap_passkey_event(uint16_t conn_handle,
|
|||
}
|
||||
|
||||
void
|
||||
ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
|
||||
ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||
int security_restored, int bonded)
|
||||
{
|
||||
#if !NIMBLE_BLE_SM
|
||||
return;
|
||||
|
@ -5387,17 +5379,24 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
|
|||
ble_gap_event_listener_call(&event);
|
||||
ble_gap_call_conn_event_cb(&event, conn_handle);
|
||||
|
||||
/* H2zero mod
|
||||
If bonding is not enabled don't store cccd data
|
||||
if (status == 0) {
|
||||
*/
|
||||
if (status == 0 && ble_hs_cfg.sm_bonding) {
|
||||
/* End mod */
|
||||
if (security_restored) {
|
||||
ble_gatts_bonding_restored(conn_handle);
|
||||
} else {
|
||||
ble_gatts_bonding_established(conn_handle);
|
||||
}
|
||||
if (status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If encryption succeded and encryption has been restored for bonded device,
|
||||
* notify gatt server so it has chance to send notification/indication if needed.
|
||||
*/
|
||||
if (security_restored) {
|
||||
ble_gatts_bonding_restored(conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is fresh pairing and bonding has been established,
|
||||
* notify gatt server about that so previous subscriptions (before bonding)
|
||||
* can be stored.
|
||||
*/
|
||||
if (bonded) {
|
||||
ble_gatts_bonding_established(conn_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
|
|||
struct ble_gap_upd_params *params);
|
||||
void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt);
|
||||
void ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||
int security_restored);
|
||||
int security_restored, int bonded);
|
||||
void ble_gap_passkey_event(uint16_t conn_handle,
|
||||
struct ble_gap_passkey_params *passkey_params);
|
||||
void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
|
||||
|
|
|
@ -1689,30 +1689,29 @@ ble_gatts_bonding_established(uint16_t conn_handle)
|
|||
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
BLE_HS_DBG_ASSERT(conn != NULL);
|
||||
BLE_HS_DBG_ASSERT(conn->bhc_sec_state.bonded);
|
||||
|
||||
if (conn->bhc_sec_state.bonded) {
|
||||
cccd_value.peer_addr = conn->bhc_peer_addr;
|
||||
gatt_srv = &conn->bhc_gatt_svr;
|
||||
cccd_value.peer_addr = conn->bhc_peer_addr;
|
||||
gatt_srv = &conn->bhc_gatt_svr;
|
||||
|
||||
for (i = 0; i < gatt_srv->num_clt_cfgs; ++i) {
|
||||
clt_cfg = (gatt_srv->clt_cfgs + i);
|
||||
if (clt_cfg == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < gatt_srv->num_clt_cfgs; ++i) {
|
||||
clt_cfg = (gatt_srv->clt_cfgs + i);
|
||||
if (clt_cfg == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clt_cfg->flags != 0) {
|
||||
cccd_value.chr_val_handle = clt_cfg->chr_val_handle;
|
||||
cccd_value.flags = clt_cfg->flags;
|
||||
cccd_value.value_changed = 0;
|
||||
if (clt_cfg->flags != 0) {
|
||||
cccd_value.chr_val_handle = clt_cfg->chr_val_handle;
|
||||
cccd_value.flags = clt_cfg->flags;
|
||||
cccd_value.value_changed = 0;
|
||||
|
||||
/* Store write use ble_hs_lock */
|
||||
ble_hs_unlock();
|
||||
ble_store_write_cccd(&cccd_value);
|
||||
ble_hs_lock();
|
||||
/* Store write use ble_hs_lock */
|
||||
ble_hs_unlock();
|
||||
ble_store_write_cccd(&cccd_value);
|
||||
ble_hs_lock();
|
||||
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
BLE_HS_DBG_ASSERT(conn != NULL);
|
||||
}
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
BLE_HS_DBG_ASSERT(conn != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -410,15 +410,13 @@ ble_hs_conn_addrs(const struct ble_hs_conn *conn,
|
|||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
/* RPA: Override peer address information. */
|
||||
struct ble_hs_resolv_entry *rl = NULL;
|
||||
|
||||
ble_addr_t bhc_peer_addr;
|
||||
bhc_peer_addr.type = conn->bhc_peer_addr.type;
|
||||
memcpy(bhc_peer_addr.val, conn->bhc_peer_addr.val, BLE_DEV_ADDR_LEN);
|
||||
|
||||
struct ble_hs_resolv_entry *rl = NULL;
|
||||
rl = ble_hs_resolv_list_find(bhc_peer_addr.val);
|
||||
if (rl != NULL) {
|
||||
addrs->peer_ota_addr = conn->bhc_peer_rpa_addr;
|
||||
memcpy(addrs->peer_id_addr.val, rl->rl_identity_addr, BLE_DEV_ADDR_LEN);
|
||||
addrs->peer_id_addr.type = rl->rl_addr_type;
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ ble_hs_hci_process_ack(uint16_t expected_opcode,
|
|||
}
|
||||
|
||||
if (rc == 0) {
|
||||
if (params_buf == NULL) {
|
||||
if (params_buf == NULL || out_ack->bha_params == NULL) {
|
||||
out_ack->bha_params_len = 0;
|
||||
} else {
|
||||
if (out_ack->bha_params_len > params_buf_len) {
|
||||
|
|
|
@ -337,14 +337,6 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
|
|||
struct ble_hs_resolv_entry *rl = NULL;
|
||||
ble_rpa_replace_peer_params_with_rl(evt.peer_addr,
|
||||
&evt.peer_addr_type, &rl);
|
||||
if (rl == NULL) {
|
||||
if (ble_rpa_resolv_add_peer_rec(evt.peer_addr) != 0) {
|
||||
BLE_HS_LOG(DEBUG, "Memory unavailable for new peer record\n");
|
||||
}
|
||||
}
|
||||
/* Set the correct RPA for logging */
|
||||
memcpy(evt.peer_rpa, data + 6, BLE_DEV_ADDR_LEN);
|
||||
|
||||
#endif
|
||||
} else {
|
||||
memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN);
|
||||
|
@ -441,14 +433,6 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
|||
memcpy(desc.addr.val, data + off, 6);
|
||||
off += 6;
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
if (ble_host_rpa_enabled()) {
|
||||
/* Now RPA to be resolved here, since controller is unaware of the
|
||||
* address is RPA */
|
||||
ble_rpa_replace_peer_params_with_rl(desc.addr.val,
|
||||
&desc.addr.type, NULL);
|
||||
}
|
||||
#endif
|
||||
desc.length_data = data[off];
|
||||
++off;
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
|||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||
struct ble_hs_conn **out_conn,
|
||||
struct ble_l2cap_chan **out_chan)
|
||||
|
@ -66,7 +66,9 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
|||
int rc;
|
||||
|
||||
rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
|
||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (out_conn != NULL) {
|
||||
*out_conn = conn;
|
||||
|
@ -74,6 +76,8 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
|||
if (out_chan != NULL) {
|
||||
*out_chan = chan;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
|
|
|
@ -115,9 +115,9 @@ int ble_hs_hci_evt_acl_process(struct os_mbuf *om);
|
|||
int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
||||
struct ble_hs_conn **out_conn,
|
||||
struct ble_l2cap_chan **out_chan);
|
||||
void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||
struct ble_hs_conn **out_conn,
|
||||
struct ble_l2cap_chan **out_chan);
|
||||
int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||
struct ble_hs_conn **out_conn,
|
||||
struct ble_l2cap_chan **out_chan);
|
||||
uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type);
|
||||
int ble_hs_misc_restore_irks(void);
|
||||
|
||||
|
|
|
@ -473,8 +473,13 @@ ble_l2cap_sig_update(uint16_t conn_handle,
|
|||
STATS_INC(ble_l2cap_stats, update_init);
|
||||
|
||||
ble_hs_lock();
|
||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||
&conn, &chan);
|
||||
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||
&conn, &chan);
|
||||
if (rc != 0) {
|
||||
ble_hs_unlock();
|
||||
goto done;
|
||||
}
|
||||
|
||||
master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
|
||||
ble_hs_unlock();
|
||||
|
||||
|
|
|
@ -28,9 +28,11 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
|||
int rc;
|
||||
|
||||
ble_hs_lock();
|
||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||
&conn, &chan);
|
||||
rc = ble_l2cap_tx(conn, chan, txom);
|
||||
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||
&conn, &chan);
|
||||
if (rc == 0) {
|
||||
rc = ble_l2cap_tx(conn, chan, txom);
|
||||
}
|
||||
ble_hs_unlock();
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -538,6 +538,11 @@ ble_sm_persist_keys(struct ble_sm_proc *proc)
|
|||
case BLE_ADDR_PUBLIC:
|
||||
case BLE_ADDR_PUBLIC_ID:
|
||||
conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID;
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
/* In case of Host based privacy, we should not be changing
|
||||
* peer address type to BLE_ADDR_PUBLIC_ID */
|
||||
conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case BLE_ADDR_RANDOM:
|
||||
|
@ -944,7 +949,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
|
|||
|
||||
if (res->enc_cb) {
|
||||
BLE_HS_DBG_ASSERT(proc == NULL || rm);
|
||||
ble_gap_enc_event(conn_handle, res->app_status, res->restore);
|
||||
ble_gap_enc_event(conn_handle, res->app_status, res->restore, res->bonded);
|
||||
}
|
||||
|
||||
if (res->app_status == 0 &&
|
||||
|
@ -1198,6 +1203,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
|||
|
||||
ble_hs_unlock();
|
||||
|
||||
res.bonded = bonded;
|
||||
ble_sm_process_result(conn_handle, &res);
|
||||
}
|
||||
|
||||
|
@ -1793,8 +1799,21 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||
*/
|
||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
|
||||
if (proc != NULL) {
|
||||
/* Pairing already in progress; abort old procedure and start new. */
|
||||
/* XXX: Check the spec on this. */
|
||||
/* Fail if procedure is in progress unless we sent a slave security
|
||||
* request to peer.
|
||||
*/
|
||||
if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) {
|
||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
||||
ble_hs_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove the procedure because it was allocated when
|
||||
* sending the Slave Security Request and it will be allocated
|
||||
* again later in this method. We should probably refactor this
|
||||
* in the future.
|
||||
*/
|
||||
ble_sm_proc_remove(proc, prev);
|
||||
ble_sm_proc_free(proc);
|
||||
}
|
||||
|
@ -2459,7 +2478,7 @@ ble_sm_timer(void)
|
|||
* procedures without reconnect.
|
||||
*/
|
||||
while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
|
||||
ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0);
|
||||
ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0, 0);
|
||||
|
||||
STAILQ_REMOVE_HEAD(&exp_list, next);
|
||||
ble_sm_proc_free(proc);
|
||||
|
|
|
@ -52,14 +52,19 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
|||
{
|
||||
struct ble_l2cap_chan *chan;
|
||||
struct ble_hs_conn *conn;
|
||||
int rc;
|
||||
|
||||
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
|
||||
|
||||
STATS_INC(ble_l2cap_stats, sm_tx);
|
||||
|
||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
|
||||
&conn, &chan);
|
||||
return ble_l2cap_tx(conn, chan, txom);
|
||||
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
|
||||
&conn, &chan);
|
||||
if (rc == 0) {
|
||||
rc = ble_l2cap_tx(conn, chan, txom);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if NIMBLE_BLE_SM
|
||||
|
|
|
@ -277,10 +277,10 @@ struct ble_sm_result {
|
|||
uint8_t sm_err;
|
||||
struct ble_gap_passkey_params passkey_params;
|
||||
void *state_arg;
|
||||
unsigned execute:1;
|
||||
unsigned enc_cb:1;
|
||||
unsigned persist_keys:1;
|
||||
unsigned restore:1;
|
||||
unsigned execute : 1;
|
||||
unsigned enc_cb : 1;
|
||||
unsigned bonded : 1;
|
||||
unsigned restore : 1;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "host/ble_store.h"
|
||||
#include "ble_hs_priv.h"
|
||||
#include "ble_hs_resolv_priv.h"
|
||||
|
||||
struct ble_store_util_peer_set {
|
||||
ble_addr_t *peer_id_addrs;
|
||||
|
@ -27,12 +28,6 @@ struct ble_store_util_peer_set {
|
|||
int status;
|
||||
};
|
||||
|
||||
struct ble_store_util_peer_cccd_set {
|
||||
struct ble_store_util_peer_set peer_set;
|
||||
ble_addr_t *curr_peer_addr;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
ble_store_util_iter_unique_peer(int obj_type,
|
||||
union ble_store_value *val,
|
||||
|
@ -65,42 +60,6 @@ ble_store_util_iter_unique_peer(int obj_type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_store_util_iter_peer_cccd(int obj_type,
|
||||
union ble_store_value *val,
|
||||
void *arg)
|
||||
{
|
||||
struct ble_store_util_peer_cccd_set *set;
|
||||
int i;
|
||||
|
||||
set = arg;
|
||||
|
||||
/* Do nothing if this peer is a duplicate or current peer */
|
||||
for (i = 0; i < set->peer_set.num_peers; i++) {
|
||||
if (ble_addr_cmp(set->peer_set.peer_id_addrs + i, &val->cccd.peer_addr) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (set->curr_peer_addr != NULL) {
|
||||
if (ble_addr_cmp(set->curr_peer_addr, &val->cccd.peer_addr) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set->peer_set.num_peers >= set->peer_set.max_peers) {
|
||||
/* Overflow; abort the iterate procedure. */
|
||||
set->peer_set.status = BLE_HS_ENOMEM;
|
||||
return 1;
|
||||
}
|
||||
|
||||
set->peer_set.peer_id_addrs[set->peer_set.num_peers] = val->cccd.peer_addr;
|
||||
set->peer_set.num_peers++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the set of peer addresses for which a bond has been established.
|
||||
*
|
||||
|
@ -141,51 +100,6 @@ ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the set of peer addresses for which CCCDs are subscribed.
|
||||
*
|
||||
* @param out_peer_id_addrs On success, the set of peer addresses
|
||||
* gets written here.
|
||||
* @param out_num_peers On success, the number of peer addresses gets written
|
||||
* here.
|
||||
* @param max_peers The capacity of the destination buffer.
|
||||
*
|
||||
* @param curr_peer_addrs Current peer's address, ignore if NULL
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOMEM if the destination buffer is too
|
||||
* small;
|
||||
* Other nonzero on error.
|
||||
*/
|
||||
static int
|
||||
ble_store_util_subscribed_cccds(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
||||
int max_peers, ble_addr_t *curr_peer_addr)
|
||||
{
|
||||
struct ble_store_util_peer_cccd_set set = {
|
||||
.peer_set = {
|
||||
.peer_id_addrs = out_peer_id_addrs,
|
||||
.num_peers = 0,
|
||||
.max_peers = max_peers,
|
||||
.status = 0,
|
||||
},
|
||||
.curr_peer_addr = curr_peer_addr,
|
||||
};
|
||||
int rc;
|
||||
|
||||
rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_CCCD,
|
||||
ble_store_util_iter_peer_cccd,
|
||||
&set);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
if (set.peer_set.status != 0) {
|
||||
return set.peer_set.status;
|
||||
}
|
||||
|
||||
*out_num_peers = set.peer_set.num_peers;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all entries from the store that are attached to the specified peer
|
||||
* address. This function deletes security entries and CCCD records.
|
||||
|
@ -222,6 +136,25 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
|
|||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||
struct ble_hs_dev_records *peer_rec =
|
||||
ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val);
|
||||
|
||||
if (peer_rec != NULL) {
|
||||
rc = ble_hs_resolv_list_rmv(peer_rec->peer_sec.peer_addr.type,
|
||||
peer_rec->peer_sec.peer_addr.val);
|
||||
if (rc != 0) {
|
||||
/* We can't do anything much here, continue with removing from peer_record */
|
||||
BLE_HS_LOG(DEBUG, "Peer Device was not removed from RL \n");
|
||||
}
|
||||
|
||||
rc = ble_rpa_remove_peer_dev_rec(peer_rec);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -305,63 +238,6 @@ ble_store_util_delete_oldest_peer(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete CCCDs of unbonded devices.
|
||||
*
|
||||
* @param curr_peer Current peer's address (not to delete), ignore
|
||||
* ignore if NULL
|
||||
*
|
||||
* @return 0 on success;
|
||||
* nonzero on error.
|
||||
*/
|
||||
int
|
||||
ble_store_clean_old_cccds(const ble_addr_t *curr_peer)
|
||||
{
|
||||
ble_addr_t peer_cccd_addrs[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
|
||||
ble_addr_t peer_bonded_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_bonded_peers, num_cccd_peers;
|
||||
int i, j, rc;
|
||||
|
||||
rc = ble_store_util_subscribed_cccds(&peer_cccd_addrs[0], &num_cccd_peers,
|
||||
MYNEWT_VAL(BLE_STORE_MAX_CCCDS),
|
||||
(void *) curr_peer);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_bonded_addrs[0], &num_bonded_peers,
|
||||
MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
union ble_store_key key = {0};
|
||||
/* Init rc to BLE_HS_ENOENT to indicate no CCCD is deleted */
|
||||
rc = BLE_HS_ENOENT;
|
||||
|
||||
for (i = 0; i < num_cccd_peers; i++) {
|
||||
key.cccd.peer_addr = peer_cccd_addrs[i];
|
||||
|
||||
for (j = 0; j < num_bonded_peers; j++) {
|
||||
if (memcmp(&peer_cccd_addrs[i], &peer_bonded_addrs[j],
|
||||
sizeof(ble_addr_t)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < num_bonded_peers) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CCCD, &key);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Round-robin status callback. If a there is insufficient storage capacity
|
||||
* for a new record, delete the oldest bond and proceed with the persist
|
||||
|
@ -374,33 +250,18 @@ ble_store_clean_old_cccds(const ble_addr_t *curr_peer)
|
|||
int
|
||||
ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
||||
{
|
||||
int rc = BLE_HS_EUNKNOWN;
|
||||
switch (event->event_code) {
|
||||
case BLE_STORE_EVENT_OVERFLOW:
|
||||
switch (event->overflow.obj_type) {
|
||||
case BLE_STORE_OBJ_TYPE_OUR_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||
return ble_gap_unpair_oldest_peer();
|
||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||
/* Try to remove unbonded CCCDs first */
|
||||
if ((rc = ble_store_clean_old_cccds((void *) &event->overflow.value->cccd.peer_addr)) == BLE_HS_ENOENT) {
|
||||
/* No unbonded CCCDs found to delete, try unpairing oldest peer
|
||||
* except current peer */
|
||||
return ble_gap_unpair_oldest_except_curr((void *) &event->overflow.value->cccd.peer_addr);
|
||||
}
|
||||
return rc;
|
||||
case BLE_STORE_OBJ_TYPE_OUR_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||
return ble_gap_unpair_oldest_peer();
|
||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||
/* Try unpairing oldest peer except current peer */
|
||||
return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr);
|
||||
|
||||
default:
|
||||
return BLE_HS_EUNKNOWN;
|
||||
|
||||
/* case BLE_STORE_OBJ_TYPE_OUR_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||
return ble_gap_unpair_oldest_peer();
|
||||
|
||||
default:
|
||||
return BLE_HS_EUNKNOWN;
|
||||
*/
|
||||
default:
|
||||
return BLE_HS_EUNKNOWN;
|
||||
}
|
||||
|
||||
case BLE_STORE_EVENT_FULL:
|
||||
|
|
|
@ -210,11 +210,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value)
|
|||
err = get_nvs_matching_index(&p_dev_rec, value, num_value,
|
||||
sizeof(struct ble_hs_dev_records));
|
||||
} else {
|
||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
if (obj_type != BLE_STORE_OBJ_TYPE_CCCD) {
|
||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
||||
sizeof(struct ble_store_value_sec));
|
||||
} else {
|
||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
||||
err = get_nvs_matching_index(&cur.cccd, value, num_value,
|
||||
sizeof(struct ble_store_value_cccd));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
/* Modifications copyright (C) 2020 Ryan Powell*/
|
||||
|
||||
#ifndef _NIMBLE_NPL_H_
|
||||
#define _NIMBLE_NPL_H_
|
||||
|
||||
|
@ -26,6 +24,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "nimconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
||||
#ifndef _NIMBLE_PORT_H
|
||||
#define _NIMBLE_PORT_H
|
||||
|
||||
|
|
|
@ -1,17 +1,100 @@
|
|||
#pragma once
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE_0 1
|
||||
|
||||
#include "sdkconfig.h"
|
||||
/** For ESP-IDF compatibility
|
||||
*
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig)*/
|
||||
#if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ENABLED)
|
||||
#define CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_DEBUG)
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
#endif
|
||||
|
||||
#else // Using Arduino
|
||||
|
||||
/***********************************************
|
||||
* Arduino config options
|
||||
**********************************************/
|
||||
|
||||
/** Comment out if not using NimBLE Client functions
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
|
||||
/** Comment out if not using NimBLE Scan functions
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
|
||||
/** Comment out if not using NimBLE Server functions
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL // Tasmota
|
||||
|
||||
/** Comment out if not using NimBLE Advertising functions
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_BROADCASTER // Tasmota
|
||||
|
||||
/** Uncomment to see debug log messages from the NimBLE host
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/** Uncomment to see NimBLE host return codes as text debug log messages.
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/** Uncomment to see GAP event codes as text in debug log messages.
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/** Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
|
||||
/** Sets the core NimBLE host runs on */
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
|
||||
/** Sets the stack size for the NimBLE host task */
|
||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL 1
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL 1
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER 1
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER 1
|
||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
||||
|
||||
/** Sets the number of simultaneous connections (esp controller max is 9) */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
|
||||
/** Sets the number of devices allowed to store/bond with */
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3 // Tasmota
|
||||
|
||||
/** Sets the number of CCCD's to store per bonded device */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 3 // Tasmota
|
||||
|
||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 0 // Tasmota
|
||||
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
|
||||
#define CONFIG_BT_NIMBLE_SM_SC 1
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
|
@ -29,6 +112,23 @@
|
|||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
#define CONFIG_BT_ENABLED 1
|
||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1
|
||||
#define CONFIG_BT_NIMBLE_DEBUG 0
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
|
||||
/** Do not comment out */
|
||||
#ifndef CONFIG_BT_ENABLED
|
||||
#define CONFIG_BT_ENABLED
|
||||
#endif
|
||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
/** Cannot use client without scan */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
/** Cannot use server without advertise */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "nimconfig.h"
|
||||
|
@ -32,6 +30,8 @@ IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
|
|||
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return malloc(size);
|
||||
#endif
|
||||
|
@ -43,6 +43,8 @@ IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
|
|||
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||
return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return calloc(n, size);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue