diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7c366ee..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-sudo: false
-
-before_install:
- - cd ${TMPDIR-/tmp}
- - wget -q http://doxygen.nl/files/doxygen-1.9.0.src.tar.gz
- - tar -xzvf doxygen-1.9.0.src.tar.gz
- - mkdir doxygen_build
- - cd doxygen_build
- - cmake ../doxygen-1.9.0/
- - make
- - export PATH="${TMPDIR-/tmp}/doxygen_build/bin:$PATH"
- - cd ${TRAVIS_BUILD_DIR}
-
-branches:
- only:
- - master
-
-script:
- - doxygen ./docs/Doxyfile
-
-deploy:
- provider: pages
- skip_cleanup: true
- local_dir: docs/html
- github_token: $GH_REPO_TOKEN
- on:
- branch: master
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69bb956..3dfcd1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,38 @@
# Changelog
-All notable changes to this project will be documented in this file.
+All notable changes to this project will be documented in this file.
+
+## [1.3.3] - 2022-02-15
+
+### Changed
+- If attribute retrieval fails with a "not found" try again with the 16 bit version if a 128 bit base uuid is used.
+
+### Fixed
+- Memory leak when deleting client instance.
+- IDf version check for data length extension.
+- Memory leak when server services changed.
+- Compiler warnings for non-esp32 devices.
+
+## [1.3.2] - 2022-01-15
+
+### Fixed
+- Initialize advertising complete callback in NimBLEAdvertising constructor.
+- Clear client disconnect timer in constructor before initializing.
+- Fix missing data when reading large values.
+- Fix missing data in notifications when using a large MTU size and more than 270 bytes of data are sent.
+- Workaround fix added for cases when the task notification value is not cleared, causing various functions that should block not to block.
+
+### Added
+- `NimBLEClient::getLastError` : Gets the error code of the last function call that produces a return code from the stack.
+- `NimBLECharacteristic::notify` : Overload method to send notifications/indications with custom values.
+- Added conditional checks for ESP32 specific functions/values to support use of the library on non-esp32 devices.
+- Added an alias to use the callback name from the original library `onMtuChanged`.
+- `NimBLEClient::setDataLen` and `NimBLEServer::setDataLen`: Data length extension support (IDF version >= 4.3.2 only)
+- Config option to set logging level for esp-nimble-cpp
+
+### Changed
+- Critical section calls now use the NimBLE API instead of FreeRTOS directly. This removes the need for a `portMUX_TYPE` variable in the class definitions.
+- Removed unnecessary variables in `NimBLEService` and changed the constructor no no longer accept `numHandles` and `inst_id` parameters.
## [1.3.1] - 2021-08-04
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f9e8cd..28780b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@ idf_component_register(
"src/NimBLEDevice.cpp"
"src/NimBLEEddystoneTLM.cpp"
"src/NimBLEEddystoneURL.cpp"
+ "src/NimBLEExtAdvertising.cpp"
"src/NimBLEHIDDevice.cpp"
"src/NimBLERemoteCharacteristic.cpp"
"src/NimBLERemoteDescriptor.cpp"
diff --git a/Kconfig b/Kconfig
index 069b000..c13fde1 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,5 +1,31 @@
menu "ESP-NimBLE-CPP configuration"
+choice NIMBLE_CPP_LOG_LEVEL
+ prompt "NimBLE CPP log verbosity"
+ default NIMBLE_CPP_LOG_LEVEL_NONE
+ help
+ Select NimBLE CPP log verbosity level.
+
+ config NIMBLE_CPP_LOG_LEVEL_NONE
+ bool "No logs"
+ config NIMBLE_CPP_LOG_LEVEL_ERROR
+ bool "Error logs"
+ config NIMBLE_CPP_LOG_LEVEL_WARNING
+ bool "Warning logs"
+ config NIMBLE_CPP_LOG_LEVEL_INFO
+ bool "Info logs"
+ config NIMBLE_CPP_LOG_LEVEL_DEBUG
+ bool "Debug logs"
+endchoice #NIMBLE_CPP_LOG_LEVEL
+
+config NIMBLE_CPP_LOG_LEVEL
+ int
+ default 0 if NIMBLE_CPP_LOG_LEVEL_NONE
+ default 1 if NIMBLE_CPP_LOG_LEVEL_ERROR
+ default 2 if NIMBLE_CPP_LOG_LEVEL_WARNING
+ default 3 if NIMBLE_CPP_LOG_LEVEL_INFO
+ default 4 if NIMBLE_CPP_LOG_LEVEL_DEBUG
+
config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
bool "Show NimBLE return codes as text in debug log."
default "n"
@@ -23,5 +49,24 @@ config NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
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.
+
+config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
+ bool "Enable timestamps to be stored with attribute values."
+ default "n"
+ help
+ Enabling this option will store the timestamp when an attribute value is updated.
+ This allows for checking the last update time using getTimeStamp()
+ or getValue(time_t*). If disabled, the timestamp returned from these functions will be 0.
+ Disabling timestamps will reduce the memory used for each value.
+
+config NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
+ int "Initial attribute value size (bytes) for empty values."
+ range 1 512
+ default 20
+ help
+ Sets the default allocation size (bytes) for each attribute if not specified
+ when the constructor is called. This is also the size used when a remote
+ characteristic or descriptor is constructed before a value is read/notifed.
+ Increasing this will reduce reallocations but increase memory footprint.
endmenu
diff --git a/docs/Bluetooth 5 features.md b/docs/Bluetooth 5 features.md
new file mode 100644
index 0000000..c0d03b5
--- /dev/null
+++ b/docs/Bluetooth 5 features.md
@@ -0,0 +1,29 @@
+# Bluetooth 5.x features
+
+## About extended advertising
+Extended advertising allows for much more capability and flexibility.
+
+* Allows for 251 bytes of advertisement data and up to 1650 bytes when chained (configuration dependant) vs 31.
+
+* New PHY's (physical layers) that allow for faster data rate (2M PHY) or long range/slower data rates (CODED PHY) as well as the original 1M PHY.
+
+* New periodic advertising, allowing the scanning device to sync with the advertisements of a beacon. This allows for the scanning device to sleep or perform other tasks before the next expected advertisement is sent, preserving cpu cycles and power (To be implemented).
+
+
+## Enabling extended advertising
+Extended advertising is supported when enabled with the config option `CONFIG_BT_NIMBLE_EXT_ADV` set to a value of 1. This is done in menuconfig under `Component config > Bluetooth > NimBLE options >
+Enable extended advertising`.
+
+When enabled the following will occur:
+* `NimBLEScan::start` method will scan on both the 1M PHY and the coded PHY standards automatically.
+
+* `NimBLEClient::connect` will use the primary PHY the device is listening on, unless specified (see below).
+
+* `NimBLEClient::setConnectPhy` becomes available to specify the PHY's to connect with (default is all).
+
+* `NimBLEAdvertising` is no longer available for use and is replaced by `NimBLEExtAdvertising`. `NimBLEDevice::getAdvertising` will now return an instance of `NimBLEExtAdvertising`.
+
+* `NimBLEAdvertisementData` is no longer available for use and is replaced by `NimBLEExtAdvertisement`. This new class is where everything about the advertisement is configured, including the advertisement intervals and advertisement ended callback.
+
+
+
diff --git a/docs/Command_line_config.md b/docs/Command_line_config.md
index c22565f..3fe4acb 100644
--- a/docs/Command_line_config.md
+++ b/docs/Command_line_config.md
@@ -6,6 +6,24 @@ Sets the number of simultaneous connections (esp controller max is 9)
- Default value is 3
+`CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED`
+
+Enable/disable storing the timestamp when an attribute value is updated
+This allows for checking the last update time using getTimeStamp() or getValue(time_t*)
+If disabled, the timestamp returned from these functions will be 0.
+Disabling timestamps will reduce the memory used for each value.
+1 = Enabled, 0 = Disabled; Default = Disabled
+
+
+`CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH`
+
+Set the default allocation size (bytes) for each attribute.
+If not specified when the constructor is called. This is also the size used when a remote
+characteristic or descriptor is constructed before a value is read/notifed.
+Increasing this will reduce reallocations but increase memory footprint.
+Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
+
+
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
Sets the default MTU size.
@@ -24,6 +42,13 @@ If defined, enables debug log messages from the NimBLE host
- Uses approx. 32kB of flash memory.
+`CONFIG_NIMBLE_CPP_LOG_LEVEL`
+
+Define to set the debug log message level from the NimBLE CPP Wrapper.
+If not defined it will use the same value as the Arduino core debug level.
+Values: 0 = NONE, 1 = ERROR, 2 = WARNING, 3 = INFO, 4+ = DEBUG
+
+
`CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT`
If defined, NimBLE host return codes will be printed as text in debug log messages.
diff --git a/docs/Doxyfile b/docs/Doxyfile
index 34d13cc..1d9a18b 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.18
+# Doxyfile 1.9.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = "esp-nimble-cpp / NimBLE-Arduino"
+PROJECT_NAME = esp-nimble-cpp
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 1.3.1
+PROJECT_NUMBER = 1.3.2
# 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
@@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = docs
+OUTPUT_DIRECTORY = .
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -227,6 +227,14 @@ QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
@@ -315,7 +323,10 @@ OPTIMIZE_OUTPUT_SLICE = NO
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
EXTENSION_MAPPING =
@@ -449,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which efficively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
@@ -512,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
@@ -549,11 +580,18 @@ HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = NO
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# (including Cygwin) ands Mac users are advised to set this option to NO.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
# The default value is: system dependent.
CASE_SENSE_NAMES = NO
@@ -792,7 +830,10 @@ WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
# The default value is: NO.
WARN_AS_ERROR = NO
@@ -823,13 +864,15 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
-INPUT = .
+INPUT = ../CHANGELOG.md \
+ . \
+ ../src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
@@ -842,13 +885,15 @@ INPUT_ENCODING = UTF-8
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
-# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
-# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
-# *.vhdl, *.ucf, *.qsf and *.ice.
+# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
+# *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.c \
*.cc \
@@ -911,11 +956,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE = ./README.md \
- ./src/FreeRTOS.h \
- ./src/FreeRTOS.cpp \
- ./examples \
- ./CMakelists.txt
+EXCLUDE = ../src/nimconfig_rename.h
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -1112,6 +1153,44 @@ USE_HTAGS = NO
VERBATIM_HEADERS = YES
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
+# YES then doxygen will add the directory of each input to the include path.
+# The default value is: YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@@ -1123,13 +1202,6 @@ VERBATIM_HEADERS = YES
ALPHABETICAL_INDEX = YES
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX = 5
-
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
@@ -1300,10 +1372,11 @@ HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: https://developer.apple.com/xcode/), introduced with OSX
-# 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
# genXcode/_index.html for more information.
@@ -1345,8 +1418,8 @@ DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# (see:
+# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1376,7 +1449,7 @@ CHM_FILE =
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
+# (YES) or that it should be included in the main .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@@ -1421,7 +1494,8 @@ QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
-# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1429,8 +1503,8 @@ QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
@@ -1438,16 +1512,16 @@ QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
@@ -1459,9 +1533,9 @@ QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
@@ -1542,8 +1616,8 @@ EXT_LINKS_IN_WINDOW = NO
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
# the HTML output. These images will generally look nicer at scaled resolutions.
-# Possible values are: png The default and svg Looks nicer but requires the
-# pdf2svg tool.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
# The default value is: png.
# This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1588,7 +1662,7 @@ USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
@@ -1618,7 +1692,8 @@ MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
@@ -1665,7 +1740,8 @@ SERVER_BASED_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
@@ -1678,8 +1754,9 @@ EXTERNAL_SEARCH = NO
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: https://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
@@ -1843,9 +1920,11 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@@ -2084,6 +2163,10 @@ DOCBOOK_PROGRAMLISTING = NO
GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
@@ -2361,10 +2444,32 @@ UML_LOOK = NO
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
UML_LIMIT_NUM_FIELDS = 10
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
@@ -2554,9 +2659,11 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc and
+# plantuml temporary files.
# The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
diff --git a/examples/Bluetooth_5/NimBLE_extended_client/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_extended_client/CMakeLists.txt
new file mode 100644
index 0000000..f46b44a
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_client/CMakeLists.txt
@@ -0,0 +1,7 @@
+# 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)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(SUPPORTED_TARGETS esp32c3 esp32s3)
+project(NimBLE_extended_client)
diff --git a/examples/Bluetooth_5/NimBLE_extended_client/Makefile b/examples/Bluetooth_5/NimBLE_extended_client/Makefile
new file mode 100644
index 0000000..2e4842d
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_client/Makefile
@@ -0,0 +1,3 @@
+PROJECT_NAME := NimBLE_extended_client
+
+include $(IDF_PATH)/make/project.mk
diff --git a/examples/Bluetooth_5/NimBLE_extended_client/main/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_extended_client/main/CMakeLists.txt
new file mode 100644
index 0000000..0a5a557
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_client/main/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(COMPONENT_SRCS "main.cpp")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+register_component()
diff --git a/examples/Bluetooth_5/NimBLE_extended_client/main/component.mk b/examples/Bluetooth_5/NimBLE_extended_client/main/component.mk
new file mode 100644
index 0000000..a98f634
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_client/main/component.mk
@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
diff --git a/examples/Bluetooth_5/NimBLE_extended_client/main/main.cpp b/examples/Bluetooth_5/NimBLE_extended_client/main/main.cpp
new file mode 100644
index 0000000..56881d0
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_client/main/main.cpp
@@ -0,0 +1,169 @@
+
+/** NimBLE Extended Client Demo:
+ *
+ * Demonstrates the Bluetooth 5.x client capabilities.
+ *
+ * Created: on April 2 2022
+ * Author: H2zero
+ *
+*/
+#include
+
+extern "C" void app_main(void);
+
+void scanEndedCB(NimBLEScanResults results);
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+static NimBLEAdvertisedDevice* advDevice;
+static bool doConnect = false;
+static uint32_t scanTime = 10; /* 0 = scan forever */
+
+/* Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default).*/
+static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /*| BLE_GAP_LE_PHY_2M_MASK */ ;
+
+/* Define a class to handle the callbacks for client connection events */
+class ClientCallbacks : public NimBLEClientCallbacks {
+ void onConnect(NimBLEClient* pClient) {
+ printf("Connected\n");
+ };
+
+ void onDisconnect(NimBLEClient* pClient) {
+ printf("%s Disconnected - Starting scan\n", pClient->getPeerAddress().toString().c_str());
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ };
+};
+
+
+/* Define a class to handle the callbacks when advertisements are received */
+class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
+
+ void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
+ printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
+ if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
+ {
+ printf("Found Our Service\n");
+ /* Ready to connect now */
+ doConnect = true;
+ /* Save the device reference in a global for the client to use*/
+ advDevice = advertisedDevice;
+ /* stop scan before connecting */
+ NimBLEDevice::getScan()->stop();
+ }
+ };
+};
+
+
+/* Callback to process the results of the last scan or restart it */
+void scanEndedCB(NimBLEScanResults results){
+ printf("Scan Ended\n");
+ if (!doConnect) { /* Don't start the scan while connecting */
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ }
+}
+
+
+/* Handles the provisioning of clients and connects / interfaces with the server */
+bool connectToServer() {
+ NimBLEClient* pClient = nullptr;
+
+ pClient = NimBLEDevice::createClient();
+ pClient->setClientCallbacks(new ClientCallbacks, false);
+
+ /* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
+ * * 0x01 BLE_GAP_LE_PHY_1M_MASK
+ * * 0x02 BLE_GAP_LE_PHY_2M_MASK
+ * * 0x04 BLE_GAP_LE_PHY_CODED_MASK
+ * Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
+ */
+ pClient->setConnectPhy(connectPhys);
+
+ /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
+ pClient->setConnectTimeout(10);
+
+ if (!pClient->connect(advDevice)) {
+ /* Created a client but failed to connect, don't need to keep it as it has no data */
+ NimBLEDevice::deleteClient(pClient);
+ printf("Failed to connect, deleted client\n");
+ return false;
+ }
+
+ printf("Connected to: %s RSSI: %d\n",
+ pClient->getPeerAddress().toString().c_str(),
+ pClient->getRssi());
+
+ /* Now we can read/write/subscribe the charateristics of the services we are interested in */
+ NimBLERemoteService* pSvc = nullptr;
+ NimBLERemoteCharacteristic* pChr = nullptr;
+
+ pSvc = pClient->getService(SERVICE_UUID);
+
+ if (pSvc) {
+ pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
+
+ if (pChr) {
+ // Read the value of the characteristic.
+ if (pChr->canRead()) {
+ std::string value = pChr->readValue();
+ printf("Characteristic value: %s\n", value.c_str());
+ }
+ }
+
+ } else {
+ printf("ABCD service not found.\n");
+ }
+
+ NimBLEDevice::deleteClient(pClient);
+ printf("Done with this device!\n");
+ return true;
+}
+
+void connectTask (void * parameter){
+ /* Loop here until we find a device we want to connect to */
+ for (;;) {
+ if (doConnect) {
+ /* Found a device we want to connect to, do it now */
+ if (connectToServer()) {
+ printf("Success!, scanning for more!\n");
+ } else {
+ printf("Failed to connect, starting scan\n");
+ }
+
+ doConnect = false;
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ }
+ vTaskDelay(pdMS_TO_TICKS(10));
+ }
+
+ vTaskDelete(NULL);
+}
+
+void app_main (void) {
+ printf("Starting NimBLE Client\n");
+ /* Create a task to handle connecting to peers */
+ xTaskCreate(connectTask, "connectTask", 5000, NULL, 1, NULL);
+
+ /* Initialize NimBLE, no device name specified as we are not advertising */
+ NimBLEDevice::init("");
+ NimBLEScan* pScan = NimBLEDevice::getScan();
+
+ /* create a callback that gets called when advertisers are found */
+ pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
+
+ /* Set scan interval (how often) and window (how long) in milliseconds */
+ pScan->setInterval(97);
+ pScan->setWindow(67);
+
+ /* Active scan will gather scan response data from advertisers
+ * but will use more energy from both devices
+ */
+ pScan->setActiveScan(true);
+
+ /* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
+ * Optional callback for when scanning stops.
+ */
+ pScan->start(scanTime, scanEndedCB);
+
+ printf("Scanning for peripherals\n");
+}
diff --git a/examples/Bluetooth_5/NimBLE_extended_server/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_extended_server/CMakeLists.txt
new file mode 100644
index 0000000..c58174a
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_server/CMakeLists.txt
@@ -0,0 +1,7 @@
+# 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)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(SUPPORTED_TARGETS esp32c3 esp32s3)
+project(NimBLE_extended_server)
diff --git a/examples/Bluetooth_5/NimBLE_extended_server/Makefile b/examples/Bluetooth_5/NimBLE_extended_server/Makefile
new file mode 100644
index 0000000..a18cf9f
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_server/Makefile
@@ -0,0 +1,3 @@
+PROJECT_NAME := NimBLE_extended_server
+
+include $(IDF_PATH)/make/project.mk
diff --git a/examples/Bluetooth_5/NimBLE_extended_server/main/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_extended_server/main/CMakeLists.txt
new file mode 100644
index 0000000..0a5a557
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_server/main/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(COMPONENT_SRCS "main.cpp")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+register_component()
diff --git a/examples/Bluetooth_5/NimBLE_extended_server/main/component.mk b/examples/Bluetooth_5/NimBLE_extended_server/main/component.mk
new file mode 100644
index 0000000..a98f634
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_server/main/component.mk
@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
diff --git a/examples/Bluetooth_5/NimBLE_extended_server/main/main.cpp b/examples/Bluetooth_5/NimBLE_extended_server/main/main.cpp
new file mode 100644
index 0000000..096a281
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_extended_server/main/main.cpp
@@ -0,0 +1,139 @@
+/** NimBLE Extended Server Demo:
+ *
+ * Demonstrates the Bluetooth 5.x extended advertising capabilities.
+ *
+ * This demo will advertise a long data string on the CODED and 1M Phy's and
+ * starts a server allowing connection over either PHY's. It will advertise for
+ * 5 seconds then sleep for 20 seconds, if a client connects it will sleep once
+ * it has disconnected then repeats.
+ *
+ * Created: on April 2 2022
+ * Author: H2zero
+ *
+*/
+
+#include "NimBLEDevice.h"
+#include "esp_sleep.h"
+
+extern "C" void app_main(void);
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+/* Time in milliseconds to advertise */
+static uint32_t advTime = 5000;
+
+/* Time to sleep between advertisements */
+static uint32_t sleepSeconds = 20;
+
+/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
+static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
+
+/* Secondary PHY used for advertising and connecting,
+ * can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
+ */
+static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
+
+
+/* Handler class for server events */
+class ServerCallbacks: public NimBLEServerCallbacks {
+ void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
+ printf("Client connected: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
+ };
+
+ void onDisconnect(NimBLEServer* pServer) {
+ printf("Client disconnected - sleeping for %u seconds\n", sleepSeconds);
+ esp_deep_sleep_start();
+ };
+};
+
+/* Callback class to handle advertising events */
+class advertisingCallbacks: public NimBLEExtAdvertisingCallbacks {
+ void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
+ /* Check the reason advertising stopped, don't sleep if client is connecting */
+ printf("Advertising instance %u stopped\n", inst_id);
+ switch (reason) {
+ case 0:
+ printf("Client connecting\n");
+ return;
+ case BLE_HS_ETIMEOUT:
+ printf("Time expired - sleeping for %u seconds\n", sleepSeconds);
+ break;
+ default:
+ break;
+ }
+
+ esp_deep_sleep_start();
+ }
+};
+
+void app_main (void) {
+ NimBLEDevice::init("Extended advertiser");
+
+ /* Create the server and add the services/characteristics/descriptors */
+ NimBLEServer *pServer = NimBLEDevice::createServer();
+ pServer->setCallbacks(new ServerCallbacks);
+
+ NimBLEService *pService = pServer->createService(SERVICE_UUID);
+ NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
+ NIMBLE_PROPERTY::READ |
+ NIMBLE_PROPERTY::WRITE |
+ NIMBLE_PROPERTY::NOTIFY);
+
+ pCharacteristic->setValue("Hello World");
+
+ /* Start the services */
+ pService->start();
+
+ /*
+ * Create an extended advertisement with the instance ID 0 and set the PHY's.
+ * Multiple instances can be added as long as the instance ID is incremented.
+ */
+ NimBLEExtAdvertisement extAdv(primaryPhy, secondaryPhy);
+
+ /* Set the advertisement as connectable */
+ extAdv.setConnectable(true);
+
+ /* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
+ extAdv.setScannable(false); // The default is false, set here for demonstration.
+
+ /* Extended advertising allows for 251 bytes (minus header bytes ~20) in a single advertisement or up to 1650 if chained */
+ extAdv.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Extended Advertising Demo.\r\n"
+ "Extended advertising allows for "
+ "251 bytes of data in a single advertisement,\r\n"
+ "or up to 1650 bytes with chaining.\r\n"
+ "This example message is 226 bytes long "
+ "and is using CODED_PHY for long range."));
+
+ extAdv.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
+
+ /* When extended advertising is enabled `NimBLEDevice::getAdvertising` returns a pointer to `NimBLEExtAdvertising */
+ NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
+
+ /* Set the callbacks for advertising events */
+ pAdvertising->setCallbacks(new advertisingCallbacks);
+
+ /*
+ * NimBLEExtAdvertising::setInstanceData takes the instance ID and
+ * a reference to a `NimBLEExtAdvertisement` object. This sets the data
+ * that will be advertised for this instance ID, returns true if successful.
+ *
+ * Note: It is safe to create the advertisement as a local variable if setInstanceData
+ * is called before exiting the code block as the data will be copied.
+ */
+ if (pAdvertising->setInstanceData(0, extAdv)) {
+ /*
+ * `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
+ * and a duration in milliseconds or a max number of advertisements to send (or both).
+ */
+ if (pAdvertising->start(0, advTime)) {
+ printf("Started advertising\n");
+ } else {
+ printf("Failed to start advertising\n");
+ }
+ } else {
+ printf("Failed to register advertisment data\n");
+ }
+
+ esp_sleep_enable_timer_wakeup(sleepSeconds * 1000000);
+}
diff --git a/examples/Bluetooth_5/NimBLE_multi_advertiser/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_multi_advertiser/CMakeLists.txt
new file mode 100644
index 0000000..7cfce86
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_multi_advertiser/CMakeLists.txt
@@ -0,0 +1,7 @@
+# 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)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(SUPPORTED_TARGETS esp32c3 esp32s3)
+project(NimBLE_multi_advertiser)
diff --git a/examples/Bluetooth_5/NimBLE_multi_advertiser/Makefile b/examples/Bluetooth_5/NimBLE_multi_advertiser/Makefile
new file mode 100644
index 0000000..501edc9
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_multi_advertiser/Makefile
@@ -0,0 +1,3 @@
+PROJECT_NAME := NimBLE_multi_advertiser
+
+include $(IDF_PATH)/make/project.mk
diff --git a/examples/Bluetooth_5/NimBLE_multi_advertiser/main/CMakeLists.txt b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/CMakeLists.txt
new file mode 100644
index 0000000..0a5a557
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/CMakeLists.txt
@@ -0,0 +1,4 @@
+set(COMPONENT_SRCS "main.cpp")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+register_component()
diff --git a/examples/Bluetooth_5/NimBLE_multi_advertiser/main/component.mk b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/component.mk
new file mode 100644
index 0000000..a98f634
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/component.mk
@@ -0,0 +1,4 @@
+#
+# "main" pseudo-component makefile.
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
diff --git a/examples/Bluetooth_5/NimBLE_multi_advertiser/main/main.cpp b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/main.cpp
new file mode 100644
index 0000000..fbbca34
--- /dev/null
+++ b/examples/Bluetooth_5/NimBLE_multi_advertiser/main/main.cpp
@@ -0,0 +1,170 @@
+/** NimBLE Multi Advertiser Demo:
+ *
+ * Demonstrates the Bluetooth 5.x extended advertising capabilities.
+ *
+ * This demo will advertise 2 advertisements, and extended scannable instance
+ * and a connectable legacy instance. They will advertise for 5 seconds then
+ * sleep for 20 seconds. The extended scannable instance will use the scan
+ * request callback to update it's data when a scan response is requested.
+ *
+ * Created: on April 9 2022
+ * Author: H2zero
+ *
+*/
+
+#include "NimBLEDevice.h"
+#include "esp_sleep.h"
+
+extern "C" void app_main(void);
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+/* Time in milliseconds to advertise */
+static uint32_t advTime = 5000;
+
+/* Time to sleep between advertisements */
+static uint32_t sleepTime = 20;
+
+/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
+static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
+
+/* Secondary PHY used for advertising and connecting,
+ * can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
+ */
+static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
+
+
+/* Handler class for server events */
+class ServerCallbacks: public NimBLEServerCallbacks {
+ void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
+ printf("Client connected: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
+ };
+
+ void onDisconnect(NimBLEServer* pServer) {
+ printf("Client disconnected\n");
+ // if still advertising we won't sleep yet.
+ if (!pServer->getAdvertising()->isAdvertising()) {
+ printf("Sleeping for %u seconds\n", sleepTime);
+ esp_deep_sleep_start();
+ }
+ };
+};
+
+/* Callback class to handle advertising events */
+class advCallbacks: public NimBLEExtAdvertisingCallbacks {
+ void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
+ /* Check the reason advertising stopped, don't sleep if client is connecting */
+ printf("Advertising instance %u stopped\n", inst_id);
+ switch (reason) {
+ case 0:
+ printf(" client connecting\n");
+ return;
+ case BLE_HS_ETIMEOUT:
+ printf("Time expired - sleeping for %u seconds\n", sleepTime);
+ break;
+ default:
+ break;
+ }
+
+ esp_deep_sleep_start();
+ }
+
+ bool m_updatedSR = false;
+
+ void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t inst_id, NimBLEAddress addr) {
+ printf("Scan request for instance %u\n", inst_id);
+ // if the data has already been updated we don't need to change it again.
+ if (!m_updatedSR) {
+ printf("Updating scan data\n");
+ NimBLEExtAdvertisement sr;
+ sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
+ pAdv->setScanResponseData(inst_id, sr);
+ m_updatedSR = true;
+ }
+ }
+};
+
+void app_main (void) {
+ NimBLEDevice::init("Multi advertiser");
+
+ /* Create a server for our legacy advertiser */
+ NimBLEServer *pServer = NimBLEDevice::createServer();
+ pServer->setCallbacks(new ServerCallbacks);
+
+ NimBLEService *pService = pServer->createService(SERVICE_UUID);
+ NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
+ NIMBLE_PROPERTY::READ |
+ NIMBLE_PROPERTY::WRITE |
+ NIMBLE_PROPERTY::NOTIFY);
+
+ pCharacteristic->setValue("Hello World");
+
+ /* Start the service */
+ pService->start();
+
+ /* Create our multi advertising instances */
+
+ // extended scannable instance advertising on coded and 1m PHY's.
+ NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
+
+ // Legacy advertising as a connectable device.
+ NimBLEExtAdvertisement legacyConnectable;
+
+ // Optional scan response data.
+ NimBLEExtAdvertisement legacyScanResponse;
+
+ /* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
+ extScannable.setScannable(true);
+ extScannable.setConnectable(false);
+
+ /* Set the initial data */
+ extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
+
+ /* enable the scan response callback, we will use this to update the data. */
+ extScannable.enableScanRequestCallback(true);
+
+ /* Optional custom address for this advertisment. */
+ legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD"));
+
+ /* Set the advertising data. */
+ legacyConnectable.setName("Legacy");
+ legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
+
+ /* Set the legacy and connectable flags. */
+ legacyConnectable.setLegacyAdvertising(true);
+ legacyConnectable.setConnectable(true);
+
+ /* Put some data in the scan response if desired. */
+ legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
+
+ /* Get the advertising ready */
+ NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
+
+ /* Set the callbacks to handle advertising events */
+ pAdvertising->setCallbacks(new advCallbacks);
+
+ /* Set instance data.
+ * Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
+ *
+ * We will set the extended scannable data on instance 0 and the legacy data on instance 1.
+ * Note that the legacy scan response data needs to be set to the same instance (1).
+ */
+ if (pAdvertising->setInstanceData( 0, extScannable ) &&
+ pAdvertising->setInstanceData( 1, legacyConnectable ) &&
+ pAdvertising->setScanResponseData( 1, legacyScanResponse )) {
+ /*
+ * `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
+ * and a duration in milliseconds or a max number of advertisements to send (or both).
+ */
+ if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
+ printf("Started advertising\n");
+ } else {
+ printf("Failed to start advertising\n");
+ }
+ } else {
+ printf("Failed to register advertisment data\n");
+ }
+
+ esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
+}
diff --git a/src/HIDTypes.h b/src/HIDTypes.h
index 726b84b..8ee31da 100644
--- a/src/HIDTypes.h
+++ b/src/HIDTypes.h
@@ -45,13 +45,8 @@
/* of data as per HID Class standard */
/* Main items */
-#ifdef ARDUINO_ARCH_ESP32
-#define HIDINPUT(size) (0x80 | size)
-#define HIDOUTPUT(size) (0x90 | size)
-#else
-#define INPUT(size) (0x80 | size)
-#define OUTPUT(size) (0x90 | size)
-#endif
+#define HIDINPUT(size) (0x80 | size)
+#define HIDOUTPUT(size) (0x90 | size)
#define FEATURE(size) (0xb0 | size)
#define COLLECTION(size) (0xa0 | size)
#define END_COLLECTION(size) (0xc0 | size)
diff --git a/src/NimBLE2904.cpp b/src/NimBLE2904.cpp
index 80318b5..282eff5 100644
--- a/src/NimBLE2904.cpp
+++ b/src/NimBLE2904.cpp
@@ -16,11 +16,8 @@
* See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
#include "nimconfig.h"
-#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
+#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLE2904.h"
@@ -86,5 +83,4 @@ void NimBLE2904::setUnit(uint16_t unit) {
setValue((uint8_t*) &m_data, sizeof(m_data));
} // setUnit
-#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
-#endif
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
diff --git a/src/NimBLE2904.h b/src/NimBLE2904.h
index d8800dd..29dde51 100644
--- a/src/NimBLE2904.h
+++ b/src/NimBLE2904.h
@@ -14,11 +14,8 @@
#ifndef MAIN_NIMBLE2904_H_
#define MAIN_NIMBLE2904_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
#include "nimconfig.h"
-#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
+#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDescriptor.h"
@@ -82,6 +79,5 @@ private:
BLE2904_Data m_data;
}; // BLE2904
-#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
-#endif /* CONFIG_BT_ENABLED */
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* MAIN_NIMBLE2904_H_ */
diff --git a/src/NimBLEAddress.cpp b/src/NimBLEAddress.cpp
index e1d3e54..b8df5ac 100644
--- a/src/NimBLEAddress.cpp
+++ b/src/NimBLEAddress.cpp
@@ -11,7 +11,7 @@
* Created on: Jul 2, 2017
* Author: kolban
*/
-#include "sdkconfig.h"
+#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include
diff --git a/src/NimBLEAddress.h b/src/NimBLEAddress.h
index 50f9231..a6e10a0 100644
--- a/src/NimBLEAddress.h
+++ b/src/NimBLEAddress.h
@@ -14,10 +14,15 @@
#ifndef COMPONENTS_NIMBLEADDRESS_H_
#define COMPONENTS_NIMBLEADDRESS_H_
-#include "sdkconfig.h"
+#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
+#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "nimble/ble.h"
+#else
+#include "nimble/nimble/include/nimble/ble.h"
+#endif
+
/**** FIX COMPILATION ****/
#undef min
#undef max
diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp
index ecfd498..29c9532 100644
--- a/src/NimBLEAdvertisedDevice.cpp
+++ b/src/NimBLEAdvertisedDevice.cpp
@@ -11,17 +11,17 @@
* Created on: Jul 3, 2017
* Author: kolban
*/
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h"
-#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
+#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEDevice.h"
#include "NimBLEAdvertisedDevice.h"
#include "NimBLEUtils.h"
#include "NimBLELog.h"
+#include
+
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
@@ -71,7 +71,7 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
* @return The appearance of the advertised device.
*/
uint16_t NimBLEAdvertisedDevice::getAppearance() {
- uint8_t data_loc = 0;
+ size_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];
@@ -89,7 +89,7 @@ uint16_t NimBLEAdvertisedDevice::getAppearance() {
* @return The advertisement interval in 0.625ms units.
*/
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
- uint8_t data_loc = 0;
+ size_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];
@@ -107,7 +107,7 @@ uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
* @return The preferred min connection interval in 1.25ms units.
*/
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
- uint8_t data_loc = 0;
+ size_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];
@@ -125,7 +125,7 @@ uint16_t NimBLEAdvertisedDevice::getMinInterval() {
* @return The preferred max connection interval in 1.25ms units.
*/
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
- uint8_t data_loc = 0;
+ size_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];
@@ -143,7 +143,7 @@ uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
* @return The manufacturer data of the advertised device.
*/
std::string NimBLEAdvertisedDevice::getManufacturerData() {
- uint8_t data_loc = 0;
+ size_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];
@@ -161,7 +161,7 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() {
* @return The URI data.
*/
std::string NimBLEAdvertisedDevice::getURI() {
- uint8_t data_loc = 0;
+ size_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];
@@ -179,7 +179,7 @@ std::string NimBLEAdvertisedDevice::getURI() {
* @return The name of the advertised device.
*/
std::string NimBLEAdvertisedDevice::getName() {
- uint8_t data_loc = 0;
+ size_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)
@@ -216,7 +216,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
* @brief Get the number of target addresses.
* @return The number of addresses.
*/
-size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
+uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() {
uint8_t count = 0;
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
@@ -234,7 +234,7 @@ size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t count = 0;
- uint8_t data_loc = 0xFF;
+ size_t data_loc = ULONG_MAX;
index++;
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
@@ -244,7 +244,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
}
- if(count > 0 && data_loc != 0xFF) {
+ if(count > 0 && data_loc != ULONG_MAX) {
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;
@@ -266,9 +266,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t bytes;
- uint8_t data_loc = findServiceData(index, &bytes);
+ size_t data_loc = findServiceData(index, &bytes);
- if(data_loc != 0xFF) {
+ if(data_loc != ULONG_MAX) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length > bytes) {
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
@@ -288,9 +288,9 @@ 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);
+ size_t data_loc = findServiceData(index, &bytes);
+ size_t plSize = m_payload.size() - 2;
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];
@@ -315,9 +315,9 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t bytes;
- uint8_t data_loc = findServiceData(index, &bytes);
+ size_t data_loc = findServiceData(index, &bytes);
- if(data_loc != 0xFF) {
+ if(data_loc != ULONG_MAX) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length >= bytes) {
return NimBLEUUID(field->value, bytes, false);
@@ -332,10 +332,10 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
* @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.
+ * @return The index in the vector where the data is located, ULONG_MAX if not found.
*/
-uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
- uint8_t data_loc = 0;
+size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
+ size_t data_loc = 0;
uint8_t found = 0;
*bytes = 0;
@@ -360,7 +360,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
return data_loc;
}
- return 0xFF;
+ return ULONG_MAX;
}
@@ -368,7 +368,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
* @brief Get the count of advertised service data UUIDS
* @return The number of service data UUIDS in the vector.
*/
-size_t NimBLEAdvertisedDevice::getServiceDataCount() {
+uint8_t NimBLEAdvertisedDevice::getServiceDataCount() {
uint8_t count = 0;
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
@@ -386,7 +386,7 @@ size_t NimBLEAdvertisedDevice::getServiceDataCount() {
*/
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
uint8_t count = 0;
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
uint8_t uuidBytes = 0;
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
ble_hs_adv_field *field = nullptr;
@@ -433,7 +433,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
* @brief Get the number of services advertised
* @return The count of services in the advertising packet.
*/
-size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
+uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
uint8_t count = 0;
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
@@ -469,7 +469,7 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
* @return The TX Power of the advertised device.
*/
int8_t NimBLEAdvertisedDevice::getTXPower() {
- uint8_t data_loc = 0;
+ size_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];
@@ -583,17 +583,60 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
} // haveTXPower
-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 CONFIG_BT_NIMBLE_EXT_ADV
+/**
+ * @brief Get the set ID of the extended advertisement.
+ * @return The set ID.
+ */
+uint8_t NimBLEAdvertisedDevice::getSetId() {
+ return m_sid;
+} // getSetId
- if(length < 2) {
+
+/**
+ * @brief Get the primary PHY used by this advertisement.
+ * @return The PHY type, one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+uint8_t NimBLEAdvertisedDevice::getPrimaryPhy() {
+ return m_primPhy;
+} // getPrimaryPhy
+
+
+/**
+ * @brief Get the primary PHY used by this advertisement.
+ * @return The PHY type, one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_2M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() {
+ return m_secPhy;
+} // getSecondaryPhy
+
+
+/**
+ * @brief Get the periodic interval of the advertisement.
+ * @return The periodic advertising interval, 0 if not periodic advertising.
+ */
+uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() {
+ return m_periodicItvl;
+} // getPeriodicInterval
+#endif
+
+
+uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t * data_loc) {
+ ble_hs_adv_field *field = nullptr;
+ size_t length = m_payload.size();
+ size_t data = 0;
+ uint8_t count = 0;
+
+ if (length < 3) {
return count;
}
- while (length > 1) {
+ while (length > 2) {
field = (ble_hs_adv_field*)&m_payload[data];
if (field->length >= length) {
@@ -601,7 +644,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
}
if (field->type == type) {
- switch(type) {
+ switch (type) {
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
count += field->length / 2;
@@ -627,8 +670,8 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
break;
}
- if(data_loc != nullptr) {
- if(index == 0 || count >= index) {
+ if (data_loc != nullptr) {
+ if (index == 0 || count >= index) {
break;
}
}
@@ -638,7 +681,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
data += 1 + field->length;
}
- if(data_loc != nullptr && field != nullptr) {
+ if (data_loc != nullptr && field != nullptr) {
*data_loc = data;
}
@@ -659,8 +702,13 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
* @brief Set the adFlag for this device.
* @param [in] advType The advertisement flag data from the advertisement.
*/
-void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
+void NimBLEAdvertisedDevice::setAdvType(uint8_t advType, bool isLegacyAdv) {
m_advType = advType;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ m_isLegacyAdv = isLegacyAdv;
+#else
+ (void)isLegacyAdv;
+#endif
} // setAdvType
@@ -705,10 +753,10 @@ std::string NimBLEAdvertisedDevice::toString() {
res += val;
}
- if(haveServiceData()) {
- size_t count = getServiceDataCount();
+ if (haveServiceData()) {
+ uint8_t count = getServiceDataCount();
res += "\nService Data:";
- for(size_t i = 0; i < count; i++) {
+ for(uint8_t i = 0; i < count; i++) {
res += "\nUUID: " + std::string(getServiceDataUUID(i));
res += ", Data: " + getServiceData(i);
}
@@ -784,6 +832,33 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
} // getPayloadLength
-#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
-#endif /* CONFIG_BT_ENABLED */
+/**
+ * @brief Check if this device is advertising as connectable.
+ * @return True if the device is connectable.
+ */
+bool NimBLEAdvertisedDevice::isConnectable() {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ if (m_isLegacyAdv) {
+ return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND ||
+ m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
+ }
+#endif
+ return (m_advType & BLE_HCI_ADV_CONN_MASK) ||
+ (m_advType & BLE_HCI_ADV_DIRECT_MASK);
+} // isConnectable
+
+
+/**
+ * @brief Check if this advertisement is a legacy or extended type
+ * @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
+ */
+bool NimBLEAdvertisedDevice::isLegacyAdvertisement() {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ return m_isLegacyAdv;
+# else
+ return true;
+#endif
+} // isLegacyAdvertisement
+
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h
index 7d378ed..772bab9 100644
--- a/src/NimBLEAdvertisedDevice.h
+++ b/src/NimBLEAdvertisedDevice.h
@@ -14,20 +14,22 @@
#ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
#define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
-#include "sdkconfig.h"
-#if defined(CONFIG_BT_ENABLED)
-
#include "nimconfig.h"
-#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
+#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAddress.h"
#include "NimBLEScan.h"
#include "NimBLEUUID.h"
+#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_hs_adv.h"
+#else
+#include "nimble/nimble/host/include/host/ble_hs_adv.h"
+#endif
#include