mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2025-06-25 09:21:42 +02:00
Compare commits
52 Commits
2.0.3
...
bugfix/onr
Author | SHA1 | Date | |
---|---|---|---|
9ce2eec0cb | |||
723cdf0a66 | |||
148087c508 | |||
88c5d0c7b7 | |||
a6c03a2aaa | |||
9df8445241 | |||
e5f4d52a5a | |||
7ef247c8db | |||
c582c8c67e | |||
74b5c59887 | |||
60efffdf2b | |||
b6379848ae | |||
b29919df96 | |||
052c0a0455 | |||
784e6f30fa | |||
5490cef129 | |||
459e8c9fcd | |||
ffa8414747 | |||
8130f88be8 | |||
c39e288c3e | |||
8158a16fbf | |||
57fe9cb77f | |||
e6249623d5 | |||
a9578637cb | |||
765193f223 | |||
3b019a0c9c | |||
5ac7272f5d | |||
4d8ab46e56 | |||
8468bb50dc | |||
1088ad8fe1 | |||
0b543d9f62 | |||
fa468d360a | |||
2759b1b69d | |||
1a0b7a8e31 | |||
1d01af0f8c | |||
f7d3c5e0c2 | |||
bc2bc35a8a | |||
15cb6bc7c6 | |||
aae70dfd21 | |||
ad12a48e9e | |||
09297fb72a | |||
b50a1b50b1 | |||
954ba0b5a7 | |||
015217c764 | |||
9a1ae677b8 | |||
6ee5174ba0 | |||
e843c6811c | |||
0d13044703 | |||
cfca3e7500 | |||
3c80c950ae | |||
182e3bb8a3 | |||
a627007a31 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
docs/doxydocs
|
||||
docs/doxydocs
|
||||
|
75
CHANGELOG.md
75
CHANGELOG.md
@ -1,6 +1,81 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [2.2.1] 2025-02-28
|
||||
|
||||
## Fixed
|
||||
- Added back `NimBLEClient::connect` overload with `NimBLEAdvertisedDevice` parameter to resolve connection error due to NULL address.
|
||||
- Crash caused by returning invalid vector entry when retrieving remote descriptors.
|
||||
|
||||
## [2.2.0] 2025-02-24
|
||||
|
||||
## Fixed
|
||||
- Crash when calling `NimBLEClient::DiscoverAttributes`.
|
||||
|
||||
## Added
|
||||
- Conditional macros for logging.
|
||||
- `NimBLEDeviceCallbacks` class with a callback for handling bond storage.
|
||||
|
||||
## [2.1.1] 2025-01-26
|
||||
|
||||
## Fixed
|
||||
- remote descriptor discovery error when no descriptors exist.
|
||||
- scan filter settings not enabled for esp32s3/c3.
|
||||
- remote descriptor discovery returning more than the desired descriptor.
|
||||
|
||||
## [2.1.0] 2025-01-12
|
||||
|
||||
## Fixed
|
||||
- Crash when retrieving descriptors if more than one exists.
|
||||
- Incorrect TX power value being advertised.
|
||||
- New user guide code for 2.x
|
||||
- Potential race condition if `NimBLEScan::clearResults1 is called from multiple tasks.
|
||||
|
||||
## Changed
|
||||
- If privacy is not enabled identity keys will not be shared.
|
||||
- `NimBLEDevice::setPower` and `NimBLEDevice::getPower` now take an additional parameter `NimBLETxPowerType` to set/get the power level for different operations.
|
||||
|
||||
## Added
|
||||
- Config option `CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER`, if defined will remove the ":" delimiter from the BLE address string.
|
||||
- Config option `CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE` if defined will make the BLE address strings uppercase.
|
||||
|
||||
## [2.0.3] 2025-01-05
|
||||
|
||||
## Fixed
|
||||
- Unused variable warning when log level is below info.
|
||||
- Build error missing definition of CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT in platformio.
|
||||
- Race condition in `NimBLEScan` that can cause a crash due to heap corruption if `NimBLEScan::stop` is called from the `onResult` callback.
|
||||
- Advertisement data not set if scan response is enabled after the data is set.
|
||||
- `NimBLECharacteristic`/`NimBLEDescriptor` not able to update their values in the `onRead` callback.
|
||||
- Too short of a timeout being requested in NimBLE_Server example leading to frequent disconnects.
|
||||
|
||||
## Changed
|
||||
- `NimBLEHIDDevice` now allows for the same report ID in multiple input/output/feature reports.
|
||||
|
||||
## Added
|
||||
- Config for custom log colors pre level.
|
||||
- Error logs in the case that NIMBLE_CPP_DEBUG_ASSERT is not defined.
|
||||
- Error logs when setting advertisement data fails.
|
||||
- Missing documentation in the migration guide about enabling automatic advertising on disconnect, which was disabled by default in 2.x.
|
||||
|
||||
## [2.0.2] 2024-12-21
|
||||
|
||||
## Fixed
|
||||
- Compile error when only advertising role is enabled.
|
||||
- Possible crash if bonded client reconnects.
|
||||
|
||||
## Changed
|
||||
- `NimBLEHIDDevice` can now create more than one in/out/feature report map.
|
||||
|
||||
## [2.0.1] 2024-12-16
|
||||
|
||||
## Fixed
|
||||
- `NimBLEHIDDevice::getOutputReport` will now return the correct characteristic.
|
||||
- Compile error when central is disabled, class `NimBLEServer` has no member named `m_pClient`.
|
||||
|
||||
## Changed
|
||||
- Added missing includes for `NimBLEConnInfo` and `NimBLEUtils` to `NimBLEDevice.h`.
|
||||
|
||||
## [2.0.0] 2024-12-14
|
||||
|
||||
## **Breaking changes**
|
||||
|
127
Kconfig
127
Kconfig
@ -26,6 +26,113 @@ config NIMBLE_CPP_LOG_LEVEL
|
||||
default 3 if NIMBLE_CPP_LOG_LEVEL_INFO
|
||||
default 4 if NIMBLE_CPP_LOG_LEVEL_DEBUG
|
||||
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR
|
||||
bool "Enable log color override."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will allow NimBLE log levels to have
|
||||
specific colors assigned.
|
||||
|
||||
menu "NIMBLE Log Override Colors"
|
||||
depends on NIMBLE_CPP_LOG_OVERRIDE_COLOR
|
||||
|
||||
choice NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR
|
||||
prompt "NimBLE CPP log override color Error"
|
||||
default NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_NONE
|
||||
help
|
||||
Select NimBLE CPP log override error color.
|
||||
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_NONE
|
||||
bool "None"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_BLACK
|
||||
bool "Black"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_RED
|
||||
bool "Red"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_GREEN
|
||||
bool "Green"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_YELLOW
|
||||
bool "Yellow"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_BLUE
|
||||
bool "Blue"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_PURPLE
|
||||
bool "Purple"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_CYAN
|
||||
bool "Cyan"
|
||||
endchoice #NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR
|
||||
|
||||
choice NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN
|
||||
prompt "NimBLE CPP log override color Warning"
|
||||
default NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_NONE
|
||||
help
|
||||
Select NimBLE CPP log override warning color.
|
||||
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_NONE
|
||||
bool "None"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_BLACK
|
||||
bool "Black"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_RED
|
||||
bool "Red"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_GREEN
|
||||
bool "Green"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_YELLOW
|
||||
bool "Yellow"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_BLUE
|
||||
bool "Blue"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_PURPLE
|
||||
bool "Purple"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_CYAN
|
||||
bool "Cyan"
|
||||
endchoice #NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN
|
||||
|
||||
choice NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO
|
||||
prompt "NimBLE CPP log override color Info"
|
||||
default NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_NONE
|
||||
help
|
||||
Select NimBLE CPP log override info color.
|
||||
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_NONE
|
||||
bool "None"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_BLACK
|
||||
bool "Black"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_RED
|
||||
bool "Red"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_GREEN
|
||||
bool "Green"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_YELLOW
|
||||
bool "Yellow"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_BLUE
|
||||
bool "Blue"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_PURPLE
|
||||
bool "Purple"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_CYAN
|
||||
bool "Cyan"
|
||||
endchoice #NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO
|
||||
|
||||
choice NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG
|
||||
prompt "NimBLE CPP log override color Debug"
|
||||
default NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_NONE
|
||||
help
|
||||
Select NimBLE CPP log override debug color.
|
||||
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_NONE
|
||||
bool "None"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_BLACK
|
||||
bool "Black"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_RED
|
||||
bool "Red"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_GREEN
|
||||
bool "Green"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_YELLOW
|
||||
bool "Yellow"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_BLUE
|
||||
bool "Blue"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_PURPLE
|
||||
bool "Purple"
|
||||
config NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_CYAN
|
||||
bool "Cyan"
|
||||
endchoice #NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG
|
||||
endmenu
|
||||
|
||||
config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
bool "Show NimBLE return codes as text in debug log."
|
||||
default "n"
|
||||
@ -50,6 +157,20 @@ config NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
|
||||
while scanning as text messages in the debug log.
|
||||
This will use approximately 250 bytes of flash memory.
|
||||
|
||||
config NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
|
||||
bool "Exclude colon characters when printing address."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will format MAC addresses without
|
||||
colon characters when printing.
|
||||
|
||||
config NIMBLE_CPP_ADDR_FMT_UPPERCASE
|
||||
bool "Use uppercase letters when printing address."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will format MAC addresses in
|
||||
uppercase letters when printing.
|
||||
|
||||
config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||
bool "Enable timestamps to be stored with attribute values."
|
||||
default "n"
|
||||
@ -77,12 +198,12 @@ config NIMBLE_CPP_DEBUG_ASSERT_ENABLED
|
||||
This will use approximately 1kB of flash memory.
|
||||
|
||||
config NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
|
||||
int "FreeRTOS task block bit"
|
||||
int "FreeRTOS task block bit."
|
||||
default 31
|
||||
help
|
||||
Configure the bit to set in the task notification value when a task is blocked waiting for an event.
|
||||
This should be set to a bit that is not used by other notifications in the system.
|
||||
|
||||
|
||||
#
|
||||
# BT config
|
||||
#
|
||||
@ -130,4 +251,4 @@ if IDF_TARGET_ESP32P4
|
||||
endchoice
|
||||
endif
|
||||
|
||||
endmenu
|
||||
endmenu
|
2
NOTICE
2
NOTICE
@ -1,6 +1,6 @@
|
||||
esp-nimble-cpp
|
||||
NimBLE-Arduino
|
||||
Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
|
||||
The Initial Developer of some parts of this library, which are copied from,
|
||||
|
@ -65,7 +65,8 @@ This returns a pointer to `const ble_addr_t` instead of a pointer to the address
|
||||
## Server
|
||||
- `NimBLEServer::disconnect` now returns `bool`, true = success, instead of `int` to be consistent with the rest of the library.
|
||||
- `NimBLEServerCallbacks::onMTUChanged` renamed to `NimBLEServerCallbacks::onMTUChange` to be consistent with the client callback.
|
||||
- `NimBLEServer::getPeerIDInfo` renamed to `NimBLEServer::getPeerInfoByHandle` to better describe it's use.
|
||||
- `NimBLEServer::getPeerIDInfo` renamed to `NimBLEServer::getPeerInfoByHandle` to better describe it's use.
|
||||
- Advertising is no longer automatically restarted when a peer disconnects, to re-enable this feature either call `NimBLEServer::advertiseOnDisconnect(true);` after creating the server or manually restart advertising in the `onDisconnect` callback.
|
||||
<br/>
|
||||
|
||||
### Services
|
||||
|
@ -48,7 +48,7 @@ PROJECT_NAME = esp-nimble-cpp
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2.0.0
|
||||
PROJECT_NUMBER = 2.2.1
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
@ -37,9 +37,7 @@ For this example we will keep it simple and use a 16 bit value: ABCD.
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
@ -79,9 +77,7 @@ The function call will simply be `pService->createCharacteristic("1234");`
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
@ -99,12 +95,13 @@ There are many different types you can send as parameters for the value but for
|
||||
`pCharacteristic->setValue("Hello BLE");`
|
||||
|
||||
Next we need to advertise for connections.
|
||||
To do this we create an instance of `NimBLEAdvertising` add our service to it (optional) and start advertisng.
|
||||
To do this we create an instance of `NimBLEAdvertising` add our service to it (optional) and start advertising.
|
||||
|
||||
**The code for this will be:**
|
||||
```
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); // create advertising instance
|
||||
pAdvertising->addServiceUUID("ABCD"); // tell advertising the UUID of our service
|
||||
pAdvertising->addServiceUUID("ABCD"); // advertise the UUID of our service
|
||||
pAdvertising->setName("NimBLE"); // advertise the device name
|
||||
pAdvertising->start(); // start advertising
|
||||
```
|
||||
That's it, this will be enough to create a BLE server with a service and a characteristic and advertise for client connections.
|
||||
@ -113,9 +110,7 @@ That's it, this will be enough to create a BLE server with a service and a chara
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
@ -126,7 +121,8 @@ void app_main(void)
|
||||
pCharacteristic->setValue("Hello BLE");
|
||||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID("ABCD");
|
||||
pAdvertising->addServiceUUID("ABCD"); // advertise the UUID of our service
|
||||
pAdvertising->setName("NimBLE"); // advertise the device name
|
||||
pAdvertising->start();
|
||||
}
|
||||
```
|
||||
@ -144,7 +140,7 @@ After initializing the NimBLE stack we create a scan instance by calling `NimBLE
|
||||
|
||||
Once we have created the scan we can start looking for advertising servers.
|
||||
|
||||
To do this we call `NimBLEScan::start(duration)`, the duration parameter is a uint32_t that specifies the number of milliseconds to scan for,
|
||||
To do this we call `NimBLEScan::getResults(duration)`, the duration parameter is a uint32_t that specifies the number of milliseconds to scan for,
|
||||
passing 0 will scan forever.
|
||||
|
||||
In this example we will scan for 10 seconds. This is a blocking function (a non blocking overload is also available).
|
||||
@ -154,9 +150,7 @@ This call returns an instance of `NimBLEScanResults` when the scan completes whi
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
NimBLEDevice::init("");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
@ -168,7 +162,7 @@ void app_main(void)
|
||||
Now that we have scanned we need to check the results for any advertisers we are interested in connecting to.
|
||||
|
||||
To do this we iterate through the results and check if any of the devices found are advertising the service we want `ABCD`.
|
||||
Each result in `NimBLEScanResults` is a `NimBLEAdvertisedDevice` instance that we can access data from.
|
||||
Each result in `NimBLEScanResults` is a `const NimBLEAdvertisedDevice*` that we can access data from.
|
||||
|
||||
We will check each device found for the `ABCD` service by calling `NimBLEAdvertisedDevice::isAdvertisingService`.
|
||||
This takes an instance of `NimBLEUUID` as a parameter so we will need to create one.
|
||||
@ -177,11 +171,11 @@ This takes an instance of `NimBLEUUID` as a parameter so we will need to create
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
for (int i = 0; i < results.getCount(); i++) {
|
||||
const NimBLEAdvertisedDevice *device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
// create a client and connect
|
||||
if (device->isAdvertisingService(serviceUuid)) {
|
||||
// create a client and connect
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -198,16 +192,16 @@ This takes a pointer to the `NimBLEAdvertisedDevice` and returns `true` if succe
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
for (int i = 0; i < results.getCount(); i++) {
|
||||
const NimBLEAdvertisedDevice *device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
if (device->isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if(pClient->connect(&device)) {
|
||||
//success
|
||||
if (pClient->connect(&device)) {
|
||||
//success
|
||||
} else {
|
||||
// failed to connect
|
||||
// failed to connect
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,11 +223,15 @@ Finally we will read the characteristic value with `NimBLERemoteCharacteristic::
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
for (int i = 0; i < results.getCount(); i++) {
|
||||
const NimBLEAdvertisedDevice *device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
if (device->isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if (!pClient) { // Make sure the client was created
|
||||
break;
|
||||
}
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
@ -247,7 +245,7 @@ for(int i = 0; i < results.getCount(); i++) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
// failed to connect
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,12 +260,16 @@ This is done by calling `NimBLEDevice::deleteClient`.
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
for (int i = 0; i < results.getCount(); i++) {
|
||||
const NimBLEAdvertisedDevice *device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
if (device->isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
|
||||
if (!pClient) { // Make sure the client was created
|
||||
break;
|
||||
}
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
|
||||
@ -280,7 +282,7 @@ for(int i = 0; i < results.getCount(); i++) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
// failed to connect
|
||||
}
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
@ -294,37 +296,39 @@ Note that there is no need to disconnect as that will be done when deleting the
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
extern "C" void app_main(void) {
|
||||
NimBLEDevice::init("");
|
||||
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
NimBLEScanResults results = pScan->start(10 * 1000);
|
||||
|
||||
NimBLEScanResults results = pScan->getResults(10 * 1000);
|
||||
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
|
||||
for (int i = 0; i < results.getCount(); i++) {
|
||||
const NimBLEAdvertisedDevice *device = results.getDevice(i);
|
||||
|
||||
if (device->isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
|
||||
if (!pClient) { // Make sure the client was created
|
||||
break;
|
||||
}
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
|
||||
|
||||
if (pService != nullptr) {
|
||||
NimBLERemoteCharacteristic *pCharacteristic = pService->getCharacteristic("1234");
|
||||
|
||||
|
||||
if (pCharacteristic != nullptr) {
|
||||
std::string value = pCharacteristic->readValue();
|
||||
// print or do whatever you need with the value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
// failed to connect
|
||||
}
|
||||
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
}
|
||||
}
|
||||
@ -334,4 +338,3 @@ void app_main(void)
|
||||
|
||||
For more advanced features and options please see the client examples in the examples folder.
|
||||
<br/>
|
||||
|
||||
|
@ -26,7 +26,7 @@ class ServerCallbacks : public NimBLEServerCallbacks {
|
||||
* Latency: number of intervals allowed to skip.
|
||||
* Timeout: 10 millisecond increments.
|
||||
*/
|
||||
pServer->updateConnParams(connInfo.getConnHandle(), 24, 48, 0, 18);
|
||||
pServer->updateConnParams(connInfo.getConnHandle(), 24, 48, 0, 180);
|
||||
}
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason) override {
|
||||
|
@ -1,5 +1,5 @@
|
||||
## IDF Component Manager Manifest File
|
||||
version: "2.0.0"
|
||||
version: "2.2.1"
|
||||
license: "Apache-2.0"
|
||||
description: "C++ wrapper for the NimBLE BLE stack"
|
||||
url: "https://github.com/h2zero/esp-nimble-cpp"
|
||||
@ -16,7 +16,7 @@ dependencies:
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
espressif/esp_wifi_remote:
|
||||
version: "*"
|
||||
version: "<0.5.4"
|
||||
rules:
|
||||
- if: "target in [esp32p4]"
|
||||
idf:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "esp-nimble-cpp",
|
||||
"version": "2.0.0",
|
||||
"version": "2.2.1",
|
||||
"description": "C++ wrapper for the NimBLE BLE stack",
|
||||
"keywords": [
|
||||
"BLE",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -68,7 +68,7 @@ class NimBLE2904 : public NimBLEDescriptor {
|
||||
static const uint8_t FORMAT_OPAQUE = 27;
|
||||
static const uint8_t FORMAT_MEDASN1 = 28;
|
||||
|
||||
void setDescription(uint16_t);
|
||||
void setDescription(uint16_t description);
|
||||
void setExponent(int8_t exponent);
|
||||
void setFormat(uint8_t format);
|
||||
void setNamespace(uint8_t namespace_value);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,6 +23,18 @@
|
||||
|
||||
# include <algorithm>
|
||||
|
||||
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_EXCLUDE_DELIMITER
|
||||
# define NIMBLE_CPP_ADDR_DELIMITER ""
|
||||
# else
|
||||
# define NIMBLE_CPP_ADDR_DELIMITER ":"
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_NIMBLE_CPP_ADDR_FMT_UPPERCASE
|
||||
# define NIMBLE_CPP_ADDR_FMT "%02X%s%02X%s%02X%s%02X%s%02X%s%02X"
|
||||
# else
|
||||
# define NIMBLE_CPP_ADDR_FMT "%02x%s%02x%s%02x%s%02x%s%02x%s%02x"
|
||||
# endif
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAddress";
|
||||
|
||||
/*************************************************
|
||||
@ -61,7 +73,7 @@ NimBLEAddress::NimBLEAddress(const std::string& addr, uint8_t type) {
|
||||
std::string mac{addr};
|
||||
mac.erase(std::remove(mac.begin(), mac.end(), ':'), mac.end());
|
||||
uint64_t address = std::stoull(mac, nullptr, 16);
|
||||
memcpy(this->val, &address, sizeof this->val);
|
||||
memcpy(this->val, &address, sizeof(this->val));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -90,7 +102,7 @@ NimBLEAddress::NimBLEAddress(const uint8_t address[BLE_DEV_ADDR_LEN], uint8_t ty
|
||||
* * BLE_ADDR_RANDOM (1)
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(const uint64_t& address, uint8_t type) {
|
||||
memcpy(this->val, &address, sizeof this->val);
|
||||
memcpy(this->val, &address, sizeof(this->val));
|
||||
this->type = type;
|
||||
} // NimBLEAddress
|
||||
|
||||
@ -193,7 +205,7 @@ bool NimBLEAddress::operator==(const NimBLEAddress& rhs) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(rhs.val, this->val, sizeof this->val) == 0;
|
||||
return memcmp(rhs.val, this->val, sizeof(this->val)) == 0;
|
||||
} // operator ==
|
||||
|
||||
/**
|
||||
@ -211,12 +223,12 @@ NimBLEAddress::operator std::string() const {
|
||||
char buffer[18];
|
||||
snprintf(buffer,
|
||||
sizeof(buffer),
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
this->val[5],
|
||||
this->val[4],
|
||||
this->val[3],
|
||||
this->val[2],
|
||||
this->val[1],
|
||||
NIMBLE_CPP_ADDR_FMT,
|
||||
this->val[5], NIMBLE_CPP_ADDR_DELIMITER,
|
||||
this->val[4], NIMBLE_CPP_ADDR_DELIMITER,
|
||||
this->val[3], NIMBLE_CPP_ADDR_DELIMITER,
|
||||
this->val[2], NIMBLE_CPP_ADDR_DELIMITER,
|
||||
this->val[1], NIMBLE_CPP_ADDR_DELIMITER,
|
||||
this->val[0]);
|
||||
return std::string{buffer};
|
||||
} // operator std::string
|
||||
@ -226,7 +238,7 @@ NimBLEAddress::operator std::string() const {
|
||||
*/
|
||||
NimBLEAddress::operator uint64_t() const {
|
||||
uint64_t address = 0;
|
||||
memcpy(&address, this->val, sizeof this->val);
|
||||
memcpy(&address, this->val, sizeof(this->val));
|
||||
return address;
|
||||
} // operator uint64_t
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -780,6 +780,16 @@ bool NimBLEAdvertisedDevice::isLegacyAdvertisement() const {
|
||||
# endif
|
||||
} // isLegacyAdvertisement
|
||||
|
||||
/**
|
||||
* @brief Convenience operator to convert this NimBLEAdvertisedDevice to NimBLEAddress representation.
|
||||
* @details This allows passing NimBLEAdvertisedDevice to functions
|
||||
* that accept NimBLEAddress and/or or it's methods as a parameter.
|
||||
*/
|
||||
NimBLEAdvertisedDevice::operator NimBLEAddress() const {
|
||||
NimBLEAddress address(getAddress());
|
||||
return address;
|
||||
} // operator NimBLEAddress
|
||||
|
||||
/**
|
||||
* @brief Get the payload advertised by the device.
|
||||
* @return The advertisement payload.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -93,6 +93,7 @@ class NimBLEAdvertisedDevice {
|
||||
uint8_t getSecondaryPhy() const;
|
||||
uint16_t getPeriodicInterval() const;
|
||||
# endif
|
||||
operator NimBLEAddress() const;
|
||||
|
||||
const std::vector<uint8_t>& getPayload() const;
|
||||
const std::vector<uint8_t>::const_iterator begin() const;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -39,7 +39,7 @@ static const char* LOG_TAG = "NimBLEAdvertisementData";
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::addData(const uint8_t* data, size_t length) {
|
||||
if ((m_payload.size() + length) > BLE_HS_ADV_MAX_SZ) {
|
||||
if (m_payload.size() + length > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Data length exceeded");
|
||||
return false;
|
||||
}
|
||||
@ -110,7 +110,7 @@ bool NimBLEAdvertisementData::addTxPower() {
|
||||
data[0] = BLE_HS_ADV_TX_PWR_LVL_LEN + 1;
|
||||
data[1] = BLE_HS_ADV_TYPE_TX_PWR_LVL;
|
||||
# ifndef CONFIG_IDF_TARGET_ESP32P4
|
||||
data[2] = NimBLEDevice::getPower();
|
||||
data[2] = NimBLEDevice::getPower(NimBLETxPowerType::Advertise);
|
||||
# else
|
||||
data[2] = 0;
|
||||
# endif
|
||||
@ -159,6 +159,7 @@ bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -169,10 +170,11 @@ bool NimBLEAdvertisementData::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
}
|
||||
|
||||
if (length + getPayload().size() > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
const uint8_t* uuid = serviceUUID.getValue();
|
||||
if (dataLoc == -1) {
|
||||
data[0] = 1 + bytes;
|
||||
@ -214,6 +216,7 @@ bool NimBLEAdvertisementData::removeServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot remove UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -266,12 +269,12 @@ bool NimBLEAdvertisementData::removeServices() {
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setManufacturerData(const uint8_t* data, size_t length) {
|
||||
if (length > 29) {
|
||||
if (length > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "MFG data too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t mdata[31];
|
||||
uint8_t mdata[BLE_HS_ADV_MAX_SZ];
|
||||
mdata[0] = length + 1;
|
||||
mdata[1] = BLE_HS_ADV_TYPE_MFG_DATA;
|
||||
memcpy(&mdata[2], data, length);
|
||||
@ -302,12 +305,12 @@ bool NimBLEAdvertisementData::setManufacturerData(const std::vector<uint8_t>& da
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setURI(const std::string& uri) {
|
||||
if (uri.length() > 29) {
|
||||
if (uri.length() > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "URI too long");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
uint8_t length = 2 + uri.length();
|
||||
data[0] = length - 1;
|
||||
data[1] = BLE_HS_ADV_TYPE_URI;
|
||||
@ -324,16 +327,16 @@ bool NimBLEAdvertisementData::setURI(const std::string& uri) {
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEAdvertisementData::setName(const std::string& name, bool isComplete) {
|
||||
if (name.length() > 29) {
|
||||
if (name.length() > BLE_HS_ADV_MAX_FIELD_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Name too long - truncating");
|
||||
isComplete = false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t length = 2 + std::min<uint8_t>(name.length(), 29);
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
uint8_t length = 2 + std::min<uint8_t>(name.length(), BLE_HS_ADV_MAX_FIELD_SZ);
|
||||
data[0] = length - 1;
|
||||
data[1] = isComplete ? BLE_HS_ADV_TYPE_COMP_NAME : BLE_HS_ADV_TYPE_INCOMP_NAME;
|
||||
memcpy(&data[2], name.c_str(), std::min<uint8_t>(name.length(), 29));
|
||||
memcpy(&data[2], name.c_str(), std::min<uint8_t>(name.length(), BLE_HS_ADV_MAX_FIELD_SZ));
|
||||
return addData(data, length);
|
||||
} // setName
|
||||
|
||||
@ -411,14 +414,14 @@ bool NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>
|
||||
bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std::vector<NimBLEUUID>& uuids) {
|
||||
uint8_t bytes = size / 8;
|
||||
uint8_t length = 2; // start with 2 for length + type bytes
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
|
||||
for (const auto& uuid : uuids) {
|
||||
if (uuid.bitSize() != size) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||
continue;
|
||||
} else {
|
||||
if (length + bytes >= 31) {
|
||||
if (length + bytes >= BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Too many services - truncating");
|
||||
complete = false;
|
||||
break;
|
||||
@ -441,6 +444,7 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
|
||||
data[1] = (complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set services, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -458,7 +462,7 @@ bool NimBLEAdvertisementData::setServices(bool complete, uint8_t size, const std
|
||||
bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
|
||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||
uint8_t sDataLen = 2 + uuidBytes + length;
|
||||
if (sDataLen > 31) {
|
||||
if (sDataLen > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service Data too long");
|
||||
return false;
|
||||
}
|
||||
@ -475,6 +479,7 @@ bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8
|
||||
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set service data, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -483,7 +488,7 @@ bool NimBLEAdvertisementData::setServiceData(const NimBLEUUID& uuid, const uint8
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t sData[31];
|
||||
uint8_t sData[BLE_HS_ADV_MAX_SZ];
|
||||
sData[0] = uuidBytes + length + 1;
|
||||
sData[1] = type;
|
||||
memcpy(&sData[2], uuid.getValue(), uuidBytes);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -38,7 +38,7 @@ class NimBLEAdvertisementData {
|
||||
bool addData(const uint8_t* data, size_t length);
|
||||
bool addData(const std::vector<uint8_t>& data);
|
||||
bool setAppearance(uint16_t appearance);
|
||||
bool setFlags(uint8_t);
|
||||
bool setFlags(uint8_t flag);
|
||||
bool addTxPower();
|
||||
bool setPreferredParams(uint16_t minInterval, uint16_t maxInterval);
|
||||
bool addServiceUUID(const NimBLEUUID& serviceUUID);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -408,7 +408,7 @@ bool NimBLEAdvertising::refreshAdvertisingData() {
|
||||
* @return True if the service was added successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
if (!m_advData.addServiceUUID(serviceUUID) && m_scanResp) {
|
||||
if (!m_advData.addServiceUUID(serviceUUID)) {
|
||||
if (!m_scanData.addServiceUUID(serviceUUID)) {
|
||||
return false;
|
||||
}
|
||||
@ -466,7 +466,7 @@ bool NimBLEAdvertising::removeServices() {
|
||||
* @return True if the appearance was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
if (!m_advData.setAppearance(appearance) && m_scanResp) {
|
||||
if (!m_advData.setAppearance(appearance)) {
|
||||
if (!m_scanData.setAppearance(appearance)) {
|
||||
return false;
|
||||
}
|
||||
@ -484,7 +484,7 @@ bool NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
* @details Range = 0x0006(7.5ms) to 0x0C80(4000ms), values not within the range will be limited to this range.
|
||||
*/
|
||||
bool NimBLEAdvertising::setPreferredParams(uint16_t minInterval, uint16_t maxInterval) {
|
||||
if (!m_advData.setPreferredParams(minInterval, maxInterval) && m_scanResp) {
|
||||
if (!m_advData.setPreferredParams(minInterval, maxInterval)) {
|
||||
if (!m_scanData.setPreferredParams(minInterval, maxInterval)) {
|
||||
return false;
|
||||
}
|
||||
@ -499,7 +499,7 @@ bool NimBLEAdvertising::setPreferredParams(uint16_t minInterval, uint16_t maxInt
|
||||
* @return True if the transmission power level was added successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::addTxPower() {
|
||||
if (!m_advData.addTxPower() && m_scanResp) {
|
||||
if (!m_advData.addTxPower()) {
|
||||
if (!m_scanData.addTxPower()) {
|
||||
return false;
|
||||
}
|
||||
@ -537,7 +537,7 @@ bool NimBLEAdvertising::setName(const std::string& name) {
|
||||
* @return True if the manufacturer data was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setManufacturerData(const uint8_t* data, size_t length) {
|
||||
if (!m_advData.setManufacturerData(data, length) && m_scanResp) {
|
||||
if (!m_advData.setManufacturerData(data, length)) {
|
||||
if (!m_scanData.setManufacturerData(data, length)) {
|
||||
return false;
|
||||
}
|
||||
@ -571,7 +571,7 @@ bool NimBLEAdvertising::setManufacturerData(const std::vector<uint8_t>& data) {
|
||||
* @return True if the URI was set successfully.
|
||||
*/
|
||||
bool NimBLEAdvertising::setURI(const std::string& uri) {
|
||||
if (!m_advData.setURI(uri) && m_scanResp) {
|
||||
if (!m_advData.setURI(uri)) {
|
||||
if (!m_scanData.setURI(uri)) {
|
||||
return false;
|
||||
}
|
||||
@ -590,7 +590,7 @@ bool NimBLEAdvertising::setURI(const std::string& uri) {
|
||||
* @note If data length is 0 the service data will not be advertised.
|
||||
*/
|
||||
bool NimBLEAdvertising::setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length) {
|
||||
if (!m_advData.setServiceData(uuid, data, length) && m_scanResp) {
|
||||
if (!m_advData.setServiceData(uuid, data, length)) {
|
||||
if (!m_scanData.setServiceData(uuid, data, length)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,6 +25,9 @@
|
||||
# endif
|
||||
|
||||
# include "NimBLEAttValue.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAttValue";
|
||||
|
||||
// Default constructor implementation.
|
||||
NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
|
||||
@ -38,13 +41,17 @@ NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len)
|
||||
# endif
|
||||
{
|
||||
NIMBLE_CPP_DEBUG_ASSERT(m_attr_value);
|
||||
if (m_attr_value == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to calloc ctx");
|
||||
}
|
||||
}
|
||||
|
||||
// Value constructor implementation.
|
||||
NimBLEAttValue::NimBLEAttValue(const uint8_t* value, uint16_t len, uint16_t max_len) : NimBLEAttValue(len, max_len) {
|
||||
memcpy(m_attr_value, value, len);
|
||||
m_attr_value[len] = '\0';
|
||||
m_attr_len = len;
|
||||
if (m_attr_value != nullptr) {
|
||||
memcpy(m_attr_value, value, len);
|
||||
m_attr_len = len;
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor implementation.
|
||||
@ -81,6 +88,10 @@ NimBLEAttValue& NimBLEAttValue::operator=(const NimBLEAttValue& source) {
|
||||
void NimBLEAttValue::deepCopy(const NimBLEAttValue& source) {
|
||||
uint8_t* res = static_cast<uint8_t*>(realloc(m_attr_value, source.m_capacity + 1));
|
||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||
if (res == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to realloc deepCopy");
|
||||
return;
|
||||
}
|
||||
|
||||
ble_npl_hw_enter_critical();
|
||||
m_attr_value = res;
|
||||
@ -106,7 +117,7 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
}
|
||||
|
||||
if ((m_attr_len + len) > m_attr_max_len) {
|
||||
NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u", len, m_attr_max_len);
|
||||
NIMBLE_LOGE(LOG_TAG, "val > max, len=%u, max=%u", len, m_attr_max_len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -117,6 +128,10 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
m_capacity = new_len;
|
||||
}
|
||||
NIMBLE_CPP_DEBUG_ASSERT(res);
|
||||
if (res == nullptr) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to realloc append");
|
||||
return *this;
|
||||
}
|
||||
|
||||
# if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
|
||||
time_t t = time(nullptr);
|
||||
@ -135,4 +150,13 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t NimBLEAttValue::operator[](int pos) const {
|
||||
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||
if (pos >= m_attr_len) {
|
||||
NIMBLE_LOGE(LOG_TAG, "pos >= len, pos=%u, len=%u", pos, m_attr_len);
|
||||
return 0;
|
||||
}
|
||||
return m_attr_value[pos];
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,7 +24,6 @@
|
||||
# include <Arduino.h>
|
||||
# endif
|
||||
|
||||
# include "NimBLELog.h"
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <ctime>
|
||||
@ -323,10 +322,7 @@ class NimBLEAttValue {
|
||||
/*********************** Operators ************************/
|
||||
|
||||
/** @brief Subscript operator */
|
||||
uint8_t operator[](int pos) const {
|
||||
NIMBLE_CPP_DEBUG_ASSERT(pos < m_attr_len);
|
||||
return m_attr_value[pos];
|
||||
}
|
||||
uint8_t operator[](int pos) const;
|
||||
|
||||
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
|
||||
operator std::vector<uint8_t>() const { return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -126,6 +126,22 @@ size_t NimBLEClient::deleteService(const NimBLEUUID& uuid) {
|
||||
return m_svcVec.size();
|
||||
} // deleteService
|
||||
|
||||
/**
|
||||
* @brief Connect to an advertising device.
|
||||
* @param [in] pDevice A pointer to the advertised device instance to connect to.
|
||||
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
|
||||
* have created when last connected.
|
||||
* @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
|
||||
* If false, this function will block until the connection is established or the connection attempt times out.
|
||||
* @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
|
||||
* If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(const NimBLEAdvertisedDevice* pDevice, bool deleteAttributes, bool asyncConnect, bool exchangeMTU) {
|
||||
NimBLEAddress address(pDevice->getAddress());
|
||||
return connect(address, deleteAttributes, asyncConnect, exchangeMTU);
|
||||
} // connect
|
||||
|
||||
/**
|
||||
* @brief Connect to the BLE Server using the address of the last connected device, or the address\n
|
||||
* passed to the constructor.
|
||||
@ -141,22 +157,6 @@ bool NimBLEClient::connect(bool deleteAttributes, bool asyncConnect, bool exchan
|
||||
return connect(m_peerAddress, deleteAttributes, asyncConnect, exchangeMTU);
|
||||
} // connect
|
||||
|
||||
/**
|
||||
* @brief Connect to an advertising device.
|
||||
* @param [in] device The device to connect to.
|
||||
* @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
|
||||
* have created when last connected.
|
||||
* @param [in] asyncConnect If true, the connection will be made asynchronously and this function will return immediately.\n
|
||||
* If false, this function will block until the connection is established or the connection attempt times out.
|
||||
* @param [in] exchangeMTU If true, the client will attempt to exchange MTU with the server after connection.\n
|
||||
* If false, the client will use the default MTU size and the application will need to call exchangeMTU() later.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(const NimBLEAdvertisedDevice* device, bool deleteAttributes, bool asyncConnect, bool exchangeMTU) {
|
||||
NimBLEAddress address(device->getAddress());
|
||||
return connect(address, deleteAttributes, asyncConnect, exchangeMTU);
|
||||
} // connect
|
||||
|
||||
/**
|
||||
* @brief Connect to a BLE Server by address.
|
||||
* @param [in] address The address of the server.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,17 +21,12 @@
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
class NimBLEDescriptor;
|
||||
class NimBLEDescriptorCallbacks;
|
||||
|
||||
# include "NimBLELocalValueAttribute.h"
|
||||
# include "NimBLECharacteristic.h"
|
||||
# include "NimBLEUUID.h"
|
||||
# include "NimBLEAttValue.h"
|
||||
# include "NimBLEConnInfo.h"
|
||||
|
||||
# include <string>
|
||||
|
||||
class NimBLECharacteristic;
|
||||
class NimBLEDescriptorCallbacks;
|
||||
|
||||
/**
|
||||
* @brief A model of a BLE descriptor.
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -76,6 +76,9 @@ extern "C" void ble_store_config_init(void);
|
||||
/**
|
||||
* Singletons for the NimBLEDevice.
|
||||
*/
|
||||
NimBLEDeviceCallbacks NimBLEDevice::defaultDeviceCallbacks{};
|
||||
NimBLEDeviceCallbacks* NimBLEDevice::m_pDeviceCallbacks = &defaultDeviceCallbacks;
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
|
||||
# endif
|
||||
@ -464,7 +467,7 @@ bool NimBLEDevice::setPowerLevel(esp_power_level_t powerLevel, esp_ble_power_typ
|
||||
* @param [in] dbm The power level to set in dBm.
|
||||
* @return True if the power level was set successfully.
|
||||
*/
|
||||
bool NimBLEDevice::setPower(int8_t dbm) {
|
||||
bool NimBLEDevice::setPower(int8_t dbm, NimBLETxPowerType type) {
|
||||
# ifdef ESP_PLATFORM
|
||||
# ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
return false; // CONFIG_IDF_TARGET_ESP32P4 does not support esp_ble_tx_power_set
|
||||
@ -472,9 +475,25 @@ bool NimBLEDevice::setPower(int8_t dbm) {
|
||||
if (dbm % 3 == 2) {
|
||||
dbm++; // round up to the next multiple of 3 to be able to target 20dbm
|
||||
}
|
||||
return setPowerLevel(static_cast<esp_power_level_t>(dbm / 3 + ESP_PWR_LVL_N0));
|
||||
|
||||
bool success = false;
|
||||
esp_power_level_t espPwr = static_cast<esp_power_level_t>(dbm / 3 + ESP_PWR_LVL_N0);
|
||||
if (type == NimBLETxPowerType::All) {
|
||||
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV);
|
||||
success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN);
|
||||
success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
} else if (type == NimBLETxPowerType::Advertise) {
|
||||
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV);
|
||||
} else if (type == NimBLETxPowerType::Scan) {
|
||||
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN);
|
||||
} else if (type == NimBLETxPowerType::Connection) {
|
||||
success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
return success;
|
||||
# endif
|
||||
# else
|
||||
(void)type; // unused
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d", dbm);
|
||||
ble_hci_vs_set_tx_pwr_cp cmd{dbm};
|
||||
ble_hci_vs_set_tx_pwr_rp rsp{0};
|
||||
@ -493,12 +512,16 @@ bool NimBLEDevice::setPower(int8_t dbm) {
|
||||
* @brief Get the transmission power.
|
||||
* @return The power level currently used in dbm or 0xFF on error.
|
||||
*/
|
||||
int NimBLEDevice::getPower() {
|
||||
int NimBLEDevice::getPower(NimBLETxPowerType type) {
|
||||
# ifdef ESP_PLATFORM
|
||||
# ifdef CONFIG_IDF_TARGET_ESP32P4
|
||||
return 0xFF; // CONFIG_IDF_TARGET_ESP32P4 does not support esp_ble_tx_power_get
|
||||
# else
|
||||
int pwr = getPowerLevel();
|
||||
esp_ble_power_type_t espPwr = type == NimBLETxPowerType::Advertise ? ESP_BLE_PWR_TYPE_ADV
|
||||
: type == NimBLETxPowerType::Scan ? ESP_BLE_PWR_TYPE_SCAN
|
||||
: ESP_BLE_PWR_TYPE_DEFAULT;
|
||||
|
||||
int pwr = getPowerLevel(espPwr);
|
||||
if (pwr < 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_get failed rc=%d", pwr);
|
||||
return 0xFF;
|
||||
@ -515,6 +538,7 @@ int NimBLEDevice::getPower() {
|
||||
return 0;
|
||||
# endif
|
||||
# else
|
||||
(void)type; // unused
|
||||
return ble_phy_txpwr_get();
|
||||
# endif
|
||||
} // getPower
|
||||
@ -820,7 +844,7 @@ bool NimBLEDevice::init(const std::string& deviceName) {
|
||||
if (!m_initialized) {
|
||||
# ifdef ESP_PLATFORM
|
||||
|
||||
# ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
||||
# if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && SOC_BT_SUPPORTED
|
||||
// make sure the linker includes esp32-hal-bt.c so Arduino init doesn't release BLE memory.
|
||||
btStarted();
|
||||
# endif
|
||||
@ -877,17 +901,23 @@ bool NimBLEDevice::init(const std::string& deviceName) {
|
||||
nimble_port_init();
|
||||
|
||||
// Setup callbacks for host events
|
||||
ble_hs_cfg.reset_cb = NimBLEDevice::onReset;
|
||||
ble_hs_cfg.sync_cb = NimBLEDevice::onSync;
|
||||
ble_hs_cfg.reset_cb = NimBLEDevice::onReset;
|
||||
ble_hs_cfg.sync_cb = NimBLEDevice::onSync;
|
||||
ble_hs_cfg.store_status_cb = [](struct ble_store_status_event* event, void* arg) {
|
||||
return m_pDeviceCallbacks->onStoreStatus(event, arg);
|
||||
};
|
||||
|
||||
// Set initial security capabilities
|
||||
ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
|
||||
ble_hs_cfg.sm_bonding = 0;
|
||||
ble_hs_cfg.sm_mitm = 0;
|
||||
ble_hs_cfg.sm_sc = 1;
|
||||
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID;
|
||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr; /*TODO: Implement handler for this*/
|
||||
ble_hs_cfg.sm_our_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
|
||||
ble_hs_cfg.sm_their_key_dist = BLE_SM_PAIR_KEY_DIST_ENC;
|
||||
# if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
ble_hs_cfg.sm_our_key_dist |= BLE_SM_PAIR_KEY_DIST_ID;
|
||||
ble_hs_cfg.sm_their_key_dist |= BLE_SM_PAIR_KEY_DIST_ID;
|
||||
# endif
|
||||
|
||||
setDeviceName(deviceName);
|
||||
ble_store_config_init();
|
||||
@ -1154,6 +1184,7 @@ bool NimBLEDevice::startSecurity(uint16_t connHandle, int* rcPtr) {
|
||||
return rc == 0 || rc == BLE_HS_EALREADY;
|
||||
} // startSecurity
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/**
|
||||
* @brief Inject the provided passkey into the Security Manager.
|
||||
* @param [in] peerInfo Connection information for the peer.
|
||||
@ -1178,6 +1209,7 @@ bool NimBLEDevice::injectConfirmPasskey(const NimBLEConnInfo& peerInfo, bool acc
|
||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_NUMCMP; ble_sm_inject_io result: %d", rc);
|
||||
return rc == 0;
|
||||
}
|
||||
# endif // CONFIG_BT_NIMBLE_ROLE_CENTRAL || CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* UTILITIES */
|
||||
@ -1235,4 +1267,13 @@ void nimble_cpp_assert(const char* file, unsigned line) {
|
||||
}
|
||||
# endif // CONFIG_NIMBLE_CPP_DEBUG_ASSERT_ENABLED
|
||||
|
||||
void NimBLEDevice::setDeviceCallbacks(NimBLEDeviceCallbacks* cb) {
|
||||
m_pDeviceCallbacks = cb ? cb : &defaultDeviceCallbacks;
|
||||
}
|
||||
|
||||
int NimBLEDeviceCallbacks::onStoreStatus(struct ble_store_status_event* event, void* arg) {
|
||||
NIMBLE_LOGD("NimBLEDeviceCallbacks", "onStoreStatus: default");
|
||||
return ble_store_util_status_rr(event, arg);
|
||||
}
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -66,6 +66,7 @@ class NimBLEConnInfo;
|
||||
# endif
|
||||
|
||||
class NimBLEAddress;
|
||||
class NimBLEDeviceCallbacks;
|
||||
|
||||
# define BLEDevice NimBLEDevice
|
||||
# define BLEClient NimBLEClient
|
||||
@ -101,6 +102,13 @@ class NimBLEAddress;
|
||||
# define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
|
||||
# endif
|
||||
|
||||
enum class NimBLETxPowerType {
|
||||
All = 0,
|
||||
Advertise = 1,
|
||||
Scan = 2,
|
||||
Connection = 3
|
||||
};
|
||||
|
||||
typedef int (*gap_event_handler)(ble_gap_event* event, void* arg);
|
||||
|
||||
/**
|
||||
@ -122,6 +130,7 @@ class NimBLEDevice {
|
||||
static bool setOwnAddrType(uint8_t type);
|
||||
static bool setOwnAddr(const NimBLEAddress& addr);
|
||||
static bool setOwnAddr(const uint8_t* addr);
|
||||
static void setDeviceCallbacks(NimBLEDeviceCallbacks* cb);
|
||||
static void setScanDuplicateCacheSize(uint16_t cacheSize);
|
||||
static void setScanFilterMode(uint8_t type);
|
||||
static bool setCustomGapHandler(gap_event_handler handler);
|
||||
@ -138,8 +147,8 @@ class NimBLEDevice {
|
||||
static void onReset(int reason);
|
||||
static void onSync(void);
|
||||
static void host_task(void* param);
|
||||
static int getPower();
|
||||
static bool setPower(int8_t dbm);
|
||||
static int getPower(NimBLETxPowerType type = NimBLETxPowerType::All);
|
||||
static bool setPower(int8_t dbm, NimBLETxPowerType type = NimBLETxPowerType::All);
|
||||
|
||||
# ifdef ESP_PLATFORM
|
||||
# ifndef CONFIG_IDF_TARGET_ESP32P4
|
||||
@ -206,6 +215,8 @@ class NimBLEDevice {
|
||||
static ble_gap_event_listener m_listener;
|
||||
static uint8_t m_ownAddrType;
|
||||
static std::vector<NimBLEAddress> m_whiteList;
|
||||
static NimBLEDeviceCallbacks* m_pDeviceCallbacks;
|
||||
static NimBLEDeviceCallbacks defaultDeviceCallbacks;
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* m_pScan;
|
||||
@ -282,5 +293,33 @@ class NimBLEDevice {
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
# include "NimBLEConnInfo.h"
|
||||
# endif
|
||||
|
||||
# include "NimBLEUtils.h"
|
||||
|
||||
/**
|
||||
* @brief Callbacks associated with a BLE device.
|
||||
*/
|
||||
class NimBLEDeviceCallbacks {
|
||||
public:
|
||||
virtual ~NimBLEDeviceCallbacks() {};
|
||||
|
||||
/**
|
||||
* @brief Indicates an inability to perform a store operation.
|
||||
* This callback should do one of two things:
|
||||
* -Address the problem and return 0, indicating that the store operation
|
||||
* should proceed.
|
||||
* -Return nonzero to indicate that the store operation should be aborted.
|
||||
* @param event Describes the store event being reported.
|
||||
* BLE_STORE_EVENT_FULL; or
|
||||
* BLE_STORE_EVENT_OVERFLOW
|
||||
* @return 0 if the store operation should proceed;
|
||||
* nonzero if the store operation should be aborted.
|
||||
*/
|
||||
virtual int onStoreStatus(struct ble_store_status_event* event, void* arg);
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
#endif // NIMBLE_CPP_DEVICE_H_
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -359,7 +359,7 @@ NimBLEExtAdvertisement::NimBLEExtAdvertisement(uint8_t priPhy, uint8_t secPhy) {
|
||||
m_params.own_addr_type = NimBLEDevice::m_ownAddrType;
|
||||
m_params.primary_phy = priPhy;
|
||||
m_params.secondary_phy = secPhy;
|
||||
m_params.tx_power = 127;
|
||||
m_params.tx_power = NimBLEDevice::getPower(NimBLETxPowerType::Advertise);
|
||||
} // NimBLEExtAdvertisement
|
||||
|
||||
/**
|
||||
@ -701,6 +701,7 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -711,10 +712,11 @@ bool NimBLEExtAdvertisement::addServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
}
|
||||
|
||||
if (length + getDataSize() > CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot add UUID, data length exceeded!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t data[31];
|
||||
uint8_t data[BLE_HS_ADV_MAX_SZ];
|
||||
const uint8_t* uuid = serviceUUID.getValue();
|
||||
if (dataLoc == -1) {
|
||||
data[0] = 1 + bytes;
|
||||
@ -756,6 +758,7 @@ bool NimBLEExtAdvertisement::removeServiceUUID(const NimBLEUUID& serviceUUID) {
|
||||
type = BLE_HS_ADV_TYPE_COMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot remove UUID, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -878,6 +881,7 @@ bool NimBLEExtAdvertisement::setServices(bool complete, uint8_t size, const std:
|
||||
header[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set services, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -932,6 +936,7 @@ bool NimBLEExtAdvertisement::setServiceData(const NimBLEUUID& uuid, const uint8_
|
||||
type = BLE_HS_ADV_TYPE_SVC_DATA_UUID128;
|
||||
break;
|
||||
default:
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set service data, invalid size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1009,8 +1014,22 @@ bool NimBLEExtAdvertisement::setPreferredParams(uint16_t minInterval, uint16_t m
|
||||
/**
|
||||
* @brief Adds Tx power level to the advertisement data.
|
||||
*/
|
||||
void NimBLEExtAdvertisement::addTxPower() {
|
||||
bool NimBLEExtAdvertisement::addTxPower() {
|
||||
if (m_params.legacy_pdu) {
|
||||
m_params.include_tx_power = 0;
|
||||
uint8_t data[3];
|
||||
data[0] = BLE_HS_ADV_TX_PWR_LVL_LEN + 1;
|
||||
data[1] = BLE_HS_ADV_TYPE_TX_PWR_LVL;
|
||||
# ifndef CONFIG_IDF_TARGET_ESP32P4
|
||||
data[2] = NimBLEDevice::getPower(NimBLETxPowerType::Advertise);
|
||||
# else
|
||||
data[2] = 0;
|
||||
# endif
|
||||
return addData(data, 3);
|
||||
}
|
||||
|
||||
m_params.include_tx_power = 1;
|
||||
return true;
|
||||
} // addTxPower
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -46,34 +46,33 @@ class NimBLEUUID;
|
||||
class NimBLEExtAdvertisement {
|
||||
public:
|
||||
NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M, uint8_t secPhy = BLE_HCI_LE_PHY_1M);
|
||||
bool setAppearance(uint16_t appearance);
|
||||
bool addServiceUUID(const NimBLEUUID& serviceUUID);
|
||||
bool addServiceUUID(const char* serviceUUID);
|
||||
bool removeServiceUUID(const NimBLEUUID& serviceUUID);
|
||||
bool removeServiceUUID(const char* serviceUUID);
|
||||
bool removeServices();
|
||||
bool setCompleteServices(const NimBLEUUID& uuid);
|
||||
bool setCompleteServices16(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setCompleteServices32(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setFlags(uint8_t flag);
|
||||
bool setManufacturerData(const uint8_t* data, size_t length);
|
||||
bool setManufacturerData(const std::string& data);
|
||||
bool setManufacturerData(const std::vector<uint8_t>& data);
|
||||
bool setURI(const std::string& uri);
|
||||
bool setName(const std::string& name, bool isComplete = true);
|
||||
bool setPartialServices(const NimBLEUUID& uuid);
|
||||
bool setPartialServices16(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setPartialServices32(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const std::string& data);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const std::vector<uint8_t>& data);
|
||||
bool setShortName(const std::string& name);
|
||||
bool setData(const uint8_t* data, size_t length);
|
||||
bool addData(const uint8_t* data, size_t length);
|
||||
bool addData(const std::string& data);
|
||||
bool setPreferredParams(uint16_t min, uint16_t max);
|
||||
|
||||
void addTxPower();
|
||||
bool setAppearance(uint16_t appearance);
|
||||
bool addServiceUUID(const NimBLEUUID& serviceUUID);
|
||||
bool addServiceUUID(const char* serviceUUID);
|
||||
bool removeServiceUUID(const NimBLEUUID& serviceUUID);
|
||||
bool removeServiceUUID(const char* serviceUUID);
|
||||
bool removeServices();
|
||||
bool setCompleteServices(const NimBLEUUID& uuid);
|
||||
bool setCompleteServices16(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setCompleteServices32(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setFlags(uint8_t flag);
|
||||
bool setManufacturerData(const uint8_t* data, size_t length);
|
||||
bool setManufacturerData(const std::string& data);
|
||||
bool setManufacturerData(const std::vector<uint8_t>& data);
|
||||
bool setURI(const std::string& uri);
|
||||
bool setName(const std::string& name, bool isComplete = true);
|
||||
bool setPartialServices(const NimBLEUUID& uuid);
|
||||
bool setPartialServices16(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setPartialServices32(const std::vector<NimBLEUUID>& uuids);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const uint8_t* data, size_t length);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const std::string& data);
|
||||
bool setServiceData(const NimBLEUUID& uuid, const std::vector<uint8_t>& data);
|
||||
bool setShortName(const std::string& name);
|
||||
bool setData(const uint8_t* data, size_t length);
|
||||
bool addData(const uint8_t* data, size_t length);
|
||||
bool addData(const std::string& data);
|
||||
bool setPreferredParams(uint16_t min, uint16_t max);
|
||||
bool addTxPower();
|
||||
void setLegacyAdvertising(bool enable);
|
||||
void setConnectable(bool enable);
|
||||
void setScannable(bool enable);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -149,14 +149,35 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) {
|
||||
}
|
||||
} // setBatteryLevel
|
||||
|
||||
/**
|
||||
* @brief Locate the characteristic for a report ID and a report type.
|
||||
*
|
||||
* @param [in] reportId Report identifier to locate.
|
||||
* @param [in] reportType Type of report (input/output/feature).
|
||||
* @return NimBLECharacteristic* The characteristic.
|
||||
* @return nullptr If the characteristic does not exist.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType) {
|
||||
NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, 0);
|
||||
for (uint16_t i = 1; (candidate != nullptr) && (i != 0); i++) {
|
||||
NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid);
|
||||
NimBLEAttValue desc1_val_att = dsc->getValue();
|
||||
const uint8_t* desc1_val = desc1_val_att.data();
|
||||
if ((desc1_val[0] == reportId) && (desc1_val[1] == reportType)) return candidate;
|
||||
candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, i);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the input report characteristic.
|
||||
* @param [in] reportId input report ID, the same as in report map for input object related to the characteristic.
|
||||
* @return A pointer to the input report characteristic.
|
||||
* @param [in] reportId Input report ID, the same as in report map for input object related to the characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to the input report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* inputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* inputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x01);
|
||||
if (inputReportChr == nullptr) {
|
||||
inputReportChr =
|
||||
m_hidSvc->createCharacteristic(inputReportChrUuid,
|
||||
@ -174,11 +195,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
|
||||
/**
|
||||
* @brief Get the output report characteristic.
|
||||
* @param [in] reportId Output report ID, the same as in report map for output object related to the characteristic.
|
||||
* @return A pointer to the output report characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to the output report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* outputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* outputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x02);
|
||||
if (outputReportChr == nullptr) {
|
||||
outputReportChr =
|
||||
m_hidSvc->createCharacteristic(inputReportChrUuid,
|
||||
@ -187,7 +209,6 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
NimBLEDescriptor* outputReportDsc = outputReportChr->createDescriptor(
|
||||
featureReportDscUuid,
|
||||
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = {reportId, 0x02};
|
||||
outputReportDsc->setValue(desc1_val, 2);
|
||||
}
|
||||
@ -198,11 +219,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
|
||||
/**
|
||||
* @brief Get the feature report characteristic.
|
||||
* @param [in] reportId Feature report ID, the same as in report map for feature object related to the characteristic.
|
||||
* @return A pointer to feature report characteristic.
|
||||
* @return NimBLECharacteristic* A pointer to feature report characteristic.
|
||||
* Store this value to avoid computational overhead.
|
||||
* @details This will create the characteristic if not already created.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) {
|
||||
NimBLECharacteristic* featureReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid);
|
||||
NimBLECharacteristic* featureReportChr = locateReportCharacteristicByIdAndType(reportId, 0x03);
|
||||
if (featureReportChr == nullptr) {
|
||||
featureReportChr = m_hidSvc->createCharacteristic(
|
||||
inputReportChrUuid,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -81,6 +81,8 @@ class NimBLEHIDDevice {
|
||||
NimBLECharacteristic* m_hidControlChr{nullptr}; // 0x2a4c
|
||||
NimBLECharacteristic* m_protocolModeChr{nullptr}; // 0x2a4e
|
||||
NimBLECharacteristic* m_batteryLevelChr{nullptr}; // 0x2a19
|
||||
|
||||
NimBLECharacteristic* locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType);
|
||||
};
|
||||
|
||||
#endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
119
src/NimBLELog.h
119
src/NimBLELog.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -28,11 +28,109 @@
|
||||
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
|
||||
# endif
|
||||
|
||||
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
|
||||
do { \
|
||||
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
|
||||
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR)
|
||||
# if CONFIG_LOG_COLORS
|
||||
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_BLACK)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_BLACK)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_RED)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_RED)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_GREEN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_GREEN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_YELLOW)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_BROWN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_BLUE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_BLUE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_PURPLE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_PURPLE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_DEBUG_CYAN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_D LOG_COLOR(LOG_COLOR_CYAN)
|
||||
# else
|
||||
# define NIMBLE_CPP_LOG_COLOR_D
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_BLACK)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_BLACK)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_RED)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_RED)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_GREEN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_YELLOW)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_BROWN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_BLUE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_BLUE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_PURPLE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_PURPLE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_INFO_CYAN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_I LOG_COLOR(LOG_COLOR_CYAN)
|
||||
# else
|
||||
# define NIMBLE_CPP_LOG_COLOR_I
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_BLACK)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_BLACK)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_RED)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_RED)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_GREEN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_GREEN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_YELLOW)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_BLUE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_BLUE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_PURPLE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_PURPLE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_WARN_CYAN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_W LOG_COLOR(LOG_COLOR_CYAN)
|
||||
# else
|
||||
# define NIMBLE_CPP_LOG_COLOR_W
|
||||
# endif
|
||||
|
||||
# if defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_BLACK)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_BLACK)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_RED)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_GREEN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_GREEN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_YELLOW)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_BROWN)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_BLUE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_BLUE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_PURPLE)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_PURPLE)
|
||||
# elif defined(CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR_ERR_CYAN)
|
||||
# define NIMBLE_CPP_LOG_COLOR_E LOG_COLOR(LOG_COLOR_CYAN)
|
||||
# else
|
||||
# define NIMBLE_CPP_LOG_COLOR_E
|
||||
# endif
|
||||
# else //CONFIG_LOG_COLORS
|
||||
# define NIMBLE_CPP_LOG_COLOR_D
|
||||
# define NIMBLE_CPP_LOG_COLOR_I
|
||||
# define NIMBLE_CPP_LOG_COLOR_W
|
||||
# define NIMBLE_CPP_LOG_COLOR_E
|
||||
# endif //CONFIG_LOG_COLORS
|
||||
|
||||
# define NIMBLE_CPP_LOG_FORMAT(letter, format) NIMBLE_CPP_LOG_COLOR_##letter #letter " (%lu) %s: " format LOG_RESET_COLOR "\n"
|
||||
|
||||
# define NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ...) \
|
||||
do { \
|
||||
if (level==ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, NIMBLE_CPP_LOG_FORMAT(E, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, NIMBLE_CPP_LOG_FORMAT(W, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else if (level==ESP_LOG_INFO) { esp_log_write(ESP_LOG_INFO, tag, NIMBLE_CPP_LOG_FORMAT(I, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
else { esp_log_write(ESP_LOG_DEBUG, tag, NIMBLE_CPP_LOG_FORMAT(D, format), esp_log_timestamp(), tag __VA_OPT__(,) __VA_ARGS__); } \
|
||||
} while(0)
|
||||
|
||||
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
|
||||
do { \
|
||||
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) NIMBLE_CPP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
# else
|
||||
# define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) \
|
||||
do { \
|
||||
if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
# endif /* CONFIG_NIMBLE_CPP_LOG_OVERRIDE_COLOR */
|
||||
|
||||
# define NIMBLE_LOGD(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_DEBUG, tag, format, ##__VA_ARGS__)
|
||||
# define NIMBLE_LOGI(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_INFO, tag, format, ##__VA_ARGS__)
|
||||
# define NIMBLE_LOGW(tag, format, ...) NIMBLE_CPP_LOG_PRINT(ESP_LOG_WARN, tag, format, ##__VA_ARGS__)
|
||||
@ -73,6 +171,13 @@
|
||||
# define NIMBLE_LOGE(tag, format, ...) (void)tag
|
||||
# endif
|
||||
|
||||
# endif /* CONFIG_NIMBLE_CPP_IDF */
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* NIMBLE_CPP_LOG_H_ */
|
||||
# endif /* CONFIG_NIMBLE_CPP_IDF */
|
||||
|
||||
# define NIMBLE_LOGD_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGD(tag, format, ##__VA_ARGS__); }}
|
||||
# define NIMBLE_LOGI_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGI(tag, format, ##__VA_ARGS__); }}
|
||||
# define NIMBLE_LOGW_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGW(tag, format, ##__VA_ARGS__); }}
|
||||
# define NIMBLE_LOGE_IF(cond, tag, format, ...) { if (cond) { NIMBLE_LOGE(tag, format, ##__VA_ARGS__); }}
|
||||
# define NIMBLE_LOGE_RC(rc, tag, format, ...) { if (rc) { NIMBLE_LOGE(tag, format "; rc=%d %s", ##__VA_ARGS__, rc, NimBLEUtils::returnCodeToString(rc)); }}
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* NIMBLE_CPP_LOG_H_ */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -27,17 +27,18 @@
|
||||
|
||||
# include <climits>
|
||||
|
||||
typedef struct {
|
||||
const NimBLEUUID* uuid;
|
||||
void* task_data;
|
||||
} desc_filter_t;
|
||||
struct NimBLEDescriptorFilter {
|
||||
NimBLERemoteDescriptor* dsc;
|
||||
const NimBLEUUID* uuid;
|
||||
void* taskData;
|
||||
};
|
||||
|
||||
static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param [in] svc A pointer to the service this characteristic belongs to.
|
||||
* @param [in] ble_gatt_chr struct defined as:
|
||||
* @param [in] chr struct defined as:
|
||||
* struct ble_gatt_chr {
|
||||
* uint16_t def_handle;
|
||||
* uint16_t val_handle;
|
||||
@ -63,71 +64,73 @@ NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
||||
* @brief Callback used by the API when a descriptor is discovered or search complete.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::descriptorDiscCB(
|
||||
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg) {
|
||||
int rc = error->status;
|
||||
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg) {
|
||||
int rc = error->status;
|
||||
auto filter = (NimBLEDescriptorFilter*)arg;
|
||||
auto pTaskData = (NimBLETaskData*)filter->taskData;
|
||||
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
|
||||
const auto uuid = filter->uuid; // UUID to filter for
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovery >> status: %d handle: %d", rc, (rc == 0) ? dsc->handle : -1);
|
||||
|
||||
auto filter = (desc_filter_t*)arg;
|
||||
auto pTaskData = (NimBLETaskData*)filter->task_data;
|
||||
const auto pChr = (NimBLERemoteCharacteristic*)pTaskData->m_pInstance;
|
||||
const NimBLEUUID* uuidFilter = filter->uuid;
|
||||
|
||||
if (error->status == BLE_HS_ENOTCONN) {
|
||||
NIMBLE_LOGE(LOG_TAG, "<< Descriptor Discovery; Not connected");
|
||||
NimBLEUtils::taskRelease(*pTaskData, error->status);
|
||||
return error->status;
|
||||
}
|
||||
|
||||
if (pChr->getHandle() != chr_val_handle) {
|
||||
rc = BLE_HS_EDONE; // descriptor not for this characteristic
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
if (uuidFilter != nullptr) {
|
||||
if (ble_uuid_cmp(uuidFilter->getBase(), &dsc->uuid.u) == 0) {
|
||||
rc = BLE_HS_EDONE; // Found the descriptor, stop the search
|
||||
} else {
|
||||
return 0; // Not the descriptor we are looking for
|
||||
}
|
||||
}
|
||||
|
||||
// Results for chrHandle added until rc != 0
|
||||
// Must find specified UUID if filter is used
|
||||
if (rc == 0 && pChr->getHandle() == chrHandle && (!uuid || 0 == ble_uuid_cmp(uuid->getBase(), &dsc->uuid.u))) {
|
||||
// Return BLE_HS_EDONE if the descriptor was found, stop the search
|
||||
pChr->m_vDescriptors.push_back(new NimBLERemoteDescriptor(pChr, dsc));
|
||||
rc = !!uuid * BLE_HS_EDONE;
|
||||
}
|
||||
|
||||
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
|
||||
if (rc != 0) {
|
||||
NimBLEUtils::taskRelease(*pTaskData, rc);
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor Discovery");
|
||||
}
|
||||
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.
|
||||
* @param [in] pFilter Pointer to a filter containing pointers to descriptor, UUID, and task data.
|
||||
* @return True if successfully retrieved, success = BLE_HS_EDONE.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilter) const {
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFilter) const {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||
|
||||
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
|
||||
desc_filter_t filter = {uuidFilter, &taskData};
|
||||
// If this is the last handle then there are no descriptors
|
||||
if (getHandle() == getRemoteService()->getEndHandle()) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found 0 descriptors.");
|
||||
return true;
|
||||
}
|
||||
|
||||
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
|
||||
NimBLEDescriptorFilter defaultFilter{nullptr, nullptr, &taskData};
|
||||
if (pFilter == nullptr) {
|
||||
pFilter = &defaultFilter;
|
||||
}
|
||||
|
||||
int rc = ble_gattc_disc_all_dscs(getClient()->getConnHandle(),
|
||||
getHandle(),
|
||||
getRemoteService()->getEndHandle(),
|
||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||
&filter);
|
||||
pFilter);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
NimBLEUtils::taskWait(taskData, BLE_NPL_TIME_FOREVER);
|
||||
rc = taskData.m_flags;
|
||||
if (rc == 0 || rc == BLE_HS_EDONE) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size());
|
||||
return true;
|
||||
auto prevDscCount = m_vDescriptors.size();
|
||||
NimBLEUtils::taskWait(pFilter->taskData, BLE_NPL_TIME_FOREVER);
|
||||
rc = ((NimBLETaskData*)pFilter->taskData)->m_flags;
|
||||
if (rc != BLE_HS_EDONE) {
|
||||
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
NIMBLE_LOGE(LOG_TAG, "<< retrieveDescriptors(): failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
if (m_vDescriptors.size() > prevDscCount) {
|
||||
pFilter->dsc = m_vDescriptors.back();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): found %d descriptors.", m_vDescriptors.size() - prevDscCount);
|
||||
return true;
|
||||
} // retrieveDescriptors
|
||||
|
||||
/**
|
||||
@ -137,51 +140,38 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID* uuidFilte
|
||||
*/
|
||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||
NimBLERemoteDescriptor* pDsc = nullptr;
|
||||
size_t prev_size = m_vDescriptors.size();
|
||||
NimBLEUUID uuidTmp{uuid};
|
||||
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
|
||||
NimBLEDescriptorFilter filter{nullptr, &uuidTmp, &taskData};
|
||||
|
||||
for (const auto& it : m_vDescriptors) {
|
||||
if (it->getUUID() == uuid) {
|
||||
pDsc = it;
|
||||
for (const auto& dsc : m_vDescriptors) {
|
||||
if (dsc->getUUID() == uuid) {
|
||||
filter.dsc = dsc;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
if (retrieveDescriptors(&uuid)) {
|
||||
if (m_vDescriptors.size() > prev_size) {
|
||||
pDsc = m_vDescriptors.back();
|
||||
goto Done;
|
||||
}
|
||||
if (!retrieveDescriptors(&filter) || filter.dsc) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// If the request was successful but 16/32 bit uuid not found
|
||||
// try again with the 128 bit uuid.
|
||||
if (uuid.bitSize() == BLE_UUID_TYPE_16 || uuid.bitSize() == BLE_UUID_TYPE_32) {
|
||||
NimBLEUUID uuid128(uuid);
|
||||
uuid128.to128();
|
||||
if (retrieveDescriptors(&uuid128)) {
|
||||
if (m_vDescriptors.size() > prev_size) {
|
||||
pDsc = m_vDescriptors.back();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the request was successful but the 128 bit uuid not found
|
||||
// try again with the 16 bit uuid.
|
||||
NimBLEUUID uuid16(uuid);
|
||||
uuid16.to16();
|
||||
// if the uuid was 128 bit but not of the BLE base type this check will fail
|
||||
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
|
||||
if (retrieveDescriptors(&uuid16)) {
|
||||
if (m_vDescriptors.size() > prev_size) {
|
||||
pDsc = m_vDescriptors.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try again with 128 bit uuid if request succeeded but no descriptor found.
|
||||
if (uuid.bitSize() != BLE_UUID_TYPE_128) {
|
||||
uuidTmp.to128();
|
||||
retrieveDescriptors(&filter);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// If the uuid was 128 bit, try again with 16 bit uuid.
|
||||
uuidTmp.to16();
|
||||
if (uuidTmp.bitSize() == BLE_UUID_TYPE_16) {
|
||||
filter.uuid = &uuidTmp;
|
||||
retrieveDescriptors(&filter);
|
||||
}
|
||||
|
||||
Done:
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", pDsc ? "" : "not ");
|
||||
return pDsc;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: %sfound", filter.dsc ? "" : "not ");
|
||||
return filter.dsc;
|
||||
} // getDescriptor
|
||||
|
||||
/**
|
||||
@ -310,7 +300,7 @@ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID& uuid) cons
|
||||
* @return True if supported.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::canBroadcast() const {
|
||||
return (m_properties & BLE_GATT_CHR_PROP_BROADCAST) != 0;
|
||||
return (m_properties & BLE_GATT_CHR_PROP_BROADCAST);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,8 +25,10 @@
|
||||
# include <vector>
|
||||
# include <functional>
|
||||
|
||||
class NimBLEUUID;
|
||||
class NimBLERemoteService;
|
||||
class NimBLERemoteDescriptor;
|
||||
struct NimBLEDescriptorFilter;
|
||||
|
||||
/**
|
||||
* @brief A model of a remote BLE characteristic.
|
||||
@ -65,10 +67,10 @@ class NimBLERemoteCharacteristic : public NimBLERemoteValueAttribute {
|
||||
~NimBLERemoteCharacteristic();
|
||||
|
||||
bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true) const;
|
||||
bool retrieveDescriptors(const NimBLEUUID* uuidFilter = nullptr) const;
|
||||
bool retrieveDescriptors(NimBLEDescriptorFilter* pFilter = nullptr) const;
|
||||
|
||||
static int descriptorDiscCB(
|
||||
uint16_t conn_handle, const ble_gatt_error* error, uint16_t chr_val_handle, const ble_gatt_dsc* dsc, void* arg);
|
||||
uint16_t connHandle, const ble_gatt_error* error, uint16_t chrHandle, const ble_gatt_dsc* dsc, void* arg);
|
||||
|
||||
const NimBLERemoteService* m_pRemoteService{nullptr};
|
||||
uint8_t m_properties{0};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -147,7 +147,10 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||
const ble_gatt_error* error,
|
||||
const ble_gatt_chr* chr,
|
||||
void* arg) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristic Discovery >>");
|
||||
NIMBLE_LOGD(LOG_TAG,
|
||||
"Characteristic Discovery >> status: %d handle: %d",
|
||||
error->status,
|
||||
(error->status == 0) ? chr->def_handle : -1);
|
||||
auto pTaskData = (NimBLETaskData*)arg;
|
||||
const auto pSvc = (NimBLERemoteService*)pTaskData->m_pInstance;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,6 +21,7 @@
|
||||
# include "NimBLERemoteValueAttribute.h"
|
||||
# include "NimBLEClient.h"
|
||||
# include "NimBLEUtils.h"
|
||||
# include "NimBLELog.h"
|
||||
|
||||
# include <climits>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -119,19 +119,19 @@ int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
}
|
||||
|
||||
if (!advertisedDevice->m_callbackSent) {
|
||||
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
pScan->m_pScanCallbacks->onDiscovered(advertisedDevice);
|
||||
}
|
||||
|
||||
// If not active scanning or scan response is not available
|
||||
// or extended advertisement scanning, report the result to the callback now.
|
||||
if (pScan->m_scanParams.passive || !isLegacyAdv || !advertisedDevice->isScannable()) {
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent++;
|
||||
// got the scan response report the full data.
|
||||
pScan->m_pScanCallbacks->onResult(advertisedDevice);
|
||||
advertisedDevice->m_callbackSent++;
|
||||
}
|
||||
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
@ -468,19 +468,26 @@ NimBLEScanResults NimBLEScan::getResults() {
|
||||
* @brief Clear the stored results of the scan.
|
||||
*/
|
||||
void NimBLEScan::clearResults() {
|
||||
for (const auto& dev : m_scanResults.m_deviceVec) {
|
||||
delete dev;
|
||||
if (m_scanResults.m_deviceVec.size()) {
|
||||
std::vector<NimBLEAdvertisedDevice*> vSwap{};
|
||||
ble_npl_hw_enter_critical();
|
||||
vSwap.swap(m_scanResults.m_deviceVec);
|
||||
ble_npl_hw_exit_critical(0);
|
||||
for (const auto& dev : vSwap) {
|
||||
delete dev;
|
||||
}
|
||||
}
|
||||
std::vector<NimBLEAdvertisedDevice*>().swap(m_scanResults.m_deviceVec);
|
||||
} // clearResults
|
||||
|
||||
/**
|
||||
* @brief Dump the scan results to the log.
|
||||
*/
|
||||
void NimBLEScanResults::dump() const {
|
||||
#if CONFIG_NIMBLE_CPP_LOG_LEVEL >=3
|
||||
for (const auto& dev : m_deviceVec) {
|
||||
NIMBLE_LOGI(LOG_TAG, "- %s", dev->toString().c_str());
|
||||
}
|
||||
#endif
|
||||
} // dump
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -70,9 +70,11 @@ NimBLEServer::~NimBLEServer() {
|
||||
delete m_pServerCallbacks;
|
||||
}
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
if (m_pClient != nullptr) {
|
||||
delete m_pClient;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -399,10 +401,12 @@ int NimBLEServer::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
}
|
||||
}
|
||||
|
||||
# if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
if (pServer->m_pClient && pServer->m_pClient->m_connHandle == event->disconnect.conn.conn_handle) {
|
||||
// If this was also the client make sure it's flagged as disconnected.
|
||||
pServer->m_pClient->m_connHandle = BLE_HS_CONN_HANDLE_NONE;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (pServer->m_svcChanged) {
|
||||
pServer->resetGATT();
|
||||
@ -607,21 +611,19 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_
|
||||
NIMBLE_LOGD(LOG_TAG,
|
||||
"Gatt %s event",
|
||||
(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR || ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) ? "Read" : "Write");
|
||||
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||
auto val = pAtt->getAttVal();
|
||||
auto pAtt = static_cast<NimBLELocalValueAttribute*>(arg);
|
||||
const NimBLEAttValue& val = pAtt->getAttVal();
|
||||
|
||||
NimBLEConnInfo peerInfo{};
|
||||
ble_gap_conn_find(connHandle, &peerInfo.m_desc);
|
||||
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_DSC:
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR: {
|
||||
// Don't call readEvent if this is an internal read (handle is NONE)
|
||||
if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||
// If the packet header is only 8 bytes then this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if (ctxt->om->om_pkthdr_len > 8 || pAtt->getAttVal().size() <= (ble_att_mtu(connHandle) - 3)) {
|
||||
pAtt->readEvent(peerInfo);
|
||||
}
|
||||
// Don't call readEvent if the buffer len is 0 (this is a follow up to a previous read),
|
||||
// or if this is an internal read (handle is NONE)
|
||||
if (ctxt->om->om_len > 0 && connHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||
pAtt->readEvent(peerInfo);
|
||||
}
|
||||
|
||||
ble_npl_hw_enter_critical();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -91,6 +91,13 @@ void NimBLEService::dump() const {
|
||||
*/
|
||||
bool NimBLEService::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
|
||||
// If started previously and no characteristics have been added or removed,
|
||||
// then we can skip the service registration process.
|
||||
if (m_pSvcDef->characteristics && !getServer()->m_svcChanged) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If started previously, clear everything and start over
|
||||
if (m_pSvcDef->characteristics) {
|
||||
if (m_pSvcDef->characteristics->descriptors) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -37,6 +37,9 @@
|
||||
# include <climits>
|
||||
|
||||
# if defined INC_FREERTOS_H
|
||||
# ifndef CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT
|
||||
# define CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT 31
|
||||
# endif
|
||||
constexpr uint32_t TASK_BLOCK_BIT = (1 << CONFIG_NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT);
|
||||
# endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2024 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* Copyright 2020-2025 Ryan Powell <ryan@nable-embedded.io> and
|
||||
* esp-nimble-cpp, NimBLE-Arduino contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -63,3 +63,19 @@
|
||||
#if defined(CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE) && !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
|
||||
#define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BTDM_BLE_SCAN_DUPL) && defined(CONFIG_BT_CTRL_BLE_SCAN_DUPL)
|
||||
#define CONFIG_BTDM_BLE_SCAN_DUPL CONFIG_BT_CTRL_BLE_SCAN_DUPL
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE) && defined(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user