mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2025-06-25 01:11:40 +02:00
Compare commits
36 Commits
1.1.0
...
remove-ard
Author | SHA1 | Date | |
---|---|---|---|
c218a27dd8 | |||
8883f44d9f | |||
9c7b690771 | |||
641f297120 | |||
7f853fa04b | |||
df4eb9f7d8 | |||
d3a0f95aaf | |||
d9d794ae40 | |||
30d6c399b8 | |||
7815d89dbf | |||
9fa9531e50 | |||
946b971750 | |||
b62358a520 | |||
e45fb8616a | |||
d38865e022 | |||
62d1f67d8b | |||
4f8342e275 | |||
05080abad4 | |||
f5eab87a87 | |||
3c33129600 | |||
3227681476 | |||
cf3227503b | |||
ef049ddf19 | |||
7bec9c240a | |||
1210772332 | |||
7dd4d68806 | |||
28d6492ea4 | |||
dff5122ce2 | |||
6e104dfb45 | |||
b290ca9077 | |||
ae2ff3a638 | |||
43c9d96373 | |||
af24cd7720 | |||
82524c80e3 | |||
9527c41486 | |||
51c49ba9fc |
68
CHANGELOG.md
68
CHANGELOG.md
@ -2,6 +2,70 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.2.0] - 2021-02-08
|
||||
|
||||
### Added
|
||||
- `NimBLECharacteristic::getDescriptorByHandle`: Return the BLE Descriptor for the given handle.
|
||||
|
||||
- `NimBLEDescriptor::getStringValue`: Get the value of this descriptor as a string.
|
||||
|
||||
- `NimBLEServer::getServiceByHandle`: Get a service by its handle.
|
||||
|
||||
- `NimBLEService::getCharacteristicByHandle`: Get a pointer to the characteristic object with the specified handle.
|
||||
|
||||
- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
|
||||
Overloads to get a vector containing pointers to all the characteristics in a service with the UUID. (supports multiple same UUID's in a service)
|
||||
- `NimBLEService::getCharacteristics(const char *uuid)`
|
||||
- `NimBLEService::getCharacteristics(const NimBLEUUID &uuid)`
|
||||
|
||||
- `NimBLEAdvertisementData` New methods:
|
||||
- `NimBLEAdvertisementData::addTxPower`: Adds transmission power to the advertisement.
|
||||
- `NimBLEAdvertisementData::setPreferredParams`: Adds connection parameters to the advertisement.
|
||||
- `NimBLEAdvertisementData::setURI`: Adds URI data to the advertisement.
|
||||
|
||||
- `NimBLEAdvertising` New methods:
|
||||
- `NimBLEAdvertising::setName`: Set the name advertised.
|
||||
- `NimBLEAdvertising::setManufacturerData`: Adds manufacturer data to the advertisement.
|
||||
- `NimBLEAdvertising::setURI`: Adds URI data to the advertisement.
|
||||
- `NimBLEAdvertising::setServiceData`: Adds service data to the advertisement.
|
||||
- `NimBLEAdvertising::addTxPower`: Adds transmission power to the advertisement.
|
||||
- `NimBLEAdvertising::reset`: Stops the current advertising and resets the advertising data to the default values.
|
||||
|
||||
- `NimBLEDevice::setScanFilterMode`: Set the controller duplicate filter mode for filtering scanned devices.
|
||||
|
||||
- `NimBLEDevice::setScanDuplicateCacheSize`: Sets the number of advertisements filtered before the cache is reset.
|
||||
|
||||
- `NimBLEScan::setMaxResults`: This allows for setting a maximum number of advertised devices stored in the results vector.
|
||||
|
||||
- `NimBLEAdvertisedDevice` New data retrieval methods added:
|
||||
- `haveAdvInterval/getAdvInterval`: checks if the interval is advertised / gets the advertisement interval value.
|
||||
|
||||
- `haveConnParams/getMinInterval/getMaxInterval`: checks if the parameters are advertised / get min value / get max value.
|
||||
|
||||
- `haveURI/getURI`: checks if a URI is advertised / gets the URI data.
|
||||
|
||||
- `haveTargetAddress/getTargetAddressCount/getTargetAddress(index)`: checks if a target address is present / gets a count of the addresses targeted / gets the address of the target at index.
|
||||
|
||||
### Changed
|
||||
- `nimconfig.h` (Arduino) is now easier to use.
|
||||
|
||||
- `NimBLEServer::getServiceByUUID` Now takes an extra parameter of instanceID to support multiple services with the same UUID.
|
||||
|
||||
- `NimBLEService::getCharacteristic` Now takes an extra parameter of instanceID to support multiple characteristics with the same UUID.
|
||||
|
||||
- `NimBLEAdvertising` Transmission power is no longer advertised by default and can be added to the advertisement by calling `NimBLEAdvertising::addTxPower`
|
||||
|
||||
- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisment.
|
||||
|
||||
- `NimBLEScan` Now uses the controller duplicate filter.
|
||||
|
||||
- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
|
||||
Instead the data will be parsed on-demand when the user application asks for specific data.
|
||||
|
||||
### Fixed
|
||||
- `NimBLEHIDDevice` Characteristics now use encryption, this resolves an issue with communicating with devices requiring encryption for HID devices.
|
||||
|
||||
|
||||
## [1.1.0] - 2021-01-20
|
||||
|
||||
### Added
|
||||
@ -9,7 +73,7 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
- New examples for securing and authenticating client/server connections, by mblasee.
|
||||
|
||||
- `NimBLEAdvertiseing::SetMinPreferred` and `NimBLEAdvertiseing::SetMinPreferred` re-added.
|
||||
- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
|
||||
|
||||
- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
|
||||
|
||||
@ -71,6 +135,7 @@ advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
|
||||
|
||||
- (Arduino) Ensure controller mode is set to BLE Only.
|
||||
|
||||
|
||||
## [1.0.2] - 2020-09-13
|
||||
|
||||
### Changed
|
||||
@ -84,6 +149,7 @@ Any changes to the controller max connection settings in `sdkconfig.h` will now
|
||||
- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
|
||||
a task running on core 0 (same as the controller) has been implemented. This improves response times and reliability for all BLE functions.
|
||||
|
||||
|
||||
## [1.0.1] - 2020-09-02
|
||||
|
||||
### Added
|
||||
|
@ -2,9 +2,33 @@
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(SUPPORTED_TARGETS esp32)
|
||||
idf_build_get_property(__hack_component_targets __COMPONENT_TARGETS)
|
||||
|
||||
set(COMPONENT_SRCS
|
||||
if("esp-nimble-component" IN_LIST BUILD_COMPONENTS OR "__esp-nimble-component" IN_LIST __hack_component_targets)
|
||||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif("nimble" IN_LIST BUILD_COMPONENTS OR "__nimble" IN_LIST __hack_component_targets)
|
||||
list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
# Dont use arduino bullshit
|
||||
#if("arduino" IN_LIST BUILD_COMPONENTS OR __hack_component_targets MATCHES "__idf_arduino")
|
||||
# list(APPEND ESP_NIMBLE_PRIV_REQUIRES
|
||||
# arduino
|
||||
# )
|
||||
#endif()
|
||||
|
||||
idf_component_register(
|
||||
REQUIRED_IDF_TARGETS
|
||||
"esp32"
|
||||
"esp32s3"
|
||||
"esp32c3"
|
||||
INCLUDE_DIRS
|
||||
"src"
|
||||
SRCS
|
||||
"src/FreeRTOS.cpp"
|
||||
"src/NimBLE2904.cpp"
|
||||
"src/NimBLEAddress.cpp"
|
||||
@ -17,6 +41,7 @@ set(COMPONENT_SRCS
|
||||
"src/NimBLEDevice.cpp"
|
||||
"src/NimBLEEddystoneTLM.cpp"
|
||||
"src/NimBLEEddystoneURL.cpp"
|
||||
"src/NimBLEHIDDevice.cpp"
|
||||
"src/NimBLERemoteCharacteristic.cpp"
|
||||
"src/NimBLERemoteDescriptor.cpp"
|
||||
"src/NimBLERemoteService.cpp"
|
||||
@ -26,31 +51,15 @@ set(COMPONENT_SRCS
|
||||
"src/NimBLEService.cpp"
|
||||
"src/NimBLEUtils.cpp"
|
||||
"src/NimBLEUUID.cpp"
|
||||
)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
src
|
||||
)
|
||||
|
||||
set(COMPONENT_PRIV_REQUIRES
|
||||
nvs_flash
|
||||
REQUIRES
|
||||
bt
|
||||
nvs_flash
|
||||
esp_ringbuf
|
||||
PRIV_REQUIRES
|
||||
${ESP_NIMBLE_PRIV_REQUIRES}
|
||||
)
|
||||
|
||||
if(COMPONENTS MATCHES "esp-nimble-component")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif(COMPONENTS MATCHES "nimble")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
if(COMPONENTS MATCHES "arduino")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
arduino
|
||||
)
|
||||
endif()
|
||||
|
||||
register_component()
|
||||
target_compile_options(${COMPONENT_TARGET}
|
||||
PUBLIC
|
||||
-DDONT_USE_ARDUINO_BULLSHIT
|
||||
)
|
||||
|
57
CMakeLists.txt_idf3
Normal file
57
CMakeLists.txt_idf3
Normal file
@ -0,0 +1,57 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(SUPPORTED_TARGETS esp32)
|
||||
|
||||
set(COMPONENT_SRCS
|
||||
"src/FreeRTOS.cpp"
|
||||
"src/NimBLE2904.cpp"
|
||||
"src/NimBLEAddress.cpp"
|
||||
"src/NimBLEAdvertisedDevice.cpp"
|
||||
"src/NimBLEAdvertising.cpp"
|
||||
"src/NimBLEBeacon.cpp"
|
||||
"src/NimBLECharacteristic.cpp"
|
||||
"src/NimBLEClient.cpp"
|
||||
"src/NimBLEDescriptor.cpp"
|
||||
"src/NimBLEDevice.cpp"
|
||||
"src/NimBLEEddystoneTLM.cpp"
|
||||
"src/NimBLEEddystoneURL.cpp"
|
||||
"src/NimBLEHIDDevice.cpp"
|
||||
"src/NimBLERemoteCharacteristic.cpp"
|
||||
"src/NimBLERemoteDescriptor.cpp"
|
||||
"src/NimBLERemoteService.cpp"
|
||||
"src/NimBLEScan.cpp"
|
||||
"src/NimBLESecurity.cpp"
|
||||
"src/NimBLEServer.cpp"
|
||||
"src/NimBLEService.cpp"
|
||||
"src/NimBLEUtils.cpp"
|
||||
"src/NimBLEUUID.cpp"
|
||||
)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
src
|
||||
)
|
||||
|
||||
set(COMPONENT_PRIV_REQUIRES
|
||||
nvs_flash
|
||||
bt
|
||||
)
|
||||
|
||||
if(COMPONENTS MATCHES "esp-nimble-component")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
esp-nimble-component
|
||||
)
|
||||
elseif(COMPONENTS MATCHES "nimble")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
nimble
|
||||
)
|
||||
endif()
|
||||
|
||||
if(COMPONENTS MATCHES "arduino")
|
||||
list(APPEND COMPONENT_PRIV_REQUIRES
|
||||
arduino
|
||||
)
|
||||
endif()
|
||||
|
||||
register_component()
|
@ -1,27 +0,0 @@
|
||||
menu "ESP-NimBLE-CPP configuration"
|
||||
|
||||
config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
bool "Show NimBLE return codes as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display return code values as text
|
||||
messages in the debug log. This will use approximately 8kB
|
||||
of flash memory.
|
||||
|
||||
config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
bool "Show NimBLE gap events as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display gap event codes as text
|
||||
messages in the debug log. This will use approximately 1kB
|
||||
of flash memory.
|
||||
|
||||
config NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
bool "Show advertisment types as text in debug log."
|
||||
default "n"
|
||||
help
|
||||
Enabling this option will display advertisment types recieved
|
||||
while scanning as text messages in the debug log.
|
||||
This will use approximately 250 bytes of flash memory.
|
||||
|
||||
endmenu
|
@ -1,27 +1,21 @@
|
||||
# Arduino command line and platformio config options
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED`
|
||||
|
||||
If defined, NimBLE Client functions will not be included.
|
||||
- Reduces flash size by approx. 7kB.
|
||||
`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`
|
||||
|
||||
Sets the number of simultaneous connections (esp controller max is 9)
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED`
|
||||
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||
|
||||
If defined, NimBLE Scan functions will not be included.
|
||||
- Reduces flash size by approx. 26kB.
|
||||
Sets the default MTU size.
|
||||
- Default value is 255
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED`
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME`
|
||||
|
||||
If defined NimBLE Server functions will not be included.
|
||||
- Reduces flash size by approx. 16kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED`
|
||||
|
||||
If defined, NimBLE Advertising functions will not be included.
|
||||
- Reduces flash size by approx. 5kB.
|
||||
Set the default device name
|
||||
- Default value is "nimble"
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_DEBUG`
|
||||
@ -48,6 +42,67 @@ If defined, advertisment types will be printed as text while scanning in debug l
|
||||
- Uses approx. 250 bytes of flash memory.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE`
|
||||
|
||||
Set the default appearance.
|
||||
- Default value is 0x00
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED`
|
||||
|
||||
If defined, NimBLE Client functions will not be included.
|
||||
- Reduces flash size by approx. 7kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED`
|
||||
|
||||
If defined, NimBLE Scan functions will not be included.
|
||||
- Reduces flash size by approx. 26kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED`
|
||||
|
||||
If defined NimBLE Server functions will not be included.
|
||||
- Reduces flash size by approx. 16kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED`
|
||||
|
||||
If defined, NimBLE Advertising functions will not be included.
|
||||
- Reduces flash size by approx. 5kB.
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_BONDS`
|
||||
|
||||
Sets the number of devices allowed to store/bond with
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CCCDS`
|
||||
|
||||
Sets the maximum number of CCCD subscriptions to store
|
||||
- Default value is 8
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_RPA_TIMEOUT`
|
||||
|
||||
Sets the random address refresh time in seconds.
|
||||
- Default value is 900
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT`
|
||||
|
||||
Set the number of msys blocks For prepare write & prepare responses. This may need to be increased if
|
||||
you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
- Default value is 12
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL`
|
||||
|
||||
Sets the NimBLE stack to use external PSRAM will be loaded
|
||||
- Must be defined with a value of 1; Default is CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_PINNED_TO_CORE`
|
||||
|
||||
Sets the core the NimBLE host stack will run on
|
||||
@ -56,37 +111,7 @@ Sets the core the NimBLE host stack will run on
|
||||
|
||||
`CONFIG_BT_NIMBLE_TASK_STACK_SIZE`
|
||||
|
||||
Set the task stack size for the NimBLE core.
|
||||
Set the task stack size for the NimBLE core.
|
||||
- Default is 4096
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL`
|
||||
|
||||
Sets the NimBLE stack to use external PSRAM will be loaded
|
||||
- Must be defined with a value of 1; Default is CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CONNECTIONS`
|
||||
|
||||
Sets the number of simultaneous connections (esp controller max is 9)
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_BONDS`
|
||||
|
||||
Sets the number of devices allowed to store/bond with
|
||||
- Default value is 3
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_MAX_CCCDS`
|
||||
|
||||
Sets the maximum number of CCCD subscriptions to store
|
||||
- Default value is 8
|
||||
<br/>
|
||||
|
||||
`CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME`
|
||||
|
||||
Set the default device name
|
||||
- Default value is "nimble"
|
||||
<br/>
|
||||
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "esp-nimble-cpp / NimBLE-Arduino"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 1.1.0
|
||||
PROJECT_NUMBER = 1.2.0
|
||||
|
||||
# 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
|
||||
@ -2179,8 +2179,12 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = CONFIG_BT_ENABLED \
|
||||
_DOXYGEN_
|
||||
PREDEFINED = _DOXYGEN_ \
|
||||
CONFIG_BT_ENABLED \
|
||||
CONFIG_BT_NIMBLE_ROLE_CENTRAL \
|
||||
CONFIG_BT_NIMBLE_ROLE_OBSERVER \
|
||||
CONFIG_BT_NIMBLE_ROLE_PERIPHERAL \
|
||||
CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
@ -69,6 +69,8 @@ For example `BLEServer::createService(SERVICE_UUID)` will work just as it did be
|
||||
|
||||
<a name="characteristics"></a>
|
||||
### Characteristics
|
||||
The constructor for `(Nim)BLECharacteristic` is now private, so if you currently subclass it to add logic you should switch to use `NimBLEService::createCharacteristic` instead. Any custom processing logic previously in a `BLECharacteristic` subclass should be moved to a `NimBLECharacteristicCallbacks` subclass instead, and passed into `NimBLECharacteristic::setCallbacks`.
|
||||
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
@ -218,10 +220,11 @@ If you wish to advertise these parameters you can still do so manually via `BLEA
|
||||
<br/>
|
||||
|
||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
||||
`NimBLEAdvertising::setAppearance`. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
|
||||
Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.
|
||||
~~Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.~~
|
||||
No longer true as of release 1.2.0 and above, custom scan response is now supported without custom advertisement data.
|
||||
<br/>
|
||||
|
||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
||||
|
@ -155,7 +155,7 @@ void FreeRTOS::Semaphore::give() {
|
||||
} else {
|
||||
xSemaphoreGive(m_semaphore);
|
||||
}
|
||||
// #ifdef ARDUINO_ARCH_ESP32
|
||||
// #if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
// FreeRTOS::sleep(10);
|
||||
// #endif
|
||||
|
||||
@ -243,7 +243,7 @@ bool FreeRTOS::Semaphore::take(uint32_t timeoutMs, std::string owner) {
|
||||
std::string FreeRTOS::Semaphore::toString() {
|
||||
char hex[9];
|
||||
std::string res = "name: " + m_name + " (0x";
|
||||
snprintf(hex, sizeof(hex), "%08x", (uint32_t)m_semaphore);
|
||||
snprintf(hex, sizeof(hex), "%08lx", (uint32_t)m_semaphore);
|
||||
res += hex;
|
||||
res += "), owner: " + m_owner;
|
||||
return res;
|
||||
|
@ -45,7 +45,7 @@
|
||||
/* of data as per HID Class standard */
|
||||
|
||||
/* Main items */
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#define HIDINPUT(size) (0x80 | size)
|
||||
#define HIDOUTPUT(size) (0x90 | size)
|
||||
#else
|
||||
|
@ -42,6 +42,7 @@ struct BLE2904_Data {
|
||||
*/
|
||||
class NimBLE2904: public NimBLEDescriptor {
|
||||
public:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic = nullptr);
|
||||
static const uint8_t FORMAT_BOOLEAN = 1;
|
||||
static const uint8_t FORMAT_UINT2 = 2;
|
||||
static const uint8_t FORMAT_UINT4 = 3;
|
||||
@ -77,7 +78,6 @@ public:
|
||||
void setUnit(uint16_t unit);
|
||||
|
||||
private:
|
||||
NimBLE2904(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
BLE2904_Data m_data;
|
||||
}; // BLE2904
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEADDRESS_H_
|
||||
#define COMPONENTS_NIMBLEADDRESS_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimble/ble.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -28,25 +28,14 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() {
|
||||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() :
|
||||
m_payload(62,0)
|
||||
{
|
||||
m_advType = 0;
|
||||
m_appearance = 0;
|
||||
m_manufacturerData = "";
|
||||
m_name = "";
|
||||
m_rssi = -9999;
|
||||
m_txPower = 0;
|
||||
m_payloadLength = 0;
|
||||
m_payload = nullptr;
|
||||
|
||||
m_haveAppearance = false;
|
||||
m_haveManufacturerData = false;
|
||||
m_haveName = false;
|
||||
m_haveRSSI = false;
|
||||
m_haveServiceData = false;
|
||||
m_haveServiceUUID = false;
|
||||
m_haveTXPower = false;
|
||||
m_callbackSent = false;
|
||||
|
||||
m_callbackSent = false;
|
||||
m_timestamp = 0;
|
||||
m_advLength = 0;
|
||||
} // NimBLEAdvertisedDevice
|
||||
|
||||
|
||||
@ -82,25 +71,126 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||
* @return The appearance of the advertised device.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||
return m_appearance;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_APPEARANCE_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertisement interval.
|
||||
* @return The advertisement interval in 0.625ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_ADV_ITVL_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getAdvInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the preferred min connection interval.
|
||||
* @return The preferred min connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||
return *field->value | *(field->value + 1) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getMinInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the preferred max connection interval.
|
||||
* @return The preferred max connection interval in 1.25ms units.
|
||||
*/
|
||||
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1) {
|
||||
return *(field->value + 2) | *(field->value + 3) << 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
} // getMaxInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the manufacturer data.
|
||||
* @return The manufacturer data of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||
return m_manufacturerData;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the URI from the advertisement.
|
||||
* @return The URI data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getURI() {
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised name.
|
||||
* @return The name of the advertised device.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getName() {
|
||||
return m_name;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
||||
{
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > 1) {
|
||||
return std::string((char*)field->value, field->length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} // getName
|
||||
|
||||
|
||||
@ -122,17 +212,70 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
||||
} // getScan
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the number of target addresses.
|
||||
* @return The number of addresses.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the target address at the index.
|
||||
* @param [in] index The index of the target address.
|
||||
* @return The target address.
|
||||
*/
|
||||
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0xFF;
|
||||
|
||||
index++;
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||
|
||||
if (count < index) {
|
||||
index -= count;
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
||||
}
|
||||
|
||||
if(count > 0 && data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
if(field->length > index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||
return NimBLEAddress(field->value + (index - 1) * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
return NimBLEAddress("");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service data.
|
||||
* @param [in] index The vector index of the service data requested.
|
||||
* @param [in] index The index of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||
if(index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: index out of range");
|
||||
return "";
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length > bytes) {
|
||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||
}
|
||||
}
|
||||
return m_serviceDataVec[index].second;
|
||||
|
||||
return "";
|
||||
} //getServiceData
|
||||
|
||||
|
||||
@ -141,51 +284,148 @@ std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||
* @param [in] uuid The uuid of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) const {
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
return it.second;
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t index = 0;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||
uint8_t plSize = m_payload.size() - 2;
|
||||
|
||||
while(data_loc < plSize) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(bytes == uuidBytes && NimBLEUUID(field->value, bytes, false) == uuid) {
|
||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||
}
|
||||
|
||||
index++;
|
||||
data_loc = findServiceData(index, &bytes);
|
||||
}
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: uuid not found");
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "No service data found");
|
||||
return "";
|
||||
} //getServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised service UUID.
|
||||
* @param [in] index The vector index of the service data UUID requested.
|
||||
* @return The advertised service UUID or an empty UUID if not found.
|
||||
* @brief Get the UUID of the serice data at the index.
|
||||
* @param [in] index The index of the service data UUID requested.
|
||||
* @return The advertised service data UUID or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
if(!haveServiceData() || index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceDataUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t bytes;
|
||||
uint8_t data_loc = findServiceData(index, &bytes);
|
||||
|
||||
if(data_loc != 0xFF) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length >= bytes) {
|
||||
return NimBLEUUID(field->value, bytes, false);
|
||||
}
|
||||
}
|
||||
return m_serviceDataVec[index].first;
|
||||
|
||||
return NimBLEUUID("");
|
||||
} // getServiceDataUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find the service data at the index.
|
||||
* @param [in] index The index of the service data to find.
|
||||
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
||||
* @return The index in the vector where the data is located, 0xFF if not found.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
uint8_t data_loc = 0;
|
||||
uint8_t found = 0;
|
||||
|
||||
*bytes = 0;
|
||||
index++;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 2;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
index -= found;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 4;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
index -= found;
|
||||
found = findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, index, &data_loc);
|
||||
if(found == index) {
|
||||
*bytes = 16;
|
||||
return data_loc;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the count of advertised service data UUIDS
|
||||
* @return The number of service data UUIDS in the vector.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
return m_serviceDataVec.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID128);
|
||||
|
||||
return count;
|
||||
} // getServiceDataCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the Service UUID.
|
||||
* @param [in] index The vector index of the service UUID requested.
|
||||
* @param [in] index The index of the service UUID requested.
|
||||
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
if(!haveServiceUUID() || index > m_serviceUUIDs.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0;
|
||||
uint8_t uuidBytes = 0;
|
||||
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
|
||||
index++;
|
||||
|
||||
do {
|
||||
count = findAdvField(type, index, &data_loc);
|
||||
if(count >= index) {
|
||||
if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS32) {
|
||||
uuidBytes = 2;
|
||||
} else if(type < BLE_HS_ADV_TYPE_INCOMP_UUIDS128) {
|
||||
uuidBytes = 4;
|
||||
} else {
|
||||
uuidBytes = 16;
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
type++;
|
||||
index -= count;
|
||||
}
|
||||
|
||||
} while(type <= BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||
|
||||
if(uuidBytes > 0) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
// In the case of more than one field of service uuid's we need to adjust
|
||||
// the index to account for the uuids of the previous fields.
|
||||
if(field->length < index * uuidBytes) {
|
||||
index -= count - field->length / uuidBytes;
|
||||
}
|
||||
|
||||
if(field->length > uuidBytes * index) {
|
||||
return NimBLEUUID(field->value + uuidBytes * (index - 1), uuidBytes, false);
|
||||
}
|
||||
}
|
||||
return m_serviceUUIDs[index];
|
||||
|
||||
return NimBLEUUID("");
|
||||
} // getServiceUUID
|
||||
|
||||
|
||||
@ -194,18 +434,32 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
* @return The count of services in the advertising packet.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
return m_serviceUUIDs.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS16);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS32);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS128);
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_COMP_UUIDS128);
|
||||
|
||||
return count;
|
||||
} // getServiceUUIDCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check advertised services for existance of the required UUID
|
||||
* @param [in] uuid The service uuid to look for in the advertisement.
|
||||
* @return Return true if service is advertised
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const {
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
||||
size_t count = getServiceUUIDCount();
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
if(uuid == getServiceUUID(i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} // isAdvertisingService
|
||||
|
||||
@ -215,16 +469,43 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const
|
||||
* @return The TX Power of the advertised device.
|
||||
*/
|
||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
||||
return m_txPower;
|
||||
uint8_t data_loc = 0;
|
||||
|
||||
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length == BLE_HS_ADV_TX_PWR_LVL_LEN + 1) {
|
||||
return *(int8_t*)field->value;
|
||||
}
|
||||
}
|
||||
|
||||
return -99;
|
||||
} // getTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have preferred connection parameters?
|
||||
* @return True if connection parameters are present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveConnParams() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE) > 0;
|
||||
} // haveConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have have the advertising interval?
|
||||
* @return True if the advertisement interval is present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveAdvInterval() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL) > 0;
|
||||
} // haveAdvInterval
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have an appearance value?
|
||||
* @return True if there is an appearance value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||
return m_haveAppearance;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_APPEARANCE) > 0;
|
||||
} // haveAppearance
|
||||
|
||||
|
||||
@ -233,16 +514,36 @@ bool NimBLEAdvertisedDevice::haveAppearance() {
|
||||
* @return True if there is manufacturer data present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveManufacturerData() {
|
||||
return m_haveManufacturerData;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_MFG_DATA) > 0;
|
||||
} // haveManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have a URI?
|
||||
* @return True if there is a URI present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveURI() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_URI) > 0;
|
||||
} // haveURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does the advertisement contain a target address?
|
||||
* @return True if an address is present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveTargetAddress() {
|
||||
return findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Does this advertisement have a name value?
|
||||
* @return True if there is a name value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveName() {
|
||||
return m_haveName;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_COMP_NAME) > 0 ||
|
||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME) > 0;
|
||||
} // haveName
|
||||
|
||||
|
||||
@ -251,7 +552,7 @@ bool NimBLEAdvertisedDevice::haveName() {
|
||||
* @return True if there is a signal strength value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||
return m_haveRSSI;
|
||||
return m_rssi != -9999;
|
||||
} // haveRSSI
|
||||
|
||||
|
||||
@ -260,7 +561,7 @@ bool NimBLEAdvertisedDevice::haveRSSI() {
|
||||
* @return True if there is a service data value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||
return m_haveServiceData;
|
||||
return getServiceDataCount() > 0;
|
||||
} // haveServiceData
|
||||
|
||||
|
||||
@ -269,7 +570,7 @@ bool NimBLEAdvertisedDevice::haveServiceData() {
|
||||
* @return True if there is a service UUID value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||
return m_haveServiceUUID;
|
||||
return getServiceUUIDCount() > 0;
|
||||
} // haveServiceUUID
|
||||
|
||||
|
||||
@ -278,143 +579,71 @@ bool NimBLEAdvertisedDevice::haveServiceUUID() {
|
||||
* @return True if there is a transmission power value present.
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||
return m_haveTXPower;
|
||||
return findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL) > 0;
|
||||
} // haveTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Parse the advertising pay load.
|
||||
*
|
||||
* The pay load is a buffer of bytes that is either 31 bytes long or terminated by
|
||||
* a 0 length value. Each entry in the buffer has the format:
|
||||
* [length][type][data...]
|
||||
*
|
||||
* The length does not include itself but does include everything after it until the next record. A record
|
||||
* with a length value of 0 indicates a terminator.
|
||||
*
|
||||
* https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, uint8_t length) {
|
||||
struct ble_hs_adv_fields fields;
|
||||
int rc = ble_hs_adv_parse_fields(&fields, payload, length);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
|
||||
return;
|
||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t data = 0;
|
||||
uint8_t length = m_payload.size();
|
||||
uint8_t count = 0;
|
||||
|
||||
if(length < 2) {
|
||||
return count;
|
||||
}
|
||||
|
||||
m_payload = payload;
|
||||
m_payloadLength = length;
|
||||
while (length > 1) {
|
||||
field = (ble_hs_adv_field*)&m_payload[data];
|
||||
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, m_payload, m_payloadLength);
|
||||
NIMBLE_LOGD(LOG_TAG,"payload: %s", pHex);
|
||||
free(pHex);
|
||||
#endif
|
||||
|
||||
if (fields.uuids16 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids16; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids16[i].value));
|
||||
if (field->length >= length) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.uuids32 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids32; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids32[i].value));
|
||||
}
|
||||
}
|
||||
if (field->type == type) {
|
||||
switch(type) {
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||
count += field->length / 2;
|
||||
break;
|
||||
|
||||
if (fields.uuids128 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids128; i++) {
|
||||
setServiceUUID(NimBLEUUID(&fields.uuids128[i]));
|
||||
}
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS32:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS32:
|
||||
count += field->length / 4;
|
||||
break;
|
||||
|
||||
if (fields.name != NULL) {
|
||||
setName(std::string(reinterpret_cast<char*>(fields.name), fields.name_len));
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS128:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS128:
|
||||
count += field->length / 16;
|
||||
break;
|
||||
|
||||
if (fields.tx_pwr_lvl_is_present) {
|
||||
setTXPower(fields.tx_pwr_lvl);
|
||||
}
|
||||
case BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR:
|
||||
case BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR:
|
||||
count += field->length / 6;
|
||||
break;
|
||||
|
||||
if (fields.svc_data_uuid16 != NULL ||
|
||||
fields.svc_data_uuid32 != NULL ||
|
||||
fields.svc_data_uuid128 != NULL)
|
||||
{
|
||||
ble_hs_adv_field *field;
|
||||
uint8_t *data = payload;
|
||||
while(length > 1) {
|
||||
field = (ble_hs_adv_field*)data;
|
||||
|
||||
if(field->length > length) {
|
||||
break;
|
||||
default:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID16) {
|
||||
if(field->length > 2) {
|
||||
uint16_t uuid;
|
||||
memcpy(&uuid, field->value, 2);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 2), field->length - 3));
|
||||
if(data_loc != nullptr) {
|
||||
if(index == 0 || count >= index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID32) {
|
||||
if(field->length > 4) {
|
||||
uint32_t uuid;
|
||||
memcpy(&uuid, field->value, 4);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 4), field->length - 5));
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID128) {
|
||||
if(field->length > 16) {
|
||||
NimBLEUUID uuid(field->value, (size_t)16, false);
|
||||
setServiceData(uuid, std::string(reinterpret_cast<char*>(field->value + 16), field->length - 17));
|
||||
}
|
||||
}
|
||||
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
if (fields.appearance_is_present) {
|
||||
setAppearance(fields.appearance);
|
||||
if(data_loc != nullptr && field != nullptr) {
|
||||
*data_loc = data;
|
||||
}
|
||||
|
||||
if (fields.mfg_data != NULL) {
|
||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields.mfg_data), fields.mfg_data_len));
|
||||
}
|
||||
|
||||
/* TODO: create storage and fucntions for these parameters
|
||||
if (fields.public_tgt_addr != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
|
||||
u8p = fields.public_tgt_addr;
|
||||
for (i = 0; i < fields.num_public_tgt_addrs; i++) {
|
||||
NIMBLE_LOGD(LOG_TAG, "public_tgt_addr=%s ", addr_str(u8p));
|
||||
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields.slave_itvl_range != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " slave_itvl_range=");
|
||||
print_bytes(fields.slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields.adv_itvl_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " adv_itvl=0x%04x\n", fields.adv_itvl);
|
||||
}
|
||||
|
||||
if (fields.uri != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " uri=");
|
||||
print_bytes(fields.uri, fields.uri_len);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
*/
|
||||
|
||||
} //parseAdvertisement
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -428,106 +657,22 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
||||
|
||||
/**
|
||||
* @brief Set the adFlag for this device.
|
||||
* @param [in] The discovered adFlag.
|
||||
* @param [in] advType The advertisement flag data from the advertisement.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
||||
m_advType = advType;
|
||||
} // setAdvType
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the appearance for this device.
|
||||
* @param [in] The discovered appearance.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setAppearance(uint16_t appearance) {
|
||||
m_appearance = appearance;
|
||||
m_haveAppearance = true;
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the manufacturer data for this device.
|
||||
* @param [in] The discovered manufacturer data.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
|
||||
m_manufacturerData = manufacturerData;
|
||||
m_haveManufacturerData = true;
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the name for this device.
|
||||
* @param [in] name The discovered name.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setName(std::string name) {
|
||||
m_name = name;
|
||||
m_haveName = true;
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the RSSI for this device.
|
||||
* @param [in] rssi The discovered RSSI.
|
||||
* @param [in] rssi The RSSI of the discovered device.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
||||
m_rssi = rssi;
|
||||
m_haveRSSI = true;
|
||||
m_rssi = rssi;
|
||||
} // setRSSI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Service UUID for this device.
|
||||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
*/
|
||||
|
||||
void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
|
||||
return setServiceUUID(NimBLEUUID(serviceUUID));
|
||||
} // setServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Service UUID for this device.
|
||||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
||||
// Don't add duplicates
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
if (m_serviceUUIDs[i] == serviceUUID) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
m_haveServiceUUID = true;
|
||||
} // setServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the ServiceData value.
|
||||
* @param [in] uuid The UUID that the service data belongs to.
|
||||
* @param [in] data The service data.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceData(NimBLEUUID uuid, std::string data) {
|
||||
m_haveServiceData = true;
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
it.second = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceDataVec.push_back({uuid, data});
|
||||
} //setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the power level for this device.
|
||||
* @param [in] txPower The discovered power level.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
||||
m_txPower = txPower;
|
||||
m_haveTXPower = true;
|
||||
} // setTXPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a string representation of this device.
|
||||
* @return A string representation of this device.
|
||||
@ -579,10 +724,35 @@ std::string NimBLEAdvertisedDevice::toString() {
|
||||
* @return The advertisement payload.
|
||||
*/
|
||||
uint8_t* NimBLEAdvertisedDevice::getPayload() {
|
||||
return m_payload;
|
||||
return &m_payload[0];
|
||||
} // getPayload
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stores the payload of the advertised device in a vector.
|
||||
* @param [in] payload The advertisement payload.
|
||||
* @param [in] length The length of the payload in bytes.
|
||||
* @param [in] append Indicates if the the data should be appended (scan response).
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setPayload(const uint8_t *payload, uint8_t length, bool append) {
|
||||
if(!append) {
|
||||
m_advLength = length;
|
||||
m_payload.assign(payload, payload + length);
|
||||
} else {
|
||||
m_payload.insert(m_payload.end(), payload, payload + length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the length of the advertisement data in the payload.
|
||||
* @return The number of bytes in the payload that is from the advertisment.
|
||||
*/
|
||||
uint8_t NimBLEAdvertisedDevice::getAdvLength() {
|
||||
return m_advLength;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertised device address type.
|
||||
* @return The device address type:
|
||||
@ -610,7 +780,7 @@ time_t NimBLEAdvertisedDevice::getTimestamp() {
|
||||
* @return The size of the payload in bytes.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||
return m_payloadLength;
|
||||
return m_payload.size();
|
||||
} // getPayloadLength
|
||||
|
||||
|
||||
|
@ -44,7 +44,11 @@ public:
|
||||
NimBLEAddress getAddress();
|
||||
uint8_t getAdvType();
|
||||
uint16_t getAppearance();
|
||||
uint16_t getAdvInterval();
|
||||
uint16_t getMinInterval();
|
||||
uint16_t getMaxInterval();
|
||||
std::string getManufacturerData();
|
||||
std::string getURI();
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <type\>.
|
||||
@ -67,7 +71,7 @@ public:
|
||||
NimBLEScan* getScan();
|
||||
size_t getServiceDataCount();
|
||||
std::string getServiceData(uint8_t index = 0);
|
||||
std::string getServiceData(const NimBLEUUID &uuid) const;
|
||||
std::string getServiceData(const NimBLEUUID &uuid);
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||
@ -106,12 +110,15 @@ public:
|
||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||
size_t getServiceUUIDCount();
|
||||
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||
size_t getTargetAddressCount();
|
||||
int8_t getTXPower();
|
||||
uint8_t* getPayload();
|
||||
uint8_t getAdvLength();
|
||||
size_t getPayloadLength();
|
||||
uint8_t getAddressType();
|
||||
time_t getTimestamp();
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid) const;
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
@ -119,46 +126,30 @@ public:
|
||||
bool haveServiceData();
|
||||
bool haveServiceUUID();
|
||||
bool haveTXPower();
|
||||
bool haveConnParams();
|
||||
bool haveAdvInterval();
|
||||
bool haveTargetAddress();
|
||||
bool haveURI();
|
||||
std::string toString();
|
||||
|
||||
private:
|
||||
friend class NimBLEScan;
|
||||
|
||||
void parseAdvertisement(uint8_t* payload, uint8_t length);
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setManufacturerData(std::string manufacturerData);
|
||||
void setName(std::string name);
|
||||
void setRSSI(int rssi);
|
||||
void setServiceData(NimBLEUUID serviceUUID, std::string data);
|
||||
void setServiceUUID(const char* serviceUUID);
|
||||
void setServiceUUID(NimBLEUUID serviceUUID);
|
||||
void setTXPower(int8_t txPower);
|
||||
|
||||
bool m_haveAppearance;
|
||||
bool m_haveManufacturerData;
|
||||
bool m_haveName;
|
||||
bool m_haveRSSI;
|
||||
bool m_haveServiceData;
|
||||
bool m_haveServiceUUID;
|
||||
bool m_haveTXPower;
|
||||
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
||||
void setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
|
||||
NimBLEAddress m_address = NimBLEAddress("");
|
||||
uint8_t m_advType;
|
||||
uint16_t m_appearance;
|
||||
std::string m_manufacturerData;
|
||||
std::string m_name;
|
||||
int m_rssi;
|
||||
int8_t m_txPower;
|
||||
uint8_t* m_payload;
|
||||
size_t m_payloadLength;
|
||||
time_t m_timestamp;
|
||||
bool m_callbackSent;
|
||||
uint8_t m_advLength;
|
||||
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
std::vector<std::pair<NimBLEUUID, std::string>>m_serviceDataVec;
|
||||
std::vector<uint8_t> m_payload;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -32,23 +32,29 @@ static const char* LOG_TAG = "NimBLEAdvertising";
|
||||
/**
|
||||
* @brief Construct a default advertising object.
|
||||
*/
|
||||
NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() {
|
||||
NimBLEAdvertising::NimBLEAdvertising() {
|
||||
reset();
|
||||
} // NimBLEAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stops the current advertising and resets the advertising data to the default values.
|
||||
*/
|
||||
void NimBLEAdvertising::reset() {
|
||||
if(NimBLEDevice::getInitialized() && isAdvertising()) {
|
||||
stop();
|
||||
}
|
||||
memset(&m_advData, 0, sizeof m_advData);
|
||||
memset(&m_scanData, 0, sizeof m_scanData);
|
||||
memset(&m_advParams, 0, sizeof m_advParams);
|
||||
memset(&m_slaveItvl, 0, sizeof m_slaveItvl);
|
||||
const char *name = ble_svc_gap_device_name();
|
||||
|
||||
m_advData.name = (uint8_t *)name;
|
||||
m_advData.name_len = strlen(name);
|
||||
m_advData.name_is_complete = 1;
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
|
||||
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
||||
m_advData.appearance = 0;
|
||||
m_advData.appearance_is_present = 0;
|
||||
m_advData.mfg_data_len = 0;
|
||||
m_advData.mfg_data = nullptr;
|
||||
m_advData.slave_itvl_range = nullptr;
|
||||
|
||||
#if !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_NON;
|
||||
@ -56,17 +62,13 @@ NimBLEAdvertising::NimBLEAdvertising() : m_slaveItvl() {
|
||||
m_advParams.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||
#endif
|
||||
m_advParams.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
m_advParams.itvl_min = 0;
|
||||
m_advParams.itvl_max = 0;
|
||||
|
||||
m_customAdvData = false;
|
||||
m_customScanResponseData = false;
|
||||
m_scanResp = true;
|
||||
m_advDataSet = false;
|
||||
// Set this to non-zero to prevent auto start if host reset before started by app.
|
||||
m_duration = BLE_HS_FOREVER;
|
||||
|
||||
} // NimBLEAdvertising
|
||||
} // reset
|
||||
|
||||
|
||||
/**
|
||||
@ -85,6 +87,7 @@ void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||
*/
|
||||
void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
||||
addServiceUUID(NimBLEUUID(serviceUUID));
|
||||
m_advDataSet = false;
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
@ -112,9 +115,95 @@ void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||
void NimBLEAdvertising::setAppearance(uint16_t appearance) {
|
||||
m_advData.appearance = appearance;
|
||||
m_advData.appearance_is_present = 1;
|
||||
m_advDataSet = false;
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add the transmission power level to the advertisement packet.
|
||||
*/
|
||||
void NimBLEAdvertising::addTxPower() {
|
||||
m_advData.tx_pwr_lvl_is_present = 1;
|
||||
m_advDataSet = false;
|
||||
} // addTxPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised name of the device.
|
||||
* @param [in] name The name to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setName(const std::string &name) {
|
||||
m_name.assign(name.begin(), name.end());
|
||||
m_advData.name = &m_name[0];
|
||||
m_advData.name_len = m_name.size();
|
||||
m_advDataSet = false;
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised manufacturer data.
|
||||
* @param [in] data The data to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setManufacturerData(const std::string &data) {
|
||||
m_mfgData.assign(data.begin(), data.end());
|
||||
m_advData.mfg_data = &m_mfgData[0];
|
||||
m_advData.mfg_data_len = m_mfgData.size();
|
||||
m_advDataSet = false;
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertised URI.
|
||||
* @param [in] uri The URI to advertise.
|
||||
*/
|
||||
void NimBLEAdvertising::setURI(const std::string &uri) {
|
||||
m_uri.assign(uri.begin(), uri.end());
|
||||
m_advData.uri = &m_uri[0];
|
||||
m_advData.uri_len = m_uri.size();
|
||||
m_advDataSet = false;
|
||||
} // setURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the service data advertised for the UUID.
|
||||
* @param [in] uuid The UUID the service data belongs to.
|
||||
* @param [in] data The data to advertise.
|
||||
* @note If data length is 0 the service data will not be advertised.
|
||||
*/
|
||||
void NimBLEAdvertising::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
m_svcData16.assign((uint8_t*)&uuid.getNative()->u16.value, (uint8_t*)&uuid.getNative()->u16.value + 2);
|
||||
m_svcData16.insert(m_svcData16.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid16 = (uint8_t*)&m_svcData16[0];
|
||||
m_advData.svc_data_uuid16_len = (data.length() > 0) ? m_svcData16.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
m_svcData32.assign((uint8_t*)&uuid.getNative()->u32.value, (uint8_t*)&uuid.getNative()->u32.value + 4);
|
||||
m_svcData32.insert(m_svcData32.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid32 = (uint8_t*)&m_svcData32[0];
|
||||
m_advData.svc_data_uuid32_len = (data.length() > 0) ? m_svcData32.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
m_svcData128.assign(uuid.getNative()->u128.value, uuid.getNative()->u128.value + 16);
|
||||
m_svcData128.insert(m_svcData128.end(), data.begin(), data.end());
|
||||
m_advData.svc_data_uuid128 = (uint8_t*)&m_svcData128[0];
|
||||
m_advData.svc_data_uuid128_len = (data.length() > 0) ? m_svcData128.size() : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the type of advertisment to use.
|
||||
* @param [in] adv_type:
|
||||
@ -172,6 +261,8 @@ void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
|
||||
m_slaveItvl[2] = m_slaveItvl[0];
|
||||
m_slaveItvl[3] = m_slaveItvl[1];
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setMinPreferred
|
||||
|
||||
|
||||
@ -200,6 +291,8 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||
m_slaveItvl[0] = m_slaveItvl[2];
|
||||
m_slaveItvl[1] = m_slaveItvl[3];
|
||||
}
|
||||
|
||||
m_advDataSet = false;
|
||||
} // setMaxPreferred
|
||||
|
||||
|
||||
@ -209,6 +302,7 @@ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||
*/
|
||||
void NimBLEAdvertising::setScanResponse(bool set) {
|
||||
m_scanResp = set;
|
||||
m_advDataSet = false;
|
||||
} // setScanResponse
|
||||
|
||||
|
||||
@ -344,12 +438,29 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
if (!m_customAdvData && !m_advDataSet) {
|
||||
//start with 3 bytes for the flags data
|
||||
uint8_t payloadLen = (2 + 1);
|
||||
if(m_advData.mfg_data_len > 0)
|
||||
payloadLen += (2 + m_advData.mfg_data_len);
|
||||
|
||||
if(m_advData.svc_data_uuid16_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid16_len);
|
||||
|
||||
if(m_advData.svc_data_uuid32_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid32_len);
|
||||
|
||||
if(m_advData.svc_data_uuid128_len > 0)
|
||||
payloadLen += (2 + m_advData.svc_data_uuid128_len);
|
||||
|
||||
if(m_advData.uri_len > 0)
|
||||
payloadLen += (2 + m_advData.uri_len);
|
||||
|
||||
if(m_advData.appearance_is_present)
|
||||
payloadLen += (2 + BLE_HS_ADV_APPEARANCE_LEN);
|
||||
|
||||
if(m_advData.tx_pwr_lvl_is_present)
|
||||
payloadLen += (2 + 1);
|
||||
payloadLen += (2 + BLE_HS_ADV_TX_PWR_LVL_LEN);
|
||||
|
||||
if(m_advData.slave_itvl_range != nullptr)
|
||||
payloadLen += (2 + 4);
|
||||
payloadLen += (2 + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
|
||||
for(auto &it : m_serviceUUIDs) {
|
||||
if(it.getNative()->u.type == BLE_UUID_TYPE_16) {
|
||||
@ -360,16 +471,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc(m_advData.uuids16,
|
||||
if(nullptr == (m_advData.uuids16 = (ble_uuid16_t*)realloc((void*)m_advData.uuids16,
|
||||
(m_advData.num_uuids16 + 1) * sizeof(ble_uuid16_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids16[m_advData.num_uuids16].value,
|
||||
&it.getNative()->u16.value, 2);
|
||||
|
||||
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
|
||||
memcpy((void*)&m_advData.uuids16[m_advData.num_uuids16],
|
||||
&it.getNative()->u16, sizeof(ble_uuid16_t));
|
||||
m_advData.uuids16_is_complete = 1;
|
||||
m_advData.num_uuids16++;
|
||||
}
|
||||
@ -381,16 +490,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc(m_advData.uuids32,
|
||||
if(nullptr == (m_advData.uuids32 = (ble_uuid32_t*)realloc((void*)m_advData.uuids32,
|
||||
(m_advData.num_uuids32 + 1) * sizeof(ble_uuid32_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids32[m_advData.num_uuids32].value,
|
||||
&it.getNative()->u32.value, 4);
|
||||
|
||||
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
|
||||
memcpy((void*)&m_advData.uuids32[m_advData.num_uuids32],
|
||||
&it.getNative()->u32, sizeof(ble_uuid32_t));
|
||||
m_advData.uuids32_is_complete = 1;
|
||||
m_advData.num_uuids32++;
|
||||
}
|
||||
@ -402,16 +509,14 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
payloadLen += add;
|
||||
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc(m_advData.uuids128,
|
||||
if(nullptr == (m_advData.uuids128 = (ble_uuid128_t*)realloc((void*)m_advData.uuids128,
|
||||
(m_advData.num_uuids128 + 1) * sizeof(ble_uuid128_t))))
|
||||
{
|
||||
NIMBLE_LOGC(LOG_TAG, "Error, no mem");
|
||||
abort();
|
||||
}
|
||||
memcpy(&m_advData.uuids128[m_advData.num_uuids128].value,
|
||||
&it.getNative()->u128.value, 16);
|
||||
|
||||
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
|
||||
memcpy((void*)&m_advData.uuids128[m_advData.num_uuids128],
|
||||
&it.getNative()->u128, sizeof(ble_uuid128_t));
|
||||
m_advData.uuids128_is_complete = 1;
|
||||
m_advData.num_uuids128++;
|
||||
}
|
||||
@ -419,7 +524,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
|
||||
// check if there is room for the name, if not put it in scan data
|
||||
if((payloadLen + (2 + m_advData.name_len)) > BLE_HS_ADV_MAX_SZ) {
|
||||
if(m_scanResp){
|
||||
if(m_scanResp && !m_customScanResponseData){
|
||||
m_scanData.name = m_advData.name;
|
||||
m_scanData.name_len = m_advData.name_len;
|
||||
if(m_scanData.name_len > BLE_HS_ADV_MAX_SZ - 2) {
|
||||
@ -433,7 +538,6 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
m_advData.name_is_complete = 0;
|
||||
} else {
|
||||
if(m_advData.tx_pwr_lvl_is_present) {
|
||||
m_advData.tx_pwr_lvl = 0;
|
||||
m_advData.tx_pwr_lvl_is_present = 0;
|
||||
payloadLen -= (2 + 1);
|
||||
}
|
||||
@ -446,7 +550,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
}
|
||||
|
||||
if(m_scanResp) {
|
||||
if(m_scanResp && !m_customScanResponseData) {
|
||||
rc = ble_gap_adv_rsp_set_fields(&m_scanData);
|
||||
switch(rc) {
|
||||
case 0:
|
||||
@ -489,19 +593,19 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids128 > 0) {
|
||||
free(m_advData.uuids128);
|
||||
free((void*)m_advData.uuids128);
|
||||
m_advData.uuids128 = nullptr;
|
||||
m_advData.num_uuids128 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids32 > 0) {
|
||||
free(m_advData.uuids32);
|
||||
free((void*)m_advData.uuids32);
|
||||
m_advData.uuids32 = nullptr;
|
||||
m_advData.num_uuids32 = 0;
|
||||
}
|
||||
|
||||
if(m_advData.num_uuids16 > 0) {
|
||||
free(m_advData.uuids16);
|
||||
free((void*)m_advData.uuids16);
|
||||
m_advData.uuids16 = nullptr;
|
||||
m_advData.num_uuids16 = 0;
|
||||
}
|
||||
@ -581,7 +685,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
||||
if(m_advCompCB != nullptr) {
|
||||
m_advCompCB(this);
|
||||
}
|
||||
}
|
||||
} // advCompleteCB
|
||||
|
||||
|
||||
/**
|
||||
@ -590,7 +694,7 @@ void NimBLEAdvertising::advCompleteCB() {
|
||||
*/
|
||||
bool NimBLEAdvertising::isAdvertising() {
|
||||
return ble_gap_adv_active();
|
||||
}
|
||||
} // isAdvertising
|
||||
|
||||
|
||||
/*
|
||||
@ -608,7 +712,7 @@ void NimBLEAdvertising::onHostSync() {
|
||||
// Otherwise we should tell the app that advertising stopped.
|
||||
advCompleteCB();
|
||||
}
|
||||
}
|
||||
} // onHostSync
|
||||
|
||||
|
||||
/**
|
||||
@ -646,6 +750,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceded");
|
||||
return;
|
||||
}
|
||||
m_payload.append(data);
|
||||
@ -657,11 +762,8 @@ void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||
* @param [in] data The data to be added to the payload.
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(char * data, size_t length){
|
||||
if ((m_payload.length() + length) > BLE_HS_ADV_MAX_SZ) {
|
||||
return;
|
||||
}
|
||||
m_payload.append(data,length);
|
||||
void NimBLEAdvertisementData::addData(char * data, size_t length) {
|
||||
addData(std::string(data, length));
|
||||
} // addData
|
||||
|
||||
|
||||
@ -680,43 +782,6 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
||||
} // setAppearance
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete services to advertise.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS16; // 0x03
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS32; // 0x05
|
||||
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4));
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_UUIDS128; // 0x07
|
||||
addData(std::string(cdata, 2) + std::string((char*) uuid.getNative()->u128.value, 16));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisement flags.
|
||||
* @param [in] flag The flags to be set in the advertisement.
|
||||
@ -738,64 +803,141 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) {
|
||||
* @param [in] data The manufacturer data to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
||||
char cdata[2];
|
||||
cdata[0] = data.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||
addData(std::string(cdata, 2) + data);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setManufacturerData");
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the URI to advertise.
|
||||
* @param [in] uri The uri to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setURI(const std::string &uri) {
|
||||
char cdata[2];
|
||||
cdata[0] = uri.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_URI;
|
||||
addData(std::string(cdata, 2) + uri);
|
||||
} // setURI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete name of this device.
|
||||
* @param [in] name The name to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setName");
|
||||
} // setName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial services to advertise.
|
||||
* @param [in] uuid The single service to advertise.
|
||||
* @brief Set a single service to advertise as a complete list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||
setServices(true, uuid.bitSize(), {uuid});
|
||||
} // setCompleteServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 16 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 16, v_uuid);
|
||||
} // setCompleteServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the complete list of 32 bit services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(true, 32, v_uuid);
|
||||
} // setCompleteServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set a single service to advertise as a partial list of services.
|
||||
* @param [in] uuid The service to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
|
||||
setServices(false, uuid.bitSize(), {uuid});
|
||||
} // setPartialServices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 16, v_uuid);
|
||||
} // setPartialServices16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the partial list of services to advertise.
|
||||
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||
setServices(false, 32, v_uuid);
|
||||
} // setPartialServices32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Utility function to create the list of service UUID's from a vector.
|
||||
* @param [in] complete If true the vector is the complete set of services.
|
||||
* @param [in] size The bit size of the UUID's in the vector. (16, 32, or 128).
|
||||
* @param [in] v_uuid The vector of service UUID's to advertise.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid)
|
||||
{
|
||||
char cdata[2];
|
||||
switch (uuid.bitSize()) {
|
||||
case 16: {
|
||||
// [Len] [0x02] [LL] [HH]
|
||||
cdata[0] = 3;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS16; // 0x02
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u16.value, 2));
|
||||
cdata[0] = (size / 8) * v_uuid.size() + 1;
|
||||
switch(size) {
|
||||
case 16:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
// [Len] [0x04] [LL] [LL] [HH] [HH]
|
||||
cdata[0] = 5;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS32; // 0x04
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u32.value, 4));
|
||||
case 32:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
|
||||
break;
|
||||
}
|
||||
|
||||
case 128: {
|
||||
// [Len] [0x04] [0] [1] ... [15]
|
||||
cdata[0] = 17;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_UUIDS128; // 0x06
|
||||
addData(std::string(cdata, 2) + std::string((char *) &uuid.getNative()->u128.value, 16));
|
||||
case 128:
|
||||
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} // setPartialServices
|
||||
|
||||
std::string uuids;
|
||||
|
||||
for(auto &it : v_uuid){
|
||||
if(it.bitSize() != size) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||
return;
|
||||
} else {
|
||||
switch(size) {
|
||||
case 16:
|
||||
uuids += std::string((char*)&it.getNative()->u16.value, 2);
|
||||
break;
|
||||
case 32:
|
||||
uuids += std::string((char*)&it.getNative()->u32.value, 4);
|
||||
break;
|
||||
case 128:
|
||||
uuids += std::string((char*)&it.getNative()->u128.value, 16);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addData(std::string(cdata, 2) + uuids);
|
||||
} // setServices
|
||||
|
||||
|
||||
/**
|
||||
@ -841,15 +983,42 @@ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::
|
||||
* @param [in] name The short name of the device.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
||||
char cdata[2];
|
||||
cdata[0] = name.length() + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||
addData(std::string(cdata, 2) + name);
|
||||
NIMBLE_LOGD("NimBLEAdvertisementData", "<< setShortName");
|
||||
} // setShortName
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds Tx power level to the advertisement data.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addTxPower() {
|
||||
char cdata[3];
|
||||
cdata[0] = BLE_HS_ADV_TX_PWR_LVL_LEN + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_TX_PWR_LVL;
|
||||
cdata[2] = NimBLEDevice::getPower();
|
||||
addData(cdata, 3);
|
||||
} // addTxPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the preferred connection interval parameters.
|
||||
* @param [in] min The minimum interval desired.
|
||||
* @param [in] max The maximum interval desired.
|
||||
*/
|
||||
void NimBLEAdvertisementData::setPreferredParams(uint16_t min, uint16_t max) {
|
||||
char cdata[6];
|
||||
cdata[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
|
||||
cdata[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
|
||||
cdata[2] = min;
|
||||
cdata[3] = min >> 8;
|
||||
cdata[4] = max;
|
||||
cdata[5] = max >> 8;
|
||||
addData(cdata, 6);
|
||||
} // setPreferredParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the payload that is to be advertised.
|
||||
* @return The payload that is to be advertised.
|
||||
|
@ -50,18 +50,27 @@ class NimBLEAdvertisementData {
|
||||
public:
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setCompleteServices(const NimBLEUUID &uuid);
|
||||
void setCompleteServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setFlags(uint8_t);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setURI(const std::string &uri);
|
||||
void setName(const std::string &name);
|
||||
void setPartialServices(const NimBLEUUID &uuid);
|
||||
void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setPartialServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setShortName(const std::string &name);
|
||||
void addData(const std::string &data); // Add data to the payload.
|
||||
void addData(char * data, size_t length);
|
||||
void addTxPower();
|
||||
void setPreferredParams(uint16_t min, uint16_t max);
|
||||
std::string getPayload(); // Retrieve the current advert payload.
|
||||
|
||||
private:
|
||||
friend class NimBLEAdvertising;
|
||||
void setServices(const bool complete, const uint8_t size,
|
||||
const std::vector<NimBLEUUID> &v_uuid);
|
||||
std::string m_payload; // The payload of the advertisement.
|
||||
}; // NimBLEAdvertisementData
|
||||
|
||||
@ -80,6 +89,10 @@ public:
|
||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||
void stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setName(const std::string &name);
|
||||
void setManufacturerData(const std::string &data);
|
||||
void setURI(const std::string &uri);
|
||||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setAdvertisementType(uint8_t adv_type);
|
||||
void setMaxInterval(uint16_t maxinterval);
|
||||
void setMinInterval(uint16_t mininterval);
|
||||
@ -89,6 +102,8 @@ public:
|
||||
void setScanResponse(bool);
|
||||
void setMinPreferred(uint16_t);
|
||||
void setMaxPreferred(uint16_t);
|
||||
void addTxPower();
|
||||
void reset();
|
||||
void advCompleteCB();
|
||||
bool isAdvertising();
|
||||
|
||||
@ -109,6 +124,12 @@ private:
|
||||
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
||||
uint8_t m_slaveItvl[4];
|
||||
uint32_t m_duration;
|
||||
std::vector<uint8_t> m_svcData16;
|
||||
std::vector<uint8_t> m_svcData32;
|
||||
std::vector<uint8_t> m_svcData128;
|
||||
std::vector<uint8_t> m_name;
|
||||
std::vector<uint8_t> m_mfgData;
|
||||
std::vector<uint8_t> m_uri;
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef MAIN_NIMBLEBEACON_H_
|
||||
#define MAIN_NIMBLEBEACON_H_
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
/**
|
||||
* @brief Representation of a beacon.
|
||||
@ -48,4 +49,5 @@ public:
|
||||
void setSignalPower(int8_t signalPower);
|
||||
}; // NimBLEBeacon
|
||||
|
||||
#endif
|
||||
#endif /* MAIN_NIMBLEBEACON_H_ */
|
||||
|
@ -52,7 +52,6 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop
|
||||
m_pService = pService;
|
||||
m_value = "";
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
m_pTaskData = nullptr;
|
||||
m_timestamp = 0;
|
||||
} // NimBLECharacteristic
|
||||
|
||||
@ -95,15 +94,26 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
addDescriptor(pDescriptor);
|
||||
|
||||
return pDescriptor;
|
||||
} // createCharacteristic
|
||||
} // createDescriptor
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @brief Add a descriptor to the characteristic.
|
||||
* @param [in] A pointer to the descriptor to add.
|
||||
*/
|
||||
void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
|
||||
pDescriptor->setCharacteristic(this);
|
||||
m_dscVec.push_back(pDescriptor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID.
|
||||
* @param [in] uuid The UUID of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||
return getDescriptorByUUID(NimBLEUUID(uuid));
|
||||
@ -111,9 +121,9 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @brief Return the BLE Descriptor for the given UUID.
|
||||
* @param [in] uuid The UUID of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
||||
for (auto &it : m_dscVec) {
|
||||
@ -124,6 +134,20 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uu
|
||||
return nullptr;
|
||||
} // getDescriptorByUUID
|
||||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given handle.
|
||||
* @param [in] handle The handle of the descriptor.
|
||||
* @return A pointer to the descriptor object or nullptr if not found.
|
||||
*/
|
||||
NimBLEDescriptor *NimBLECharacteristic::getDescriptorByHandle(uint16_t handle) {
|
||||
for (auto &it : m_dscVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the handle of the characteristic.
|
||||
@ -151,6 +175,11 @@ NimBLEService* NimBLECharacteristic::getService() {
|
||||
} // getService
|
||||
|
||||
|
||||
void NimBLECharacteristic::setService(NimBLEService *pService) {
|
||||
m_pService = pService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID of the characteristic.
|
||||
* @return The UUID of the characteristic.
|
||||
@ -287,16 +316,13 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||
subVal |= NIMBLE_SUB_INDICATE;
|
||||
}
|
||||
|
||||
if(m_pTaskData != nullptr) {
|
||||
m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 :
|
||||
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
||||
xTaskNotifyGive(m_pTaskData->task);
|
||||
}
|
||||
|
||||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||
event->subscribe.conn_handle, subVal);
|
||||
event->subscribe.conn_handle, subVal);
|
||||
|
||||
if(!event->subscribe.cur_indicate && event->subscribe.prev_indicate) {
|
||||
NimBLEDevice::getServer()->clearIndicateWait(event->subscribe.conn_handle);
|
||||
}
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
|
||||
auto it = m_subscribedVec.begin();
|
||||
for(;it != m_subscribedVec.end(); ++it) {
|
||||
@ -308,16 +334,14 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||
if(subVal > 0) {
|
||||
if(it == m_subscribedVec.end()) {
|
||||
m_subscribedVec.push_back({event->subscribe.conn_handle, subVal});
|
||||
return;
|
||||
} else {
|
||||
(*it).second = subVal;
|
||||
}
|
||||
|
||||
(*it).second = subVal;
|
||||
|
||||
} else if(it != m_subscribedVec.end()) {
|
||||
m_subscribedVec.erase(it);
|
||||
m_subscribedVec.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
}
|
||||
|
||||
|
||||
@ -402,40 +426,20 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
||||
// We also must create it in each loop iteration because it is consumed with each host call.
|
||||
os_mbuf *om = ble_hs_mbuf_from_flat((uint8_t*)value.data(), length);
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
||||
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "prior Indication in progress");
|
||||
os_mbuf_free_chain(om);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ble_gattc_indicate_custom(it.first, m_handle, om);
|
||||
if(rc != 0){
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
} else {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
rc = m_pTaskData->rc;
|
||||
}
|
||||
|
||||
m_pTaskData = nullptr;
|
||||
|
||||
if(rc == BLE_HS_EDONE) {
|
||||
rc = 0;
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
NimBLEDevice::getServer()->clearIndicateWait(it.first);
|
||||
}
|
||||
} else {
|
||||
rc = ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
if(rc == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
}
|
||||
|
||||
m_pCallbacks->onStatus(this, statusRC, rc);
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify");
|
||||
@ -455,6 +459,13 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
/**
|
||||
* @brief Get the callback handlers for this characteristic.
|
||||
*/
|
||||
NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() {
|
||||
return m_pCallbacks;
|
||||
} //getCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the characteristic.
|
||||
@ -462,7 +473,7 @@ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallback
|
||||
* @param [in] length The length of the data in bytes.
|
||||
*/
|
||||
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && !defined(DONT_USE_ARDUINO_BULLSHIT) && CORE_DEBUG_LEVEL >= 4)
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
||||
free(pHex);
|
||||
|
@ -59,6 +59,31 @@ class NimBLECharacteristicCallbacks;
|
||||
*/
|
||||
class NimBLECharacteristic {
|
||||
public:
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
NimBLECharacteristicCallbacks*
|
||||
getCallbacks();
|
||||
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
size_t getSubscribedCount();
|
||||
|
||||
NimBLEDescriptor* createDescriptor(const char* uuid,
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
@ -70,11 +95,13 @@ public:
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
uint16_t max_len = 100);
|
||||
|
||||
void addDescriptor(NimBLEDescriptor *pDescriptor);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
|
||||
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEUUID getUUID();
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
|
||||
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
size_t getDataLength();
|
||||
/**
|
||||
* @brief A template to convert the characteristic data to <type\>.
|
||||
* @tparam T The type to convert the data to.
|
||||
@ -92,46 +119,26 @@ public:
|
||||
return *((T *)pData);
|
||||
}
|
||||
|
||||
size_t getDataLength();
|
||||
void indicate();
|
||||
void notify(bool is_notification = true);
|
||||
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the characteristic value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
}
|
||||
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
size_t getSubscribedCount();
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
|
||||
private:
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEService;
|
||||
|
||||
NimBLECharacteristic(const char* uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
NimBLECharacteristic(const NimBLEUUID &uuid,
|
||||
uint16_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE,
|
||||
NimBLEService* pService = nullptr);
|
||||
|
||||
~NimBLECharacteristic();
|
||||
|
||||
NimBLEService* getService();
|
||||
uint16_t getProperties();
|
||||
void setService(NimBLEService *pService);
|
||||
void setSubscribe(struct ble_gap_event *event);
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
@ -143,7 +150,6 @@ private:
|
||||
NimBLEService* m_pService;
|
||||
std::string m_value;
|
||||
std::vector<NimBLEDescriptor*> m_dscVec;
|
||||
ble_task_data_t *m_pTaskData;
|
||||
portMUX_TYPE m_valMux;
|
||||
time_t m_timestamp;
|
||||
|
||||
|
@ -436,6 +436,24 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
} // updateConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get detailed information about the current peer connection.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEClient::getConnInfo() {
|
||||
NimBLEConnInfo connInfo;
|
||||
if (!isConnected()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Not connected");
|
||||
} else {
|
||||
int rc = ble_gap_conn_find(m_conn_id, &connInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Connection info not found");
|
||||
}
|
||||
}
|
||||
|
||||
return connInfo;
|
||||
} // getConnInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the timeout to wait for connection attempt to complete.
|
||||
* @param [in] time The number of seconds before timeout.
|
||||
@ -1016,7 +1034,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
|
||||
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %lu", event->passkey.params.numcmp);
|
||||
pkey.action = event->passkey.params.action;
|
||||
// Compatibility only - Do not use, should be removed the in future
|
||||
if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "NimBLEAddress.h"
|
||||
#include "NimBLEUUID.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLERemoteService.h"
|
||||
|
||||
@ -71,6 +72,7 @@ public:
|
||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
void discoverAttributes();
|
||||
NimBLEConnInfo getConnInfo();
|
||||
|
||||
private:
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
|
55
src/NimBLEConnInfo.h
Normal file
55
src/NimBLEConnInfo.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef NIMBLECONNINFO_H_
|
||||
#define NIMBLECONNINFO_H_
|
||||
|
||||
#include "NimBLEAddress.h"
|
||||
|
||||
/**
|
||||
* @brief Connection information.
|
||||
*/
|
||||
class NimBLEConnInfo {
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEClient;
|
||||
ble_gap_conn_desc m_desc;
|
||||
NimBLEConnInfo() { m_desc = {}; }
|
||||
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
|
||||
public:
|
||||
/** @brief Gets the over-the-air address of the connected peer */
|
||||
NimBLEAddress getAddress() { return NimBLEAddress(m_desc.peer_ota_addr); }
|
||||
|
||||
/** @brief Gets the ID address of the connected peer */
|
||||
NimBLEAddress getIdAddress() { return NimBLEAddress(m_desc.peer_id_addr); }
|
||||
|
||||
/** @brief Gets the connection handle of the connected peer */
|
||||
uint16_t getConnHandle() { return m_desc.conn_handle; }
|
||||
|
||||
/** @brief Gets the connection interval for this connection (in 1.25ms units) */
|
||||
uint16_t getConnInterval() { return m_desc.conn_itvl; }
|
||||
|
||||
/** @brief Gets the supervision timeout for this connection (in 10ms units) */
|
||||
uint16_t getConnTimeout() { return m_desc.supervision_timeout; }
|
||||
|
||||
/** @brief Gets the allowable latency for this connection (unit = number of intervals) */
|
||||
uint16_t getConnLatency() { return m_desc.conn_latency; }
|
||||
|
||||
/** @brief Gets the maximum transmission unit size for this connection (in bytes) */
|
||||
uint16_t getMTU() { return ble_att_mtu(m_desc.conn_handle); }
|
||||
|
||||
/** @brief Check if we are in the master role in this connection */
|
||||
bool isMaster() { return (m_desc.role == BLE_GAP_ROLE_MASTER); }
|
||||
|
||||
/** @brief Check if we are in the slave role in this connection */
|
||||
bool isSlave() { return (m_desc.role == BLE_GAP_ROLE_SLAVE); }
|
||||
|
||||
/** @brief Check if we are connected to a bonded peer */
|
||||
bool isBonded() { return (m_desc.sec_state.bonded == 1); }
|
||||
|
||||
/** @brief Check if the connection in encrypted */
|
||||
bool isEncrypted() { return (m_desc.sec_state.encrypted == 1); }
|
||||
|
||||
/** @brief Check if the the connection has been authenticated */
|
||||
bool isAuthenticated() { return (m_desc.sec_state.authenticated == 1); }
|
||||
|
||||
/** @brief Gets the key size used to encrypt the connection */
|
||||
uint8_t getSecKeySize() { return m_desc.sec_state.key_size; }
|
||||
};
|
||||
#endif
|
@ -37,6 +37,7 @@ NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16
|
||||
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief NimBLEDescriptor constructor.
|
||||
*/
|
||||
@ -47,7 +48,7 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
|
||||
m_value.attr_len = 0; // Initial length is 0.
|
||||
m_value.attr_max_len = max_len; // Maximum length of the data.
|
||||
m_handle = NULL_HANDLE; // Handle is initially unknown.
|
||||
m_pCharacteristic = nullptr; // No initial characteristic.
|
||||
m_pCharacteristic = pCharacteristic;
|
||||
m_pCallbacks = &defaultCallbacks; // No initial callback.
|
||||
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
|
||||
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
@ -123,10 +124,26 @@ uint8_t* NimBLEDescriptor::getValue() {
|
||||
} // getValue
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the value of this descriptor as a string.
|
||||
* @return A std::string instance containing a copy of the descriptor's value.
|
||||
*/
|
||||
std::string NimBLEDescriptor::getStringValue() {
|
||||
return std::string((char *) m_value.attr_value, m_value.attr_len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the characteristic this descriptor belongs to.
|
||||
* @return A pointer to the characteristic this descriptor belongs to.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() {
|
||||
return m_pCharacteristic;
|
||||
} // getCharacteristic
|
||||
|
||||
|
||||
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg) {
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
|
||||
@ -163,7 +180,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
if((len + next->om_len) > pDescriptor->m_value.attr_max_len) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
memcpy(&buf[len-1], next->om_data, next->om_len);
|
||||
memcpy(&buf[len], next->om_data, next->om_len);
|
||||
len += next->om_len;
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
@ -231,6 +248,14 @@ void NimBLEDescriptor::setValue(const std::string &value) {
|
||||
setValue((uint8_t*) value.data(), value.length());
|
||||
} // setValue
|
||||
|
||||
/**
|
||||
* @brief Set the characteristic this descriptor belongs to.
|
||||
* @param [in] pChar A pointer to the characteristic this descriptior belongs to.
|
||||
*/
|
||||
void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
|
||||
m_pCharacteristic = pChar;
|
||||
} // setCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the descriptor.
|
||||
|
@ -43,14 +43,29 @@ class NimBLEDescriptorCallbacks;
|
||||
*/
|
||||
class NimBLEDescriptor {
|
||||
public:
|
||||
uint16_t getHandle();
|
||||
size_t getLength();
|
||||
NimBLEUUID getUUID();
|
||||
uint8_t* getValue();
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
std::string toString();
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic = nullptr);
|
||||
|
||||
~NimBLEDescriptor();
|
||||
|
||||
uint16_t getHandle();
|
||||
NimBLEUUID getUUID();
|
||||
std::string toString();
|
||||
|
||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
|
||||
|
||||
size_t getLength();
|
||||
uint8_t* getValue();
|
||||
std::string getStringValue();
|
||||
|
||||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
NimBLECharacteristic* getCharacteristic();
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||
@ -64,22 +79,12 @@ public:
|
||||
private:
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEService;
|
||||
friend class NimBLE2902;
|
||||
friend class NimBLE2904;
|
||||
|
||||
NimBLEDescriptor(const char* uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties,
|
||||
uint16_t max_len,
|
||||
NimBLECharacteristic* pCharacteristic);
|
||||
|
||||
~NimBLEDescriptor();
|
||||
|
||||
static int handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
void setHandle(uint16_t handle);
|
||||
void setCharacteristic(NimBLECharacteristic* pChar);
|
||||
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_handle;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#include "NimBLEDevice.h"
|
||||
@ -30,7 +30,7 @@
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#include "esp32-hal-bt.h"
|
||||
#endif
|
||||
|
||||
@ -60,8 +60,11 @@ ble_gap_event_listener NimBLEDevice::m_listener;
|
||||
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||
#endif
|
||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||
std::vector<NimBLEAddress> NimBLEDevice::m_whiteList;
|
||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
|
||||
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
|
||||
uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE;
|
||||
|
||||
|
||||
/**
|
||||
@ -303,7 +306,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the transmission power.
|
||||
* @brief Get the transmission power.
|
||||
* @param [in] powerType The power level to set, can be one of:
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, For connection handle 0
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
||||
@ -342,7 +345,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||
default:
|
||||
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
|
||||
}
|
||||
} // setPower
|
||||
} // getPower
|
||||
|
||||
|
||||
/**
|
||||
@ -400,6 +403,258 @@ void NimBLEDevice::stopAdvertising() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the duplicate filter cache size for filtering scanned devices.
|
||||
* @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n
|
||||
* Range is 10-1000, a larger value will reduce how often the same devices are reported.
|
||||
* @details Must only be called before calling NimBLEDevice::init.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::setScanDuplicateCacheSize(uint16_t cacheSize) {
|
||||
if(initialized) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot change scan cache size while initialized");
|
||||
return;
|
||||
} else if(cacheSize > 1000 || cacheSize <10) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid scan cache size; min=10 max=1000");
|
||||
return;
|
||||
}
|
||||
|
||||
m_scanDuplicateSize = cacheSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the duplicate filter mode for filtering scanned devices.
|
||||
* @param [in] mode One of three possible options:
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE (0) (default)\n
|
||||
Filter by device address only, advertisements from the same address will be reported only once.
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA (1)\n
|
||||
Filter by data only, advertisements with the same data will only be reported once,\n
|
||||
even from different addresses.
|
||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)\n
|
||||
Filter by address and data, advertisements from the same address will be reported only once,\n
|
||||
except if the data in the advertisement has changed, then it will be reported again.
|
||||
* @details Must only be called before calling NimBLEDevice::init.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
if(initialized) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot change scan duplicate type while initialized");
|
||||
return;
|
||||
} else if(mode > 2) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid scan duplicate type");
|
||||
return;
|
||||
}
|
||||
|
||||
m_scanFilterMode = mode;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
/**
|
||||
* @brief Gets the number of bonded peers stored
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEDevice::getNumBonds() {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc !=0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return num_peers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes all bonding information.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::deleteAllBonds() {
|
||||
ble_store_clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Deletes a peer bond.
|
||||
* @param [in] address The address of the peer with which to delete bond info.
|
||||
* @returns true on success.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::deleteBond(const NimBLEAddress &address) {
|
||||
ble_addr_t delAddr;
|
||||
memcpy(&delAddr.val, address.getNative(),6);
|
||||
delAddr.type = address.getType();
|
||||
|
||||
int rc = ble_gap_unpair(&delAddr);
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is bonded.
|
||||
* @param [in] address The address to check for bonding.
|
||||
* @returns true if bonded.
|
||||
*/
|
||||
/*STATIC*/
|
||||
bool NimBLEDevice::isBonded(const NimBLEAddress &address) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_peers; i++) {
|
||||
NimBLEAddress storedAddr(peer_id_addrs[i]);
|
||||
if(storedAddr == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the address of a bonded peer device by index.
|
||||
* @param [in] index The index to retrieve the peer address of.
|
||||
* @returns NimBLEAddress of the found bonded peer or nullptr if not found.
|
||||
*/
|
||||
/*STATIC*/
|
||||
NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
|
||||
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||
int num_peers, rc;
|
||||
|
||||
rc = ble_store_util_bonded_peers(&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||
if (rc != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (index > num_peers || index < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return NimBLEAddress(peer_id_addrs[index]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Checks if a peer device is whitelisted.
|
||||
* @param [in] address The address to check for in the whitelist.
|
||||
* @returns true if the address is in the whitelist.
|
||||
*/
|
||||
bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) {
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it == address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a peer address to the whitelist.
|
||||
* @param [in] address The address to add to the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
|
||||
if (NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_whiteList.push_back(address);
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a peer address from the whitelist.
|
||||
* @param [in] address The address to remove from the whitelist.
|
||||
* @returns true if successful.
|
||||
*/
|
||||
bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) {
|
||||
if (!NimBLEDevice::onWhiteList(address)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<ble_addr_t> wlVec;
|
||||
wlVec.reserve(m_whiteList.size());
|
||||
|
||||
for (auto &it : m_whiteList) {
|
||||
if (it != address) {
|
||||
ble_addr_t wlAddr;
|
||||
memcpy(&wlAddr.val, it.getNative(), 6);
|
||||
wlAddr.type = it.getType();
|
||||
wlVec.push_back(wlAddr);
|
||||
}
|
||||
}
|
||||
|
||||
int rc = ble_gap_wl_set(&wlVec[0], wlVec.size());
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't remove from the list unless NimBLE returned success
|
||||
for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) {
|
||||
if ((*it) == address) {
|
||||
m_whiteList.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the count of addresses in the whitelist.
|
||||
* @returns The number of addresses in the whitelist.
|
||||
*/
|
||||
size_t NimBLEDevice::getWhiteListCount() {
|
||||
return m_whiteList.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the address at the vector index.
|
||||
* @param [in] index The vector index to retrieve the address from.
|
||||
* @returns the NimBLEAddress at the whitelist index or nullptr if not found.
|
||||
*/
|
||||
NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
|
||||
if (index > m_whiteList.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index);
|
||||
return nullptr;
|
||||
}
|
||||
return m_whiteList[index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||
* @param [in] reason The reason code for the reset.
|
||||
@ -485,7 +740,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||
int rc=0;
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
|
||||
btStarted();
|
||||
#endif
|
||||
@ -499,8 +754,17 @@ void NimBLEDevice::stopAdvertising() {
|
||||
|
||||
ESP_ERROR_CHECK(errRc);
|
||||
|
||||
ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init());
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
bt_cfg.mode = ESP_BT_MODE_BLE;
|
||||
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
|
||||
bt_cfg.normal_adv_size = m_scanDuplicateSize;
|
||||
bt_cfg.scan_duplicate_type = m_scanFilterMode;
|
||||
|
||||
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
|
||||
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
|
||||
ESP_ERROR_CHECK(esp_nimble_hci_init());
|
||||
nimble_port_init();
|
||||
|
||||
// Setup callbacks for host events
|
||||
@ -519,6 +783,8 @@ void NimBLEDevice::stopAdvertising() {
|
||||
|
||||
// Set the device name.
|
||||
rc = ble_svc_gap_device_name_set(deviceName.c_str());
|
||||
if (rc != 0)
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_svc_gap_device_name_set() failed %i name_size=%zd", rc, deviceName.size());
|
||||
assert(rc == 0);
|
||||
|
||||
ble_store_config_init();
|
||||
@ -544,10 +810,12 @@ void NimBLEDevice::stopAdvertising() {
|
||||
if (ret == 0) {
|
||||
nimble_port_deinit();
|
||||
|
||||
#if 0
|
||||
ret = esp_nimble_hci_and_controller_deinit();
|
||||
if (ret != ESP_OK) {
|
||||
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
initialized = false;
|
||||
m_synced = false;
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef MAIN_NIMBLEDEVICE_H_
|
||||
#define MAIN_NIMBLEDEVICE_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
|
||||
@ -95,6 +95,11 @@ public:
|
||||
static bool getInitialized();
|
||||
static NimBLEAddress getAddress();
|
||||
static std::string toString();
|
||||
static bool whiteListAdd(const NimBLEAddress & address);
|
||||
static bool whiteListRemove(const NimBLEAddress & address);
|
||||
static bool onWhiteList(const NimBLEAddress & address);
|
||||
static size_t getWhiteListCount();
|
||||
static NimBLEAddress getWhiteListAddress(size_t index);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
static NimBLEScan* getScan();
|
||||
@ -123,6 +128,8 @@ public:
|
||||
static bool isIgnored(const NimBLEAddress &address);
|
||||
static void addIgnored(const NimBLEAddress &address);
|
||||
static void removeIgnored(const NimBLEAddress &address);
|
||||
static void setScanDuplicateCacheSize(uint16_t cacheSize);
|
||||
static void setScanFilterMode(uint8_t type);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
@ -140,6 +147,14 @@ public:
|
||||
static std::list<NimBLEClient*>* getClientList();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
static bool deleteBond(const NimBLEAddress &address);
|
||||
static int getNumBonds();
|
||||
static bool isBonded(const NimBLEAddress &address);
|
||||
static void deleteAllBonds();
|
||||
static NimBLEAddress getBondedAddress(int index);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
friend class NimBLEClient;
|
||||
@ -184,6 +199,9 @@ private:
|
||||
static ble_gap_event_listener m_listener;
|
||||
static gap_event_handler m_customGapHandler;
|
||||
static uint8_t m_own_addr_type;
|
||||
static uint16_t m_scanDuplicateSize;
|
||||
static uint8_t m_scanFilterMode;
|
||||
static std::vector<NimBLEAddress> m_whiteList;
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: pcbreflux
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEEddystoneTLM.h"
|
||||
#include "NimBLELog.h"
|
||||
@ -124,30 +124,30 @@ std::string NimBLEEddystoneTLM::toString() {
|
||||
out += " C\n";
|
||||
|
||||
out += "Adv. Count ";
|
||||
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
|
||||
snprintf(val, sizeof(val), "%lu", ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
out += "Time in seconds ";
|
||||
snprintf(val, sizeof(val), "%d", rawsec/10);
|
||||
snprintf(val, sizeof(val), "%lu", rawsec/10);
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
out += "Time ";
|
||||
|
||||
snprintf(val, sizeof(val), "%04d", rawsec / 864000);
|
||||
snprintf(val, sizeof(val), "%04lu", rawsec / 864000);
|
||||
out += val;
|
||||
out += ".";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 36000) % 24);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 600) % 60);
|
||||
out += val;
|
||||
out += ":";
|
||||
|
||||
snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60);
|
||||
snprintf(val, sizeof(val), "%02lu", (rawsec / 10) % 60);
|
||||
out += val;
|
||||
out += "\n";
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#ifndef _NimBLEEddystoneTLM_H_
|
||||
#define _NimBLEEddystoneTLM_H_
|
||||
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
|
||||
#include <string>
|
||||
@ -57,4 +59,5 @@ private:
|
||||
|
||||
}; // NimBLEEddystoneTLM
|
||||
|
||||
#endif
|
||||
#endif /* _NimBLEEddystoneTLM_H_ */
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: pcbreflux
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEEddystoneURL.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#ifndef _NIMBLEEddystoneURL_H_
|
||||
#define _NIMBLEEddystoneURL_H_
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
#include "NimBLEUUID.h"
|
||||
|
||||
#include <string>
|
||||
@ -49,4 +50,5 @@ private:
|
||||
|
||||
}; // NIMBLEEddystoneURL
|
||||
|
||||
#endif
|
||||
#endif /* _NIMBLEEddystoneURL_H_ */
|
||||
|
@ -103,7 +103,7 @@ void NimBLEHIDDevice::manufacturer(std::string name) {
|
||||
/**
|
||||
* @brief Sets the Plug n Play characterisc value.
|
||||
* @param [in] sig The vendor ID source number.
|
||||
* @param [in[ vid The vendor ID number.
|
||||
* @param [in] vid The vendor ID number.
|
||||
* @param [in] pid The product ID number.
|
||||
* @param [in] version The produce version number.
|
||||
*/
|
||||
@ -128,8 +128,8 @@ void NimBLEHIDDevice::hidInfo(uint8_t country, uint8_t flags) {
|
||||
* @return pointer to new input report characteristic
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLECharacteristic* inputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
|
||||
NimBLEDescriptor* inputReportDescriptor = inputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x01 };
|
||||
inputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
@ -144,7 +144,7 @@ NimBLECharacteristic* NimBLEHIDDevice::inputReport(uint8_t reportID) {
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* outputReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
NimBLEDescriptor* outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLEDescriptor* outputReportDescriptor = outputReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x02 };
|
||||
outputReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
@ -159,7 +159,7 @@ NimBLECharacteristic* NimBLEHIDDevice::outputReport(uint8_t reportID) {
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEHIDDevice::featureReport(uint8_t reportID) {
|
||||
NimBLECharacteristic* featureReportCharacteristic = m_hidService->createCharacteristic((uint16_t) 0x2a4d, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
NimBLEDescriptor* featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t) 0x2908);
|
||||
NimBLEDescriptor* featureReportDescriptor = featureReportCharacteristic->createDescriptor((uint16_t) 0x2908, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
|
||||
|
||||
uint8_t desc1_val[] = { reportID, 0x03 };
|
||||
featureReportDescriptor->setValue((uint8_t*) desc1_val, 2);
|
||||
|
@ -7,17 +7,17 @@
|
||||
*/
|
||||
#ifndef MAIN_NIMBLELOG_H_
|
||||
#define MAIN_NIMBLELOG_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(DONT_USE_ARDUINO_BULLSHIT)
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "modlog/modlog.h"
|
||||
|
||||
|
||||
// If Arduino is being used, strip out the colors and ignore log printing below ui setting.
|
||||
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR
|
||||
// otherwise no messages will be printed above that level.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#ifndef CORE_DEBUG_LEVEL
|
||||
#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
|
||||
#endif
|
||||
@ -49,12 +49,15 @@
|
||||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "\033[0;31mE %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(WARN, "\033[0;33mW %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(INFO, "\033[0;32mI %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(DEBUG, "D %s: "#format"\n",tag,##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "\033[1;31mCRIT %s: "#format"\033[0m\n",tag,##__VA_ARGS__)
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#define NIMBLE_LOGE(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGW(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGI(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__)
|
||||
#define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
|
||||
|
||||
#endif /*ARDUINO_ARCH_ESP32*/
|
||||
|
||||
#endif /*CONFIG_BT_ENABLED*/
|
||||
#endif /*MAIN_NIMBLELOG_H_*/
|
||||
#endif /*MAIN_NIMBLELOG_H_*/
|
||||
|
@ -55,6 +55,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||
|
||||
m_handle = chr->val_handle;
|
||||
m_defHandle = chr->def_handle;
|
||||
m_endHandle = 0;
|
||||
m_charProp = chr->properties;
|
||||
m_pRemoteService = pRemoteService;
|
||||
m_notifyCallback = nullptr;
|
||||
@ -146,31 +147,25 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_dsc *dsc,
|
||||
void *arg)
|
||||
{
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Descriptor Discovered >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? dsc->handle : -1);
|
||||
|
||||
desc_filter_t *filter = (desc_filter_t*)arg;
|
||||
const NimBLEUUID *uuid_filter = filter->uuid;
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)filter->task_data;
|
||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
int rc=0;
|
||||
|
||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
if (characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (error->status) {
|
||||
switch (rc) {
|
||||
case 0: {
|
||||
if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion");
|
||||
rc = BLE_HS_EDONE;
|
||||
break;
|
||||
}
|
||||
if(uuid_filter != nullptr) {
|
||||
if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
if (uuid_filter != nullptr) {
|
||||
if (ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||
return 0;
|
||||
} else {
|
||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Found");
|
||||
rc = BLE_HS_EDONE;
|
||||
}
|
||||
}
|
||||
@ -180,11 +175,10 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = error->status;
|
||||
break;
|
||||
}
|
||||
|
||||
/** If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
/* If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
||||
* If we get any other error code tell the application to abort by returning non-zero in the rc.
|
||||
*/
|
||||
@ -202,6 +196,38 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief callback from NimBLE when the next characteristic of the service is discovered.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::nextCharCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg)
|
||||
{
|
||||
int rc = error->status;
|
||||
NIMBLE_LOGD(LOG_TAG, "Next Characteristic >> status: %d handle: %d",
|
||||
rc, (rc == 0) ? chr->val_handle : -1);
|
||||
|
||||
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||
NimBLERemoteCharacteristic *pChar = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||
|
||||
if (pChar->getRemoteService()->getClient()->getConnId() != conn_handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
pChar->m_endHandle = chr->def_handle - 1;
|
||||
rc = BLE_HS_EDONE;
|
||||
} else if (rc == BLE_HS_EDONE) {
|
||||
pChar->m_endHandle = pChar->getRemoteService()->getEndHandle();
|
||||
} else {
|
||||
pTaskData->rc = rc;
|
||||
}
|
||||
|
||||
xTaskNotifyGive(pTaskData->task);
|
||||
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.
|
||||
@ -209,35 +235,57 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||
|
||||
uint16_t endHandle = getRemoteService()->getEndHandle(this);
|
||||
if(m_handle >= endHandle) {
|
||||
return false;
|
||||
// If this is the last handle then there are no descriptors
|
||||
if (m_handle == getRemoteService()->getEndHandle()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
|
||||
// If we don't know the end handle of this characteristic retrieve the next one in the service
|
||||
// The end handle is the next characteristic definition handle -1.
|
||||
if (m_endHandle == 0) {
|
||||
rc = ble_gattc_disc_all_chrs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
getRemoteService()->getEndHandle(),
|
||||
NimBLERemoteCharacteristic::nextCharCB,
|
||||
&taskData);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error getting end handle rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Could not retrieve end handle rc=%d", taskData.rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc_filter_t filter = {uuid_filter, &taskData};
|
||||
|
||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||
m_handle,
|
||||
endHandle,
|
||||
m_endHandle,
|
||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||
&filter);
|
||||
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_dscs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: startHandle:%d endHandle:%d taskData.rc=%d %s", m_handle, endHandle, taskData.rc, NimBLEUtils::returnCodeToString(0x0100+taskData.rc));
|
||||
return false;
|
||||
if (taskData.rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to retrieve descriptors; startHandle:%d endHandle:%d taskData.rc=%d",
|
||||
m_handle, m_endHandle, taskData.rc);
|
||||
}
|
||||
|
||||
return true;
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size());
|
||||
return (taskData.rc == 0);
|
||||
} // retrieveDescriptors
|
||||
|
||||
|
||||
@ -664,7 +712,7 @@ std::string NimBLERemoteCharacteristic::toString() {
|
||||
* @return false if not connected or cant perform write for some reason.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
||||
return writeValue((uint8_t*)newValue.c_str(), newValue.length(), response);
|
||||
} // writeValue
|
||||
|
||||
|
||||
|
@ -148,12 +148,15 @@ private:
|
||||
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
static int nextCharCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg);
|
||||
|
||||
// Private properties
|
||||
NimBLEUUID m_uuid;
|
||||
uint8_t m_charProp;
|
||||
uint16_t m_handle;
|
||||
uint16_t m_defHandle;
|
||||
uint16_t m_endHandle;
|
||||
NimBLERemoteService* m_pRemoteService;
|
||||
std::string m_value;
|
||||
notify_callback m_notifyCallback;
|
||||
|
@ -223,6 +223,20 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
if(taskData.rc == 0){
|
||||
if (uuid_filter == nullptr) {
|
||||
if (m_characteristicVector.size() > 1) {
|
||||
for (auto it = m_characteristicVector.begin(); it != m_characteristicVector.end(); ++it ) {
|
||||
auto nx = std::next(it, 1);
|
||||
if (nx == m_characteristicVector.end()) {
|
||||
break;
|
||||
}
|
||||
(*it)->m_endHandle = (*nx)->m_defHandle - 1;
|
||||
}
|
||||
}
|
||||
|
||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||
return true;
|
||||
}
|
||||
@ -249,23 +263,6 @@ uint16_t NimBLERemoteService::getEndHandle() {
|
||||
return m_endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
/**
|
||||
* @brief Get the end handle of specified NimBLERemoteCharacteristic.
|
||||
*/
|
||||
|
||||
uint16_t NimBLERemoteService::getEndHandle(NimBLERemoteCharacteristic *pCharacteristic) {
|
||||
uint16_t endHandle = m_endHandle;
|
||||
|
||||
for(auto &it: m_characteristicVector) {
|
||||
uint16_t defHandle = it->getDefHandle() - 1;
|
||||
if(defHandle > pCharacteristic->getDefHandle() && endHandle > defHandle) {
|
||||
endHandle = defHandle;
|
||||
}
|
||||
}
|
||||
|
||||
return endHandle;
|
||||
} // getEndHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service start handle.
|
||||
|
@ -70,7 +70,6 @@ private:
|
||||
|
||||
uint16_t getStartHandle();
|
||||
uint16_t getEndHandle();
|
||||
uint16_t getEndHandle(NimBLERemoteCharacteristic *pCharacteristic);
|
||||
void releaseSemaphores();
|
||||
|
||||
// Properties
|
||||
|
@ -38,9 +38,9 @@ NimBLEScan::NimBLEScan() {
|
||||
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||
m_ignoreResults = false;
|
||||
m_wantDuplicates = false;
|
||||
m_pTaskData = nullptr;
|
||||
m_duration = BLE_HS_FOREVER; // make sure this is non-zero in the event of a host reset
|
||||
m_maxResults = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ NimBLEScan::~NimBLEScan() {
|
||||
|
||||
case BLE_GAP_EVENT_DISC: {
|
||||
if(pScan->m_ignoreResults) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -88,34 +88,49 @@ NimBLEScan::~NimBLEScan() {
|
||||
|
||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||
// Otherwise just update the relevant parameters of the already known device.
|
||||
if(advertisedDevice == nullptr){
|
||||
if(advertisedDevice == nullptr && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
|
||||
// Check if we have reach the scan results limit, ignore this one if so.
|
||||
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
||||
if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
advertisedDevice->setAddress(advertisedAddress);
|
||||
advertisedDevice->setAdvType(event->disc.event_type);
|
||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
else{
|
||||
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
if(event->disc.length_data > 0) {
|
||||
advertisedDevice->parseAdvertisement(event->disc.data, event->disc.length_data);
|
||||
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else if(advertisedDevice != nullptr) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||
} else {
|
||||
// Scan response from unknown device
|
||||
return 0;
|
||||
}
|
||||
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
if(pScan->m_wantDuplicates || !advertisedDevice->m_callbackSent) {
|
||||
// If not active scanning report the result to the listener.
|
||||
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
// If not active scanning or scan response is not available
|
||||
// report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive ||
|
||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||
{
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
|
||||
// Otherwise wait for the scan response so we can report all of the data at once.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
// Otherwise, wait for the scan response so we can report the complete data.
|
||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||
advertisedDevice->m_callbackSent = true;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
// If not storing results and we have invoked the callback, delete the device.
|
||||
if(pScan->m_maxResults == 0 && advertisedDevice->m_callbackSent) {
|
||||
pScan->erase(advertisedAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +138,21 @@ NimBLEScan::~NimBLEScan() {
|
||||
}
|
||||
case BLE_GAP_EVENT_DISC_COMPLETE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
|
||||
event->disc_complete.reason);
|
||||
event->disc_complete.reason);
|
||||
|
||||
// If a device advertised with scan reponse available and it was not received
|
||||
// the callback would not have been invoked, so do it here.
|
||||
if(pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||
if(!it->m_callbackSent) {
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pScan->m_maxResults == 0) {
|
||||
pScan->clearResults();
|
||||
}
|
||||
|
||||
if (pScan->m_scanCompleteCB != nullptr) {
|
||||
pScan->m_scanCompleteCB(pScan->m_scanResults);
|
||||
@ -145,15 +174,11 @@ NimBLEScan::~NimBLEScan() {
|
||||
|
||||
/**
|
||||
* @brief Should we perform an active or passive scan?
|
||||
* The default is a passive scan. An active scan means that we will wish a scan response.
|
||||
* The default is a passive scan. An active scan means that we will request a scan response.
|
||||
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
||||
*/
|
||||
void NimBLEScan::setActiveScan(bool active) {
|
||||
if (active) {
|
||||
m_scan_params.passive = 0;
|
||||
} else {
|
||||
m_scan_params.passive = 1;
|
||||
}
|
||||
m_scan_params.passive = !active;
|
||||
} // setActiveScan
|
||||
|
||||
|
||||
@ -202,6 +227,16 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
||||
} // setFilterPolicy
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the max number of results to store.
|
||||
* @param [in] maxResults The number of results to limit storage to\n
|
||||
* 0 == none (callbacks only) 0xFF == unlimited, any other value is the limit.
|
||||
*/
|
||||
void NimBLEScan::setMaxResults(uint8_t maxResults) {
|
||||
m_maxResults = maxResults;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the call backs to be invoked.
|
||||
* @param [in] pAdvertisedDeviceCallbacks Call backs to be invoked.
|
||||
@ -209,7 +244,7 @@ void NimBLEScan::setFilterPolicy(uint8_t filter) {
|
||||
*/
|
||||
void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks,
|
||||
bool wantDuplicates) {
|
||||
m_wantDuplicates = wantDuplicates;
|
||||
setDuplicateFilter(!wantDuplicates);
|
||||
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
|
||||
} // setAdvertisedDeviceCallbacks
|
||||
|
||||
@ -249,7 +284,7 @@ bool NimBLEScan::isScanning() {
|
||||
* @return True if scan started or false if there was an error.
|
||||
*/
|
||||
bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%lu)", duration);
|
||||
|
||||
// Save the callback to be invoked when the scan completes.
|
||||
m_scanCompleteCB = scanCompleteCB;
|
||||
@ -281,6 +316,8 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
// Clear the cache if already scanning in case an advertiser was missed.
|
||||
clearDuplicateCache();
|
||||
break;
|
||||
|
||||
case BLE_HS_EBUSY:
|
||||
@ -342,10 +379,14 @@ bool NimBLEScan::stop() {
|
||||
|
||||
int rc = ble_gap_disc_cancel();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
|
||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_maxResults == 0) {
|
||||
clearResults();
|
||||
}
|
||||
|
||||
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
|
||||
m_scanCompleteCB(m_scanResults);
|
||||
}
|
||||
@ -359,13 +400,21 @@ bool NimBLEScan::stop() {
|
||||
} // stop
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clears the duplicate scan filter cache.
|
||||
*/
|
||||
void NimBLEScan::clearDuplicateCache() {
|
||||
esp_ble_scan_dupilcate_list_flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Delete peer device from the scan results vector.
|
||||
* @param [in] address The address of the device to delete from the results.
|
||||
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
||||
*/
|
||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
NIMBLE_LOGD(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
|
||||
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||
if((*it)->getAddress() == address) {
|
||||
@ -414,6 +463,7 @@ void NimBLEScan::clearResults() {
|
||||
delete it;
|
||||
}
|
||||
m_scanResults.m_advertisedDevicesVector.clear();
|
||||
clearDuplicateCache();
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,9 +70,11 @@ public:
|
||||
void setDuplicateFilter(bool enabled);
|
||||
void setLimitedOnly(bool enabled);
|
||||
void setFilterPolicy(uint8_t filter);
|
||||
void clearDuplicateCache();
|
||||
bool stop();
|
||||
void clearResults();
|
||||
NimBLEScanResults getResults();
|
||||
void setMaxResults(uint8_t maxResults);
|
||||
void erase(const NimBLEAddress &address);
|
||||
|
||||
|
||||
@ -89,10 +91,10 @@ private:
|
||||
void (*m_scanCompleteCB)(NimBLEScanResults scanResults);
|
||||
ble_gap_disc_params m_scan_params;
|
||||
bool m_ignoreResults;
|
||||
bool m_wantDuplicates;
|
||||
NimBLEScanResults m_scanResults;
|
||||
uint32_t m_duration;
|
||||
ble_task_data_t *m_pTaskData;
|
||||
uint8_t m_maxResults;
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLESECURITY_H_
|
||||
#define COMPONENTS_NIMBLESECURITY_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -37,6 +37,7 @@ static NimBLEServerCallbacks defaultCallbacks;
|
||||
* the NimBLEDevice class.
|
||||
*/
|
||||
NimBLEServer::NimBLEServer() {
|
||||
memset(m_indWait, BLE_HS_CONN_HANDLE_NONE, sizeof(m_indWait));
|
||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
@ -104,28 +105,47 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the service object.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
||||
return getServiceByUUID(NimBLEUUID(uuid));
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid, uint16_t instanceId) {
|
||||
return getServiceByUUID(NimBLEUUID(uuid), instanceId);
|
||||
} // getServiceByUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its UUID
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
* @return A reference to the service object.
|
||||
* @param [in] uuid The UUID of the service.
|
||||
* @param instanceId The index of the service to return (used when multiple services have the same UUID).
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
|
||||
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||
uint16_t position = 0;
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
return it;
|
||||
if (position == instanceId){
|
||||
return it;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
} // getServiceByUUID
|
||||
|
||||
/**
|
||||
* @brief Get a %BLE Service by its handle
|
||||
* @param handle The handle of the service.
|
||||
* @return A pointer to the service object or nullptr if not found.
|
||||
*/
|
||||
NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||
for (auto &it : m_svcVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||
@ -154,7 +174,7 @@ void NimBLEServer::start() {
|
||||
abort();
|
||||
}
|
||||
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && !defined(DONT_USE_ARDUINO_BULLSHIT) && CORE_DEBUG_LEVEL >= 4)
|
||||
ble_gatts_show_local();
|
||||
#endif
|
||||
/*** Future use ***
|
||||
@ -234,6 +254,63 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
} // getConnectedCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the vector of the connected client ID's.
|
||||
*/
|
||||
std::vector<uint16_t> NimBLEServer::getPeerDevices() {
|
||||
return m_connectedPeersVec;
|
||||
} // getPeerDevices
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by vector index.
|
||||
* @param [in] index The vector index of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(size_t index) {
|
||||
if (index >= m_connectedPeersVec.size()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "No peer at index %u", index);
|
||||
return NimBLEConnInfo();
|
||||
}
|
||||
|
||||
return getPeerIDInfo(m_connectedPeersVec[index]);
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by address.
|
||||
* @param [in] address The address of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerInfo(const NimBLEAddress& address) {
|
||||
ble_addr_t peerAddr;
|
||||
memcpy(&peerAddr.val, address.getNative(),6);
|
||||
peerAddr.type = address.getType();
|
||||
|
||||
NimBLEConnInfo peerInfo;
|
||||
int rc = ble_gap_conn_find_by_addr(&peerAddr, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the connection information of a connected peer by connection ID.
|
||||
* @param [in] id The connection id of the peer.
|
||||
*/
|
||||
NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
NimBLEConnInfo peerInfo;
|
||||
|
||||
int rc = ble_gap_conn_find(id, &peerInfo.m_desc);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Peer info not found");
|
||||
}
|
||||
|
||||
return peerInfo;
|
||||
} // getPeerIDInfo
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle a GATT Server Event.
|
||||
*
|
||||
@ -261,7 +338,9 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->m_pServerCallbacks->onConnect(server);
|
||||
server->m_pServerCallbacks->onConnect(server, &desc);
|
||||
@ -316,7 +395,9 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
(it->getProperties() & BLE_GATT_CHR_F_READ_ENC))
|
||||
{
|
||||
rc = ble_gap_conn_find(event->subscribe.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!desc.sec_state.encrypted) {
|
||||
NimBLEDevice::startSecurity(event->subscribe.conn_handle);
|
||||
@ -339,18 +420,44 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
} // BLE_GAP_EVENT_MTU
|
||||
|
||||
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||
if(event->notify_tx.indication && event->notify_tx.status != 0) {
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
if(it->m_pTaskData != nullptr) {
|
||||
it->m_pTaskData->rc = event->notify_tx.status;
|
||||
xTaskNotifyGive(it->m_pTaskData->task);
|
||||
}
|
||||
break;
|
||||
}
|
||||
NimBLECharacteristic *pChar = nullptr;
|
||||
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->notify_tx.attr_handle) {
|
||||
pChar = it;
|
||||
}
|
||||
}
|
||||
|
||||
if(pChar == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLECharacteristicCallbacks::Status statusRC;
|
||||
|
||||
if(event->notify_tx.indication) {
|
||||
if(event->notify_tx.status != 0) {
|
||||
if(event->notify_tx.status == BLE_HS_EDONE) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE;
|
||||
} else if(rc == BLE_HS_ETIMEOUT) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
server->clearIndicateWait(event->notify_tx.conn_handle);
|
||||
} else {
|
||||
if(event->notify_tx.status == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
}
|
||||
}
|
||||
|
||||
pChar->m_pCallbacks->onStatus(pChar, statusRC, event->notify_tx.status);
|
||||
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
@ -373,7 +480,10 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
|
||||
/* Delete the old bond. */
|
||||
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
if (rc != 0){
|
||||
return BLE_GAP_REPEAT_PAIRING_IGNORE;
|
||||
}
|
||||
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
|
||||
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
|
||||
@ -414,7 +524,7 @@ size_t NimBLEServer::getConnectedCount() {
|
||||
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
|
||||
|
||||
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp);
|
||||
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %lu", event->passkey.params.numcmp);
|
||||
pkey.action = event->passkey.params.action;
|
||||
// Compatibility only - Do not use, should be removed the in future
|
||||
if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
@ -540,14 +650,23 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a service which was already created, but removed from availability.
|
||||
* @brief Adds a service which was either already created but removed from availability,\n
|
||||
* or created and later added to services list.
|
||||
* @param [in] service The service object to add.
|
||||
* @note If it is desired to advertise the service it must be added by
|
||||
* calling NimBLEAdvertising::addServiceUUID.
|
||||
*/
|
||||
void NimBLEServer::addService(NimBLEService* service) {
|
||||
// If adding a service that was not removed just return.
|
||||
// Check that a service with the supplied UUID does not already exist.
|
||||
if(getServiceByUUID(service->getUUID()) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
|
||||
std::string(service->getUUID()).c_str());
|
||||
}
|
||||
|
||||
// If adding a service that was not removed add it and return.
|
||||
// Else reset GATT and send service changed notification.
|
||||
if(service->m_removed == 0) {
|
||||
m_svcVec.push_back(service);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -646,7 +765,28 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
|
||||
if(rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
} // updateConnParams
|
||||
}// updateConnParams
|
||||
|
||||
|
||||
bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEServer::clearIndicateWait(uint16_t conn_handle) {
|
||||
for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) {
|
||||
if(m_indWait[i] == conn_handle) {
|
||||
m_indWait[i] = BLE_HS_CONN_HANDLE_NONE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Default callback handlers */
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "NimBLEAdvertising.h"
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
|
||||
|
||||
class NimBLEService;
|
||||
@ -49,15 +50,19 @@ public:
|
||||
void startAdvertising();
|
||||
void stopAdvertising();
|
||||
void start();
|
||||
NimBLEService* getServiceByUUID(const char* uuid);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLEService* getServiceByHandle(uint16_t handle);
|
||||
int disconnect(uint16_t connID,
|
||||
uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
void updateConnParams(uint16_t conn_handle,
|
||||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
uint16_t getPeerMTU(uint16_t conn_id);
|
||||
// std::vector<uint16_t> getPeerDevices();
|
||||
std::vector<uint16_t> getPeerDevices();
|
||||
NimBLEConnInfo getPeerInfo(size_t index);
|
||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
void advertiseOnDisconnect(bool);
|
||||
|
||||
private:
|
||||
@ -72,6 +77,7 @@ private:
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
uint16_t m_indWait[CONFIG_BT_NIMBLE_MAX_CONNECTIONS];
|
||||
std::vector<uint16_t> m_connectedPeersVec;
|
||||
|
||||
// uint16_t m_svcChgChrHdl; // Future use
|
||||
@ -81,6 +87,8 @@ private:
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
void resetGATT();
|
||||
bool setIndicateWait(uint16_t conn_handle);
|
||||
void clearIndicateWait(uint16_t conn_handle);
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
|
@ -233,9 +233,9 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||
// Check that we don't add the same characteristic twice.
|
||||
|
||||
if (getCharacteristic(uuid) != nullptr) {
|
||||
NIMBLE_LOGW(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
|
||||
std::string(uuid).c_str());
|
||||
}
|
||||
|
||||
@ -246,31 +246,80 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
||||
} // createCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
void NimBLEService::addCharacteristic(NimBLECharacteristic* pCharacteristic) {
|
||||
pCharacteristic->setService(this);
|
||||
m_chrVec.push_back(pCharacteristic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t instanceId) {
|
||||
return getCharacteristic(NimBLEUUID(uuid), instanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @param instanceId The index of the characteristic to return (used when multiple characteristics have the same UUID).
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId) {
|
||||
uint16_t position = 0;
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
return it;
|
||||
if (position == instanceId) {
|
||||
return it;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified handle.
|
||||
* @param handle The handle of the characteristic.
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic *NimBLEService::getCharacteristicByHandle(uint16_t handle) {
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getHandle() == handle) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics() {
|
||||
return m_chrVec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const char *uuid) {
|
||||
return getCharacteristics(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A vector containing pointers to each characteristic with the provided UUID associated with this service.
|
||||
*/
|
||||
std::vector<NimBLECharacteristic *> NimBLEService::getCharacteristics(const NimBLEUUID &uuid) {
|
||||
std::vector<NimBLECharacteristic*> result;
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
result.push_back(it);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of this service.
|
||||
@ -295,7 +344,7 @@ std::string NimBLEService::toString() {
|
||||
*/
|
||||
NimBLEServer* NimBLEService::getServer() {
|
||||
return m_pServer;
|
||||
} // getServer
|
||||
}// getServer
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif // CONFIG_BT_ENABLED
|
||||
|
@ -35,6 +35,20 @@ class NimBLECharacteristic;
|
||||
*/
|
||||
class NimBLEService {
|
||||
public:
|
||||
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
NimBLEServer* getServer();
|
||||
|
||||
NimBLEUUID getUUID();
|
||||
uint16_t getHandle();
|
||||
std::string toString();
|
||||
void dump();
|
||||
|
||||
bool start();
|
||||
|
||||
NimBLECharacteristic* createCharacteristic(const char* uuid,
|
||||
uint32_t properties =
|
||||
NIMBLE_PROPERTY::READ |
|
||||
@ -45,19 +59,17 @@ public:
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE);
|
||||
|
||||
void dump();
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||
NimBLEUUID getUUID();
|
||||
NimBLEServer* getServer();
|
||||
bool start();
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
|
||||
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle);
|
||||
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics();
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics(const char* uuid);
|
||||
std::vector<NimBLECharacteristic*> getCharacteristics(const NimBLEUUID &uuid);
|
||||
|
||||
|
||||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Author: kolban
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEUUID.h"
|
||||
@ -65,29 +65,42 @@ static const char* LOG_TAG = "NimBLEUUID";
|
||||
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||
}
|
||||
else {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
||||
m_valueSet = false;
|
||||
}
|
||||
} // NimBLEUUID(std::string)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a UUID from 16 bytes of memory.
|
||||
* @brief Create a UUID from 2, 4, 16 bytes of memory.
|
||||
* @param [in] pData The pointer to the start of the UUID.
|
||||
* @param [in] size The size of the data.
|
||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||
if (size != 16) {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes");
|
||||
return;
|
||||
}
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
uint8_t *uuidValue = nullptr;
|
||||
|
||||
switch(size) {
|
||||
case 2:
|
||||
uuidValue = (uint8_t*)&m_uuid.u16.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||
break;
|
||||
case 4:
|
||||
uuidValue = (uint8_t*)&m_uuid.u32.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||
break;
|
||||
case 16:
|
||||
uuidValue = m_uuid.u128.value;
|
||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||
break;
|
||||
default:
|
||||
m_valueSet = false;
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid UUID size");
|
||||
return;
|
||||
}
|
||||
if (msbFirst) {
|
||||
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
||||
std::reverse_copy(pData, pData + size, uuidValue);
|
||||
} else {
|
||||
memcpy(m_uuid.u128.value, pData, 16);
|
||||
memcpy(uuidValue, pData, size);
|
||||
}
|
||||
m_valueSet = true;
|
||||
} // NimBLEUUID
|
||||
@ -264,10 +277,6 @@ std::string NimBLEUUID::toString() const {
|
||||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
NIMBLE_LOGD(LOG_TAG,"Comparing UUIDs; type %u to %u; UUID %s to %s",
|
||||
m_uuid.u.type, rhs.m_uuid.u.type,
|
||||
this->toString().c_str(), rhs.toString().c_str());
|
||||
|
||||
if(m_uuid.u.type != rhs.m_uuid.u.type) {
|
||||
uint8_t uuidBase[16] = {
|
||||
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||||
|
@ -15,7 +15,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEUUID_H_
|
||||
#define COMPONENTS_NIMBLEUUID_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_uuid.h"
|
||||
/**** FIX COMPILATION ****/
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef COMPONENTS_NIMBLEUTILS_H_
|
||||
#define COMPONENTS_NIMBLEUTILS_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_NIMBLE_ENABLED)
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
|
286
src/nimconfig.h
286
src/nimconfig.h
@ -1,241 +1,93 @@
|
||||
/** @file
|
||||
*
|
||||
/** @file
|
||||
*
|
||||
* IGNORE THIS FILE IF USING ESP-IDF, USE MENUCONFIG TO SET NIMBLE OPTIONS.
|
||||
*
|
||||
* The config options here are for Arduino use only.
|
||||
* The config options here are for doxygen documentation only.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/*
|
||||
* For ESP-IDF compatibility
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
|
||||
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig)
|
||||
*
|
||||
* Note: We do not use #ifdef CONFIG_BT_NIMBLE_ENABLED since we cannot enable NimBLE when using
|
||||
* Arduino as a component and the esp-nimble-compnent, so we check if other config options are defined.
|
||||
* We also need to use a config parameter that must be present and not likely defined in the command line.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN) || defined(CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN)
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ENABLED) && !defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
#define CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_DEBUG) && !defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
#endif
|
||||
|
||||
#else // Using Arduino
|
||||
|
||||
/***********************************************
|
||||
* Arduino config options start here
|
||||
**********************************************/
|
||||
|
||||
/** @brief Comment out if not using NimBLE Client functions \n
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
/** @brief Comment out if not using NimBLE Scan functions \n
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
/** @brief Comment out if not using NimBLE Server functions \n
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
/** @brief Comment out if not using NimBLE Advertising functions \n
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
/* Uncomment to see debug log messages from the NimBLE host
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/* Uncomment to see NimBLE host return codes as text debug log messages.
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/* Uncomment to see GAP event codes as text in debug log messages.
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/* Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
|
||||
/** @brief Sets the core NimBLE host runs on */
|
||||
#ifndef CONFIG_BT_NIMBLE_PINNED_TO_CORE
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
#endif
|
||||
|
||||
/** @brief Sets the stack size for the NimBLE host task */
|
||||
#ifndef CONFIG_BT_NIMBLE_TASK_STACK_SIZE
|
||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sets the memory pool where NimBLE will be loaded
|
||||
* @details By default NimBLE is loaded in internal ram.\n
|
||||
* To use external PSRAM you must change this to `#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1`
|
||||
*/
|
||||
#ifndef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
#endif
|
||||
|
||||
/** @brief Sets the number of simultaneous connections (esp controller max is 9) */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
#endif
|
||||
|
||||
/** @brief Sets the number of devices allowed to store/bond with */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_BONDS
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
#endif
|
||||
|
||||
/** @brief Sets the maximum number of CCCD subscriptions to store */
|
||||
#ifndef CONFIG_BT_NIMBLE_MAX_CCCDS
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
#endif
|
||||
|
||||
/** @brief Default device name */
|
||||
#ifndef CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
#endif
|
||||
|
||||
/** @brief Set if CCCD's and bond data should be stored in NVS */
|
||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
||||
|
||||
/** @brief Allow legacy paring */
|
||||
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
|
||||
|
||||
/** @brief Allow BLE secure connections */
|
||||
#define CONFIG_BT_NIMBLE_SM_SC 1
|
||||
|
||||
/** @brief Max device name length (bytes) */
|
||||
#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31
|
||||
|
||||
/** @brief Default MTU size */
|
||||
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 256
|
||||
|
||||
/** @brief Default GAP appearance */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
|
||||
/** @brief ACL Buffer count */
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
|
||||
|
||||
/** @brief ACL Buffer size */
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
|
||||
|
||||
/** @brief HCI Event Buffer size */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
|
||||
|
||||
/** @brief Number of high priority HCI event buffers */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
|
||||
|
||||
/** @brief Number of low priority HCI event buffers */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8
|
||||
|
||||
/**
|
||||
* @brief Sets the number of MSYS buffers available.
|
||||
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
|
||||
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
|
||||
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
|
||||
/** @brief Random address refresh time in seconds */
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
|
||||
/** @brief Maximum number of connection oriented channels */
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
|
||||
/* These should not be altered */
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL 1
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
|
||||
|
||||
#ifndef CONFIG_BT_ENABLED
|
||||
#define CONFIG_BT_ENABLED
|
||||
#endif
|
||||
|
||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
/**********************************
|
||||
End Arduino config
|
||||
**********************************/
|
||||
|
||||
|
||||
/* Cannot use client without scan */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
/* Cannot use server without advertise */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
|
||||
#include "nimconfig_rename.h"
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/** @brief Uncomment to see debug log messages from the NimBLE host \n
|
||||
|
||||
/** @brief Un-comment to change the number of simultaneous connections (esp controller max is 9) */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
|
||||
/** @brief Un-comment to change the default MTU size */
|
||||
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||
|
||||
/** @brief Un-comment to change default device name */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
|
||||
/** @brief Un-comment to see debug log messages from the NimBLE host
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/** @brief Uncomment to see NimBLE host return codes as text debug log messages. \n
|
||||
/** @brief Un-comment to see NimBLE host return codes as text debug log messages.
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see GAP event codes as text in debug log messages. \n
|
||||
/** @brief Un-comment to see GAP event codes as text in debug log messages.
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see advertisment types as text while scanning in debug log messages. \n
|
||||
/** @brief Un-comment to see advertisment types as text while scanning in debug log messages.
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
|
||||
/** @brief Un-comment to change the default GAP appearance */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Client functions \n
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Scan functions \n
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Server functions \n
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED
|
||||
|
||||
/** @brief Un-comment if not using NimBLE Advertising functions \n
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED
|
||||
|
||||
/** @brief Un-comment to change the number of devices allowed to store/bond with */
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
|
||||
/** @brief Un-comment to change the maximum number of CCCD subscriptions to store */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
|
||||
/** @brief Un-comment to change the random address refresh time (in seconds) */
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
|
||||
/**
|
||||
* @brief Un-comment to change the number of MSYS buffers available.
|
||||
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
|
||||
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
|
||||
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
|
||||
/** @brief Un-comment to use external PSRAM for the NimBLE host */
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1
|
||||
|
||||
/** @brief Un-comment to change the core NimBLE host runs on */
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
|
||||
/** @brief Un-comment to change the stack size for the NimBLE host task */
|
||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
|
||||
#endif // _DOXYGEN_
|
||||
|
53
src/nimconfig_rename.h
Normal file
53
src/nimconfig_rename.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* For ESP-IDF compatibility
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ENABLED) && !defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
#define CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_DEBUG) && !defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA ) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA CONFIG_SCAN_DUPLICATE_BY_ADV_DATA
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCAN_DUPLICATE_TYPE) && !defined(CONFIG_BTDM_SCAN_DUPL_TYPE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_TYPE CONFIG_SCAN_DUPLICATE_TYPE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DUPLICATE_SCAN_CACHE_SIZE) && !defined(CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE)
|
||||
#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NIMBLE_MAX_CONNECTIONS ) && !defined(CONFIG_BT_NIMBLE_MAX_CONNECTIONS)
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
|
||||
#endif
|
Reference in New Issue
Block a user