diff --git a/API_DIFFERENCES.md b/API_DIFFERENCES.md deleted file mode 100644 index 91b0fd7..0000000 --- a/API_DIFFERENCES.md +++ /dev/null @@ -1,245 +0,0 @@ -# Server API differnces: - -### Characteristics: -When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`. - -#### Previous: -``` -BLECharacteristic::PROPERTY_READ | -BLECharacteristic::PROPERTY_WRITE -``` - -#### Changed to: -``` -NIMBLE_PROPERTY::READ | -NIMBLE_PROPERTY::WRITE -``` - -#### The full list of properties: -``` -NIMBLE_PROPERTY::READ -NIMBLE_PROPERTY::READ_ENC -NIMBLE_PROPERTY::READ_AUTHEN -NIMBLE_PROPERTY::READ_AUTHOR -NIMBLE_PROPERTY::WRITE -NIMBLE_PROPERTY::WRITE_NR -NIMBLE_PROPERTY::WRITE_ENC -NIMBLE_PROPERTY::WRITE_AUTHEN -NIMBLE_PROPERTY::WRITE_AUTHOR -NIMBLE_PROPERTY::BROADCAST -NIMBLE_PROPERTY::NOTIFY -NIMBLE_PROPERTY::INDICATE -``` - -### Descriptors: -Descriptors are now created using the NimBLEcharacteristic method `createDescriptor()`. - -The previous method `addDescriptor()` is now a private function in the library. - -This was done because the NimBLE host automatically creates a 0x2902 descriptor if a characteristic has notify or indicate properties applied. -Due to this fact, this library also creates one automatically for your application. -The only reason to manually create this descriptor now is to assign callback functions. -If you do not require this functionality you can safely exclude the manual creation of that descriptor. - - -For any other descriptor, (except 0x2904, see below) it should now be created just as characteristics are -by invoking the `NimBLECharacteristic::createDescriptor` methods. -Which are defined as: -``` -NimBLEDescriptor* createDescriptor(const char* uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, - uint16_t max_len = 100); - -NimBLEDescriptor* createDescriptor(NimBLEUUID uuid, - uint32_t properties = NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE, - uint16_t max_len = 100); -``` -##### Example: -``` -pDescriptor = pCharacteristic->createDescriptor("ABCD", - NIMBLE_PROPERTY::READ | - NIMBLE_PROPERTY::WRITE | - NIMBLE_PROPERTY::WRITE_ENC, - 25);` -``` -Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes. - -For the 0x2904 descriptor, there is a special class that is created when you call `createDescriptor("2904")`. - -The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to `NimBLE2904*` to access the specific class methods. - -##### Example: -``` -p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904"); -``` - -#### Server Security: -Security is set on the characteristic or descriptor properties by applying one of the following: -``` -NIMBLE_PROPERTY::READ_ENC -NIMBLE_PROPERTY::READ_AUTHEN -NIMBLE_PROPERTY::READ_AUTHOR -NIMBLE_PROPERTY::WRITE_ENC -NIMBLE_PROPERTY::WRITE_AUTHEN -NIMBLE_PROPERTY::WRITE_AUTHOR -``` -When a peer wants to read or write a characteristic or descriptor with any of these properties applied -it will trigger the pairing process. By default the "just-works" pairing will be performed automatically. -This can be changed to use passkey authentication or numeric confirmation. See below for details. - - -# Client API Differences: -The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a pointer to the -`NimBLEAdvertisedDevice` object instead of a copy. - -`NimBLEClient::connect()` now takes an extra parameter to indicate if the client should download the services - database from the peripheral, default value is true. - -Defined as: -``` -bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true); -bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true); -``` -If set to false the client will use the services database it retrieved from the peripheral last time it connected. -This allows for faster connections and power saving if the devices just dropped connection and want to reconnect. - -``` -NimBLERemoteCharacteristic::writeValue(); -NimBLERemoteCharacteristic::registerForNotify(); -``` -Now return true or false to indicate success or failure so you can choose to disconnect or try again. - -``` -NimBLEClient::getServices() -NimBLERemoteService::getCharacteristics() -``` -Now return a pointer to a `std::vector` of the respective object database instead of `std::map`. - -`NimBLERemoteService::getCharacteristicsByHandle()` -Has been removed from the API as it is no longer maintained in the library. - -The last two above changes reduce the heap usage significantly with minimal application code adjustments. - -**UPDATED** on June 21, 2020 -> ``` -> NimBLEClient::getServices(bool refresh = false) -> NimBLERemoteService::getCharacteristics(bool refresh = false) -> NimBLERemoteCharacteristic::getDecriptors(bool refresh = false) ->``` -These methods now take an optional (bool) parameter. -If true it will clear the respective vector and retrieve all the respective attributes from the peripheral. -If false(default) it will return the respective vector empty or otherwise with the currently stored attributes. - -**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data -the user may not be interested in. - -**Added:** `NimBLEClient::discoverAtrributes()` for the user to discover all the peripheral attributes -to replace the the former functionality. - - -> ``` ->getService(NimBLEUUID) ->getCharacteristic(NimBLEUUID) ->getDescriptor(NimBLEUUID) ->``` -These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only) -the specified attribute from the peripheral. - -These changes allow more control for the user to manage the resources used for the attributes. -*** -#### Client Security: -The client will automatically initiate security when the peripheral responds that it's required. -The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below. - - -# Security: -Security callback functions are now incorporated in the client/server Callbacks class. -However backward compatibility with the `BLESecurity` class is retained to minimize app code changes. - -The relevant server callbacks are defined as: -``` -bool onConfirmPIN(uint32_t pin); // accept or reject the passkey -void onAuthenticationComplete(ble_gap_conn_desc* desc); // auth complete - details in desc -bool onPassKeyNotify(uint32_t pass_key); // receive the passkey sent by the client, accept or reject -``` -The relevant client callbacks are defined as: -``` -bool onConfirmPIN(uint32_t pin); // accept or reject the passkey -void onAuthenticationComplete(ble_gap_conn_desc* desc); // auth complete - details in desc -uint32_t onPassKeyRequest(); // return the passkey to send to the server -``` - -Security settings and IO capabilities are now set by the corresponding method of `NimBLEDevice::`. -``` -static void setSecurityAuth(bool bonding, bool mitm, bool sc); -static void setSecurityAuth(uint8_t auth_req); -static void setSecurityIOCap(uint8_t iocap); -static void setSecurityInitKey(uint8_t init_key); -static void setSecurityRespKey(uint8_t init_key); - - -/** - * @brief Set the authorization mode for this device. - * @param bonding, if true we allow bonding, false no bonding will be performed. - * @param mitm, if true we are capable of man in the middle protection, false if not. - * @param sc, if true we will perform secure connection pairing, false we will use legacy pairing. - */ -void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) - - - -/** - * @brief Set the authorization mode for this device. - * @param A bitmap indicating what modes are supported. - * The bits are defined as follows: - ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND - ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM - ** 0x08 BLE_SM_PAIR_AUTHREQ_SC - ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. - ** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only. - */ -void NimBLEDevice::setSecurityAuth(uint8_t auth_req) - - - -/** - * @brief Set the Input/Output capabilities of this device. - * @param One of the following: - ** 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability - ** 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability - ** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability - ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability - ** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability - */ -void NimBLEDevice::setSecurityIOCap(uint8_t iocap) - - - -/** - * @brief If we are the initiator of the security procedure this sets the keys we will distribute. - * @param A bitmap indicating which keys to distribute during pairing. - * The bits are defined as follows: - ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key. - ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK). - ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK - */ -void NimBLEDevice::setSecurityInitKey(uint8_t init_key) - - -/** - * @brief Set the keys we are willing to accept during pairing. - * @param A bitmap indicating which keys to accept during pairing. - * The bits are defined as follows: - ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key. - ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK). - ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK - */ -void NimBLEDevice::setSecurityRespKey(uint8_t init_key) -``` - - I'm sure there are more things I have forgotten but this is all the majors. - I will update this document as necessary. diff --git a/README.md b/README.md index f914937..7c44cc7 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,63 @@ -# *** UPDATES *** -**Breaking changes:** -**NEW** on June 21, 2020 -> ``` -> NimBLEClient::getServices(bool refresh = false) -> NimBLERemoteService::getCharacteristics(bool refresh = false) -> NimBLERemoteCharacteristic::getDecriptors(bool refresh = false) ->``` -These methods now take an optional (bool) parameter. -If true it will clear the respective vector and retrieve all the respective attributes from the peripheral. -If false(default) it will return the respective vector empty or otherwise with the currently stored attributes. - -**NEW** on May 23, 2020 -Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database. - -This change will affect your application code if you use `NimBLEClient::getServices()` or `NimBLERemoteService::getCharacteristics()` -in your application as they now return a pointer to `std::vector` of the respective attributes. - -In addition `NimBLERemoteService::getCharacteristicsByHandle()` has been removed as it is no longer maintained in the library. - -These changes were necessary due to the amount of resources required to use `std::map`, it was not justifed by any benfit it provided. - -It is expected that there will be minimal impact on most applications, if you need help adjusting your code please create an issue. - # esp-nimble-cpp -NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the @nkolban cpp_uitls API. + +NimBLE CPP library for use with ESP32 that attempts to maintain compatibility with the [nkolban cpp_uitls BLE API](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils). + +**An Arduino version of this library, including NimBLE, can be [found here.](https://github.com/h2zero/NimBLE-Arduino)** This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original library but refactored to use the NimBLE stack. In addition, this library will be more actively developed and maintained to provide improved capabilites and stability over the original. -**Testing shows a nearly 50% reduction in flash use and approx. 100kB less ram consumed vs the original!** +**Testing shows a nearly 50% reduction in flash use and approx. 100kB less ram consumed vs the original!** +*Your results may vary* +
- -# Installation: +### What is NimBLE? +NimBLE is a completely open source Bluetooth Low Energy stack produced by [Apache](https://github.com/apache/mynewt-nimble). +It is more suited to resource constrained devices than bluedroid and has now been ported to the ESP32 by Espressif. +
-Download as .zip and extract to components folder in your esp-idf project. +# Installation -Run menuconfig, go to `Component config->Bluetooth->` enable Bluetooth and select NimBLE host. +### ESP-IDF v4.0+ +Download as .zip and extract or clone into the components folder in your esp-idf project. -`#include "NimBLEDevice.h"` in main.cpp. +Run menuconfig, go to `Component config->Bluetooth` enable Bluetooth and in `Bluetooth host` NimBLE. +Configure settings in `NimBLE Options`. +`#include "NimBLEDevice.h"` in main.cpp. +Call `NimBLEDevice::init("");` in `app_main`. +
+### ESP-IDF v3.2 & v3.3 +The NimBLE component does not come with these versions of IDF. +A backport that works in these versions has been created and is [available here](https://github.com/h2zero/esp-nimble-component). +Download or clone that repo into your project/components folder and run menuconfig. +Configure settings in `main menu -> NimBLE Options`. -# Usage: +`#include "NimBLEDevice.h"` in main.cpp. +Call `NimBLEDevice::init("");` in `app_main`. +
+# Using This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes. -Check [API_DIFFERENCES](https://github.com/h2zero/esp-nimble-cpp/blob/master/API_DIFFERENCES.md) for details. +See: [Breaking API Changes vs Original](docs/BREAKING_API_CHANGES.md) for details. +Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes. +
-# Acknowledgments: +# Acknowledgments +* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from. +* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples. +* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code. +
-* @nkolban and @chegewara for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets) this project was derived from. -* @beegee-tokyo for contributing your time to test/debug and contributing the beacon examples. -* @Jeroen88 for the amazing help debugging and improving the client code. +# Todo +1. Implement random addresses. +2. Implement NimBLEServer::removeService +3. Implement extra fields in NimBLEAdvertisedDevice. +4. Document nimconfig. +5. Add BLE Mesh code. +
-# Todo: - -1. Create documentation. -2. Add BLE Mesh code. -3. Expose more NimBLE features. \ No newline at end of file diff --git a/docs/BREAKING_API_CHANGES.md b/docs/BREAKING_API_CHANGES.md new file mode 100644 index 0000000..70bd97b --- /dev/null +++ b/docs/BREAKING_API_CHANGES.md @@ -0,0 +1,222 @@ +# Breaking API Changes vs Original +
+ +# Server API differnces + +### Characteristics +When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`. + +#### Originally +> BLECharacteristic::PROPERTY_READ | +> BLECharacteristic::PROPERTY_WRITE + +#### Is Now +> NIMBLE_PROPERTY::READ | +> NIMBLE_PROPERTY::WRITE +
+ +#### The full list of properties +> NIMBLE_PROPERTY::READ +> NIMBLE_PROPERTY::READ_ENC +> NIMBLE_PROPERTY::READ_AUTHEN +> NIMBLE_PROPERTY::READ_AUTHOR +> NIMBLE_PROPERTY::WRITE +> NIMBLE_PROPERTY::WRITE_NR +> NIMBLE_PROPERTY::WRITE_ENC +> NIMBLE_PROPERTY::WRITE_AUTHEN +> NIMBLE_PROPERTY::WRITE_AUTHOR +> NIMBLE_PROPERTY::BROADCAST +> NIMBLE_PROPERTY::NOTIFY +> NIMBLE_PROPERTY::INDICATE +
+ +### Descriptors +Descriptors are now created using the `NimBLECharacteristic::createDescriptor()` method. + +The previous method `BLECharacteristic::addDescriptor()` is now a private function in the library. + +This was done because the NimBLE host automatically creates a 0x2902 descriptor if a characteristic has NOTIFY or INDICATE properties applied. +Due to this fact, the library also creates one automatically for your application. +The only reason to manually create this descriptor now is to assign callback functions. +If you do not require this functionality you can safely exclude the manual creation of the 0x2902 descriptor. + +For any other descriptor, (except 0x2904, see below) it should now be created just as characteristics are +by using the `NimBLECharacteristic::createDescriptor` method. +Which are defined as: +``` +NimBLEDescriptor* createDescriptor(const char* uuid, + uint32_t properties = + NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, + uint16_t max_len = 100); + +NimBLEDescriptor* createDescriptor(NimBLEUUID uuid, + uint32_t properties = + NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE, + uint16_t max_len = 100); +``` +##### Example +``` +pDescriptor = pCharacteristic->createDescriptor("ABCD", + NIMBLE_PROPERTY::READ | + NIMBLE_PROPERTY::WRITE | + NIMBLE_PROPERTY::WRITE_ENC, + 25); +``` +Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes. +
+ +For the 0x2904 and 0x2902 descriptor, there is a special class that is created when you call `createDescriptor("2904")`or `createDescriptor("2902")`. + +The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` or `NimBLE2902` so you must cast the returned pointer to +`NimBLE2904` or `NimBLE2902` to access the specific class methods. + +##### Example +``` +p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904"); +p2902 = (NimBLE2902*)pCharacteristic->createDescriptor("2902"); +``` +
+ +### Server Security +Security is set on the characteristic or descriptor properties by applying one of the following: +> NIMBLE_PROPERTY::READ_ENC +> NIMBLE_PROPERTY::READ_AUTHEN +> NIMBLE_PROPERTY::READ_AUTHOR +> NIMBLE_PROPERTY::WRITE_ENC +> NIMBLE_PROPERTY::WRITE_AUTHEN +> NIMBLE_PROPERTY::WRITE_AUTHOR + +When a peer wants to read or write a characteristic or descriptor with any of these properties applied +it will trigger the pairing process. By default the "just-works" pairing will be performed automatically. +This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details. + +
+ +# Client API Differences +The `NimBLEAdvertisedDeviceCallbacks::onResult()` method now receives a pointer to the +`NimBLEAdvertisedDevice` object instead of a copy. + +`NimBLEClient::connect()` now takes an extra parameter to indicate if the client should download the services + database from the peripheral, default value is true. + +Defined as: +> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool refreshServices = true); +> NimBLEClient::connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true); + +If set to false the client will use the services database it retrieved from the peripheral last time it connected. +This allows for faster connections and power saving if the devices just dropped connection and want to reconnect. +
+ +> NimBLERemoteCharacteristic::writeValue(); +> NimBLERemoteCharacteristic::registerForNotify(); + +Now return true or false to indicate success or failure so you can choose to disconnect or try again. +
+ +> NimBLERemoteCharacteristic::registerForNotify(); +Is now **deprecated**. +> NimBLERemoteCharacteristic::subscribe() +> NimBLERemoteCharacteristic::unsubscribe() + +Are the new methods added to replace it. +
+ +> NimBLERemoteCharacteristic::readUInt8() +> NimBLERemoteCharacteristic::readUInt16() +> NimBLERemoteCharacteristic::readUInt32() +> NimBLERemoteCharacteristic::readFloat() + +Are **deprecated** and NimBLERemoteCharacteristic::readValue(time_t\*, bool) template added to replace them. +
+ +> NimBLERemoteService::getCharacteristicsByHandle() + +Has been removed from the API as it is no longer maintained in the library. +
+ +> NimBLERemoteCharacteristic::readRawData() + +Has been removed from the API as it stored an unnecessary copy of the data. +The user application should use NimBLERemoteCharacteristic::readValue or NimBLERemoteCharacteristic::getValue. +Then cast the returned std::string to the type they wish such as: +``` +uint8_t *val = (uint8_t*)pChr->readValue().data(); +``` +
+ +> NimBLEClient::getServices(bool refresh = false) +> NimBLERemoteCharacteristic::getDescriptors(bool refresh = false) +> NimBLERemoteService::getCharacteristics(bool refresh = false) + +These methods now take an optional (bool) parameter and return a pointer to `std::vector` instead of `std::map`. +If passed true it will clear the respective vector and retrieve all the respective attributes from the peripheral. +If false(default) it will return the respective vector with the currently stored attributes. + +**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data +the user may not be interested in. + +**Added:** NimBLEClient::discoverAttributes() for the user to discover all the peripheral attributes +to replace the the removed functionality. +
+ +> NimBLEClient::getService() +> NimBLERemoteService::getCharacteristic() +> NimBLERemoteCharacteristic::getDescriptor() + +These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only) +the specified attribute from the peripheral. + +These changes allow more control for the user to manage the resources used for the attributes. +
+ +### Client Security +The client will automatically initiate security when the peripheral responds that it's required. +The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below. +
+ +# Security Differences +Security callback functions are now incorporated in the NimBLEServerCallbacks / NimBLEClientCallbacks classes. +However backward compatibility with the original `BLESecurity` class is retained to minimize app code changes. + +The callback methods are: + +> bool onConfirmPIN(uint32_t pin); + +Receives the pin when using numeric comparison authentication, `return true;` to accept. +
+ +> uint32_t onPassKeyRequest(); + +For server callback; return the passkey expected from the client. +For client callback; return the passkey to send to the server. +
+ +> void onAuthenticationComplete(ble_gap_conn_desc\* desc); + +Authentication complete, success or failed information is in `desc`. +
+ +Security settings and IO capabilities are now set by the following methods of NimBLEDevice. +> NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) +> NimBLEDevice::setSecurityAuth(uint8_t auth_req) + +Sets the authorization mode for this device. +
+ +> NimBLEDevice::setSecurityIOCap(uint8_t iocap) + +Sets the Input/Output capabilities of this device. +
+ +> NimBLEDevice::setSecurityInitKey(uint8_t init_key) + +If we are the initiator of the security procedure this sets the keys we will distribute. +
+ +> NimBLEDevice::setSecurityRespKey(uint8_t resp_key) + +Sets the keys we are willing to accept from the peer during pairing. +
+ diff --git a/docs/Improvements_and_updates.md b/docs/Improvements_and_updates.md new file mode 100644 index 0000000..4b0d345 --- /dev/null +++ b/docs/Improvements_and_updates.md @@ -0,0 +1,99 @@ +# Improvements and updates + +# Server + +NimBLECharacteristic::setValue(const T &s) +NimBLEDescriptor::setValue(const T &s) + +Now use a template to accomodate standard and custom types/values. + +**Example** +``` +struct my_struct{ + uint8_t one; + uint16_t two; + uint32_t four; + uint64_t eight; + float flt; +}myStruct; + + myStruct.one = 1; + myStruct.two = 2; + myStruct.four = 4; + myStruct.eight = 8; + myStruct.flt = 1234.56; + + pCharacteristic->setValue(myStruct); + ``` +This will send the struct to the recieving client when read or a notification sent. + +NimBLECharacteristic::getValue now takes an optional timestamp parameter which will update it's value with +the time the last value was recieved. In addition an overloaded template has been added to retrieve the value +as a type specified by the user. + +**Example** +``` + time_t timestamp; + myStruct = pCharacteristic->getValue(×tamp); // timestamp optional +``` +
+ +**Advertising will automatically start when a client disconnects.** + +A new method `NimBLEServer::advertiseOnDisconnect(bool)` has been implemented to control this, true(default) = enabled. +
+ +# Client + +NimBLERemoteCharacteristic::readValue(time_t\*, bool) +NimBLERemoteDescriptor::readValue(bool) + +Have been added as templates to allow reading the values as any specified type. + +**Example** +``` +struct my_struct{ + uint8_t one; + uint16_t two; + uint32_t four; + uint64_t eight; + float flt; +}myStruct; + + time_t timestamp; + myStruct = pRemoteCharacteristic->readValue(×tamp); // timestamp optional +``` +
+ +NimBLERemoteCharacteristic::registerForNotify +Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is recieved. + +NimBLERemoteCharacteristic::subscribe and NimBLERemoteCharacteristic::unsubscribe have been implemented to replace it. +A callback is no longer requred to get the most recent value unless timing is important. Instead, the application can call NimBLERemoteCharacteristic::getValue to +get the last updated value any time. + +In addition NimBLERemoteCharacteristic::readValue and NimBLERemoteCharacteristic::getValue take an optional timestamp parameter which will update it's value with +the time the last value was recieved. + +NimBLEClient::getService will now retrieve only the service specified and not the full database, this preserves resources +otherwise wasted retrieving and allocating attributes the user application is not interested in. +
+ +# General +To reduce resource use all instances of std::map have been replaced with std::vector. + +Use of FreeRTOS::Semaphore has been removed as it was consuming too much ram, the related files have been left in place to accomodate application use. + +Operators `==`, `!=` and `std::string` have been added to NimBLEAddress and NimBLEUUID for easier comparison and logging. + +New constructor for NimBLEUUID(uint32_t, uint16_t, uint16_t, uint64_t) added to lower memory use vs string construction. See: [#21](https://github.com/h2zero/NimBLE-Arduino/pull/21). + +Security/pairing operations are now handled in the respective NimBLEClientCallbacks and NimBLEServerCallbacks classes, NimBLESecurity(deprecated) remains for backward compatibility. + +Configuration options have been added to add or remove debugging information, when disabled (default) significatly reduces binary size. +In ESP-IDF the options are in menuconfig: `Main menu -> ESP-NimBLE-cpp configuration`. +For Arduino the options must be commented / uncommented in nimconfig.h. + +Many more internal improvements have been made as well, this is a brief overview. Refer to the class docs for futher information on class specifics. +
+ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..cebcbe0 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,67 @@ +# Overview + +This is a C++ BLE library for the ESP32 that uses the NimBLE host stack instead of bluedroid. +The aim is to maintain, as much as reasonable, the original bluedroid C++ API while adding new features +and making improvements in performance, resource use and stability. + +**Testing shows a nearly 50% reduction in flash use and approx. 100kB less ram consumed vs the original!** +*Your results may vary* +
+ +### What is NimBLE? +NimBLE is a completely open source Bluetooth Low Energy stack produced by [Apache](https://github.com/apache/mynewt-nimble). +It is more suited to resource constrained devices than bluedroid and has now been ported to the ESP32 by Espressif. +
+ +# Arduino Installation +Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library. + +`#include "NimBLEDevice.h"` at the beginning of your sketch. + +Tested and working with esp32-arduino v1.0.2 and 1.0.4 in Arduino IDE v1.8.12 and platform IO. +
+ +# ESP-IDF Installation +### v4.0+ +Download as .zip and extract or clone into the components folder in your esp-idf project. + +Run menuconfig, go to `Component config->Bluetooth` enable Bluetooth and in `Bluetooth host` NimBLE. +Configure settings in `NimBLE Options`. +`#include "NimBLEDevice.h"` in main.cpp. +Call `NimBLEDevice::init("");` in `app_main`. +
+ +### v3.2 & v3.3 +The NimBLE component does not come with these versions of IDF. +A backport that works in these versions has been created and is [available here](https://github.com/h2zero/esp-nimble-component). +Download or clone that repo into your project/components folder and run menuconfig. +Configure settings in `main menu -> NimBLE Options`. + +`#include "NimBLEDevice.h"` in main.cpp. +Call `NimBLEDevice::init("");` in `app_main`. +
+ +# Using +This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes. + +See: [Breaking API Changes vs Original](docs/BREAKING_API_CHANGES.md) for details. + +Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes. + +### Arduino +    See the Refactored_original_examples in the examples folder for highlights of the differences with the original library. + +    More advanced examples highlighting many available features are in examples/NimBLE_Server, NimBLE_Client. + +    Beacon examples provided by [beegee-tokyo](https://github.com/beegee-tokyo) are in examples/BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon. + +    Change the settings in the nimconfig.h file to customize NimBLE to your project, such as increasing max connections (default == 3). +
+ +# Acknowledgments + +* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from. +* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples. +* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code. +
+ diff --git a/src/FreeRTOS.cpp b/src/FreeRTOS.cpp index f6bbe17..ff1061c 100644 --- a/src/FreeRTOS.cpp +++ b/src/FreeRTOS.cpp @@ -114,6 +114,10 @@ bool FreeRTOS::Semaphore::timedWait(std::string owner, uint32_t timeoutMs) { } // wait +/** + * @brief Construct a semaphore, the semaphore is given when created. + * @param [in] name A name string to provide debugging support. + */ FreeRTOS::Semaphore::Semaphore(std::string name) { m_usePthreads = false; // Are we using pThreads or FreeRTOS? if (m_usePthreads) { @@ -140,8 +144,7 @@ FreeRTOS::Semaphore::~Semaphore() { /** - * @brief Give a semaphore. - * The Semaphore is given. + * @brief Give the semaphore. */ void FreeRTOS::Semaphore::give() { NIMBLE_LOGD(LOG_TAG, "Semaphore giving: %s", toString().c_str()); diff --git a/src/FreeRTOS.h b/src/FreeRTOS.h index a6737b7..2f3d938 100644 --- a/src/FreeRTOS.h +++ b/src/FreeRTOS.h @@ -29,6 +29,9 @@ public: static uint32_t getTimeSinceStart(); +/** + * @brief A binary semaphore class that operates like a mutex, it is already given when constructed. + */ class Semaphore { public: Semaphore(std::string owner = ""); @@ -42,6 +45,10 @@ public: std::string toString(); bool timedWait(std::string owner = "", uint32_t timeoutMs = portMAX_DELAY); uint32_t wait(std::string owner = ""); + /** + * @brief Get the value of the semaphore. + * @return The value stored if the semaphore was given with give(value); + */ uint32_t value(){ return m_value; }; private: @@ -57,7 +64,7 @@ public: /** - * @brief Ringbuffer. + * @brief A wrapper class for a freeRTOS ringbuffer. */ class Ringbuffer { public: diff --git a/src/NimBLEAddress.cpp b/src/NimBLEAddress.cpp index 8c2c68f..34b9cfa 100644 --- a/src/NimBLEAddress.cpp +++ b/src/NimBLEAddress.cpp @@ -23,17 +23,17 @@ static const char* LOG_TAG = "NimBLEAddress"; /************************************************* -NOTE: NimBLE addresses are in INVERSE ORDER! -We will accomodate that fact in these methods. + * NOTE: NimBLE address bytes are in INVERSE ORDER! + * We will accomodate that fact in these methods. *************************************************/ /** - * @brief Create an address from the native ESP32 representation. - * @param [in] address The native representation. + * @brief Create an address from the native NimBLE representation. + * @param [in] address The native NimBLE address. */ NimBLEAddress::NimBLEAddress(ble_addr_t address) { memcpy(m_address, address.val, 6); -} // BLEAddress +} // NimBLEAddress /** @@ -45,7 +45,7 @@ NimBLEAddress::NimBLEAddress(ble_addr_t address) { * ``` * which is 17 characters in length. * - * @param [in] stringAddress The hex representation of the address. + * @param [in] stringAddress The hex string representation of the address. */ NimBLEAddress::NimBLEAddress(const std::string &stringAddress) { if (stringAddress.length() == 0) { @@ -72,12 +72,12 @@ NimBLEAddress::NimBLEAddress(const std::string &stringAddress) { for(size_t index = 0; index < sizeof m_address; index++) { m_address[index] = data[index]; } -} // BLEAddress +} // NimBLEAddress /** - * @brief Constructor for compatibility with bluedroid esp library. - * @param [in] uint8_t[6] or esp_bd_addr_t struct containing the address. + * @brief Constructor for compatibility with bluedroid esp library using native ESP representation. + * @param [in] address A uint8_t[6] or esp_bd_addr_t containing the address. */ NimBLEAddress::NimBLEAddress(uint8_t address[6]) { std::reverse_copy(address, address + sizeof m_address, m_address); @@ -85,8 +85,9 @@ NimBLEAddress::NimBLEAddress(uint8_t address[6]) { /** - * @brief Constructor for address using a hex value. Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16" - * @param [in] uint64_t containing the address. + * @brief Constructor for address using a hex value.\n + * Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16" + * @param [in] address uint64_t containing the address. */ NimBLEAddress::NimBLEAddress(const uint64_t &address) { memcpy(m_address, &address, sizeof m_address); @@ -104,8 +105,8 @@ bool NimBLEAddress::equals(const NimBLEAddress &otherAddress) const { /** - * @brief Return the native representation of the address. - * @return The native representation of the address. + * @brief Get the native representation of the address. + * @return a pointer to the uint8_t[6] array of the address. */ const uint8_t *NimBLEAddress::getNative() const { return m_address; @@ -122,30 +123,48 @@ const uint8_t *NimBLEAddress::getNative() const { * ``` * * @return The string representation of the address. + * @deprecated Use std::string() operator instead. */ std::string NimBLEAddress::toString() const { return std::string(*this); } // toString +/** + * @brief Convienience operator to check if this address is equal to another. + */ bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const { return memcmp(rhs.m_address, m_address, sizeof m_address) == 0; -} +} // operator == + +/** + * @brief Convienience operator to check if this address is not equal to another. + */ bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const { return !this->operator==(rhs); -} +} // operator != + +/** + * @brief Convienience operator to convert this address to string representation. + * @details This allows passing NimBLEAddress to functions + * that accept std::string and/or or it's methods as a parameter. + */ NimBLEAddress::operator std::string() const { char buffer[18]; sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]); return std::string(buffer); -} +} // operator std::string + +/** + * @brief Convienience operator to convert the native address representation to uint_64. + */ NimBLEAddress::operator uint64_t() const { uint64_t address = 0; memcpy(&address, m_address, sizeof m_address); return address; -} +} // operator uint64_t #endif diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index c53bb68..c06bb63 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -36,6 +36,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() { m_rssi = -9999; m_serviceData = ""; m_txPower = 0; + m_payloadLength = 0; m_pScan = nullptr; m_payloadLength = 0; m_payload = nullptr; @@ -53,11 +54,7 @@ NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() { /** - * @brief Get the address. - * - * Every %BLE device exposes an address that is used to identify it and subsequently connect to it. - * Call this function to obtain the address of the advertised device. - * + * @brief Get the address of the advertising device. * @return The address of the advertised device. */ NimBLEAddress NimBLEAdvertisedDevice::getAddress() { @@ -66,9 +63,13 @@ NimBLEAddress NimBLEAdvertisedDevice::getAddress() { /** - * @brief Get the advertised type. - * - * @return The advertised type of the advertised device. + * @brief Get the advertisement type. + * @return The advertising type the device is reporting: + * * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising + * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertisng - high duty cycle + * * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response + * * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertisng - not connectable + * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle */ uint8_t NimBLEAdvertisedDevice::getAdvType() { return m_advType; @@ -98,7 +99,7 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() { /** - * @brief Get the name. + * @brief Get the advertised name. * @return The name of the advertised device. */ std::string NimBLEAdvertisedDevice::getName() { @@ -116,7 +117,7 @@ int NimBLEAdvertisedDevice::getRSSI() { /** - * @brief Get the scan object that created this advertisement. + * @brief Get the scan object that created this advertised device. * @return The scan object. */ NimBLEScan* NimBLEAdvertisedDevice::getScan() { @@ -134,8 +135,8 @@ std::string NimBLEAdvertisedDevice::getServiceData() { /** - * @brief Get the service data UUID. - * @return The service data UUID. + * @brief Get the advertised service UUID. + * @return The advertise service UUID. */ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() { @@ -154,7 +155,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventual /** - * @brief Check advertised serviced for existence required UUID + * @brief Check advertised services for existance of the required UUID * @return Return true if service is advertised */ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){ @@ -163,7 +164,7 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){ if (m_serviceUUIDs[i].equals(uuid)) return true; } return false; -} +} // isAdvertisingService /** @@ -335,7 +336,7 @@ bool NimBLEAdvertisedDevice::haveTXPower() { setAppearance(fields->appearance); } -/**** TODO: create storage and fucntions for these parameters +/* 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; @@ -435,7 +436,7 @@ void NimBLEAdvertisedDevice::setRSSI(int rssi) { /** * @brief Set the Scan that created this advertised device. - * @param pScan The Scan that created this advertised device. + * @param [in] pScan The Scan that created this advertised device. */ void NimBLEAdvertisedDevice::setScan(NimBLEScan* pScan) { m_pScan = pScan; @@ -459,7 +460,7 @@ void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) { void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) { // Don't add duplicates for (int i = 0; i < m_serviceUUIDs.size(); i++) { - if (m_serviceUUIDs[i].equals(serviceUUID)) { + if (m_serviceUUIDs[i] == serviceUUID) { return; } } @@ -539,35 +540,68 @@ std::string NimBLEAdvertisedDevice::toString() { } // toString +/** + * @brief Get the payload advertised by the device. + * @return The advertisement payload. + */ uint8_t* NimBLEAdvertisedDevice::getPayload() { return m_payload; -} +} // getPayload +/** + * @brief Get the advertised device address type. + * @return The device address type: + * * BLE_ADDR_PUBLIC (0x00) + * * BLE_ADDR_RANDOM (0x01) + * * BLE_ADDR_PUBLIC_ID (0x02) + * * BLE_ADDR_RANDOM_ID (0x03) + */ uint8_t NimBLEAdvertisedDevice::getAddressType() { return m_addressType; -} +} // getAddressType +/** + * @brief Get the timeStamp of when the device last advertised. + * @return The timeStamp of when the device was last seen. + */ time_t NimBLEAdvertisedDevice::getTimestamp() { return m_timestamp; -} +} // getTimestamp +/** + * @brief Set the advertised device address type. + * @param [in] type The address type of the device: + * * BLE_ADDR_PUBLIC (0x00) + * * BLE_ADDR_RANDOM (0x01) + * * BLE_ADDR_PUBLIC_ID (0x02) + * * BLE_ADDR_RANDOM_ID (0x03) + */ void NimBLEAdvertisedDevice::setAddressType(uint8_t type) { m_addressType = type; -} +} // setAddressType +/** + * @brief Get the length of the payload advertised by the device. + * @return The size of the payload in bytes. + */ size_t NimBLEAdvertisedDevice::getPayloadLength() { return m_payloadLength; -} +} // getPayloadLength +/** + * @brief Set the advertisment payload data. + * @param [in] payload A pointer to the device payload data. + * @param [in] length The length of the payload data in bytes. + */ void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t length){ m_payload = payload; m_payloadLength = length; -} +} // setAdvertisementResult #endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index c38d700..d1f400c 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -46,6 +46,14 @@ public: uint16_t getAppearance(); std::string getManufacturerData(); +/** + * @brief A template to convert the service data to . + * @tparam T The type to convert the data to. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: getManufacturerData(skipSizeCheck); + */ template T getManufacturerData(bool skipSizeCheck = false) { std::string data = getManufacturerData(); @@ -59,6 +67,14 @@ public: NimBLEScan* getScan(); std::string getServiceData(); +/** + * @brief A template to convert the service data to . + * @tparam T The type to convert the data to. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: getServiceData(skipSizeCheck); + */ template T getServiceData(bool skipSizeCheck = false) { std::string data = getServiceData(); @@ -123,7 +139,6 @@ private: std::string m_name; NimBLEScan* m_pScan; int m_rssi; - std::vector m_serviceUUIDs; int8_t m_txPower; std::string m_serviceData; NimBLEUUID m_serviceDataUUID; @@ -132,6 +147,8 @@ private: uint8_t m_addressType; time_t m_timestamp; bool m_callbackSent; + + std::vector m_serviceUUIDs; }; /** diff --git a/src/NimBLEAdvertising.cpp b/src/NimBLEAdvertising.cpp index 7e1e07a..ccec223 100644 --- a/src/NimBLEAdvertising.cpp +++ b/src/NimBLEAdvertising.cpp @@ -31,7 +31,6 @@ static const char* LOG_TAG = "NimBLEAdvertising"; /** * @brief Construct a default advertising object. - * */ NimBLEAdvertising::NimBLEAdvertising() { memset(&m_advData, 0, sizeof m_advData); @@ -78,43 +77,70 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) { /** * @brief Set the device appearance in the advertising data. - * The appearance attribute is of type 0x19. The codes for distinct appearances can be found here: + * The codes for distinct appearances can be found here:\n * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml. * @param [in] appearance The appearance of the device in the advertising data. - * @return N/A. */ void NimBLEAdvertising::setAppearance(uint16_t appearance) { m_advData.appearance = appearance; m_advData.appearance_is_present = 1; } // setAppearance + +/** + * @brief Set the type of advertisment to use. + * @param [in] adv_type: + * * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising + * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertisng - high duty cycle + * * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response + * * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertisng - not connectable + * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle + */ void NimBLEAdvertising::setAdvertisementType(uint8_t adv_type){ m_advParams.conn_mode = adv_type; } // setAdvertisementType + +/** + * @brief Set the minimum advertising interval. + * @param [in] mininterval Minimum value for advertising interval in 0.625ms units, 0 = use default. + */ void NimBLEAdvertising::setMinInterval(uint16_t mininterval) { m_advParams.itvl_min = mininterval; } // setMinInterval + +/** + * @brief Set the maximum advertising interval. + * @param [in] maxinterval Maximum value for advertising interval in 0.625ms units, 0 = use default. + */ void NimBLEAdvertising::setMaxInterval(uint16_t maxinterval) { m_advParams.itvl_max = maxinterval; } // setMaxInterval -/* These are dummy functions for now for compatibility */ +/** + * @brief NOP - Not yet implemented, dummy function for backward compatibility. + */ void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) { - //m_advData.min_interval = mininterval; -} // +} // setMinPreferred + +/** + * @brief NOP - Not yet implemented, dummy function for backward compatibility. + */ void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) { - //m_advData.max_interval = maxinterval; -} // -/*******************************************************/ +} // setMaxPreferred +/** + * @brief Set if scan response is available. + * @param [in] set true = scan response available. + */ void NimBLEAdvertising::setScanResponse(bool set) { m_scanResp = set; -} +} // setScanResponse + /** * @brief Set the filtering for the scan filter. @@ -145,6 +171,7 @@ void NimBLEAdvertising::setScanFilter(bool scanRequestWhitelistOnly, bool connec } } // setScanFilter + /** * @brief Set the advertisement data that is to be published in a regular advertisement. * @param [in] advertisementData The data to be advertised. @@ -182,8 +209,6 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme /** * @brief Start advertising. - * Start advertising. - * @return N/A. */ void NimBLEAdvertising::start() { NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData); @@ -375,8 +400,6 @@ void NimBLEAdvertising::start() { /** * @brief Stop advertising. - * Stop advertising. - * @return N/A. */ void NimBLEAdvertising::stop() { NIMBLE_LOGD(LOG_TAG, ">> stop"); @@ -390,7 +413,7 @@ void NimBLEAdvertising::stop() { } // stop -/** +/* * Host reset seems to clear advertising data, * we need clear the flag so it reloads it. */ @@ -427,8 +450,8 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) { /** - * @brief Set the complete services. - * @param [in] uuid The single service to advertise. + * @brief Set the complete services to advertise. + * @param [in] uuid The UUID of the service. */ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) { char cdata[2]; @@ -465,16 +488,7 @@ void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) { /** * @brief Set the advertisement flags. - * @param [in] The flags to be set in the advertisement. - * * ****DO NOT USE THESE**** - * * ESP_BLE_ADV_FLAG_LIMIT_DISC - * * ESP_BLE_ADV_FLAG_GEN_DISC - * * ESP_BLE_ADV_FLAG_BREDR_NOT_SPT - * * ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT - * * ESP_BLE_ADV_FLAG_DMT_HOST_SPT - * * ESP_BLE_ADV_FLAG_NON_LIMIT_DISC - * * - * * ****THESE ARE SUPPORTED**** + * @param [in] flag The flags to be set in the advertisement. * * BLE_HS_ADV_F_DISC_LTD * * BLE_HS_ADV_F_DISC_GEN * * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE @@ -490,7 +504,7 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) { /** * @brief Set manufacturer specific data. - * @param [in] data Manufacturer data. + * @param [in] data The manufacturer data to advertise. */ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) { NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData"); @@ -503,8 +517,8 @@ void NimBLEAdvertisementData::setManufacturerData(const std::string &data) { /** - * @brief Set the name. - * @param [in] The complete name of the device. + * @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()); @@ -517,7 +531,7 @@ void NimBLEAdvertisementData::setName(const std::string &name) { /** - * @brief Set the partial services. + * @brief Set the partial services to advertise. * @param [in] uuid The single service to advertise. */ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) { @@ -555,8 +569,8 @@ void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) { /** * @brief Set the service data (UUID + data) - * @param [in] uuid The UUID to set with the service data. Size of UUID will be used. - * @param [in] data The data to be associated with the service data advert. + * @param [in] uuid The UUID to set with the service data. + * @param [in] data The data to be associated with the service data advertised. */ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) { char cdata[2]; @@ -593,7 +607,7 @@ void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std:: /** * @brief Set the short name. - * @param [in] The short name of the device. + * @param [in] name The short name of the device. */ void NimBLEAdvertisementData::setShortName(const std::string &name) { NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str()); diff --git a/src/NimBLEAdvertising.h b/src/NimBLEAdvertising.h index ad76d7e..d81d797 100644 --- a/src/NimBLEAdvertising.h +++ b/src/NimBLEAdvertising.h @@ -84,8 +84,6 @@ public: void setAdvertisementData(NimBLEAdvertisementData& advertisementData); void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly); void setScanResponseData(NimBLEAdvertisementData& advertisementData); - void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM); - void setMinPreferred(uint16_t); void setMaxPreferred(uint16_t); void setScanResponse(bool); diff --git a/src/NimBLEBeacon.cpp b/src/NimBLEBeacon.cpp index 718a507..d3c7526 100644 --- a/src/NimBLEBeacon.cpp +++ b/src/NimBLEBeacon.cpp @@ -22,6 +22,10 @@ static const char* LOG_TAG = "NimBLEBeacon"; + +/** + * @brief Construct a default beacon object. + */ NimBLEBeacon::NimBLEBeacon() { m_beaconData.manufacturerId = 0x4c00; m_beaconData.subType = 0x02; @@ -32,32 +36,64 @@ NimBLEBeacon::NimBLEBeacon() { memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID)); } // NimBLEBeacon + +/** + * @brief Retrieve the data that is being advertised. + * @return The advertised data. + */ std::string NimBLEBeacon::getData() { return std::string((char*) &m_beaconData, sizeof(m_beaconData)); } // getData + +/** + * @brief Get the major value being advertised. + * @return The major value advertised. + */ uint16_t NimBLEBeacon::getMajor() { return m_beaconData.major; } + +/** + * @brief Get the manufacturer ID being advertised. + * @return The manufacturer ID value advertised. + */ uint16_t NimBLEBeacon::getManufacturerId() { return m_beaconData.manufacturerId; } + +/** + * @brief Get the minor value being advertised. + * @return minor value advertised. + */ uint16_t NimBLEBeacon::getMinor() { return m_beaconData.minor; } + +/** + * @brief Get the proximity UUID being advertised. + * @return The UUID advertised. + */ NimBLEUUID NimBLEBeacon::getProximityUUID() { return NimBLEUUID(m_beaconData.proximityUUID, 16, false); } + +/** + * @brief Get the signal power being advertised. + * @return signal power level advertised. + */ int8_t NimBLEBeacon::getSignalPower() { return m_beaconData.signalPower; } + /** - * Set the raw data for the beacon record. + * @brief Set the raw data for the beacon record. + * @param [in] data The raw beacon data. */ void NimBLEBeacon::setData(const std::string &data) { if (data.length() != sizeof(m_beaconData)) { @@ -68,24 +104,49 @@ void NimBLEBeacon::setData(const std::string &data) { memcpy(&m_beaconData, data.data(), sizeof(m_beaconData)); } // setData + +/** + * @brief Set the major value. + * @param [in] major The major value. + */ void NimBLEBeacon::setMajor(uint16_t major) { m_beaconData.major = ENDIAN_CHANGE_U16(major); } // setMajor + +/** + * @brief Set the manufacturer ID. + * @param [in] manufacturerId The manufacturer ID value. + */ void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) { m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId); } // setManufacturerId + +/** + * @brief Set the minor value. + * @param [in] minor The minor value. + */ void NimBLEBeacon::setMinor(uint16_t minor) { m_beaconData.minor = ENDIAN_CHANGE_U16(minor); } // setMinior + +/** + * @brief Set the proximity UUID. + * @param [in] uuid The proximity UUID. + */ void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) { NimBLEUUID temp_uuid = uuid; temp_uuid.to128(); memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16); } // setProximityUUID + +/** + * @brief Set the signal power. + * @param [in] signalPower The signal power value. + */ void NimBLEBeacon::setSignalPower(int8_t signalPower) { m_beaconData.signalPower = signalPower; } // setSignalPower diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 0bd11f6..5142a01 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -65,6 +65,7 @@ NimBLECharacteristic::~NimBLECharacteristic() { * @brief Create a new BLE Descriptor associated with this characteristic. * @param [in] uuid - The UUID of the descriptor. * @param [in] properties - The properties of the descriptor. + * @param [in] max_len - The max length in bytes of the descriptor value. * @return The new BLE descriptor. */ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) { @@ -76,6 +77,7 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3 * @brief Create a new BLE Descriptor associated with this characteristic. * @param [in] uuid - The UUID of the descriptor. * @param [in] properties - The properties of the descriptor. + * @param [in] max_len - The max length in bytes of the descriptor value. * @return The new BLE descriptor. */ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) { @@ -106,8 +108,8 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, /** * @brief Return the BLE Descriptor for the given UUID if associated with this characteristic. - * @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve. - * @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned. + * @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. */ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) { return getDescriptorByUUID(NimBLEUUID(uuid)); @@ -116,8 +118,8 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) { /** * @brief Return the BLE Descriptor for the given UUID if associated with this characteristic. - * @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve. - * @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned. + * @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. */ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) { for (auto &it : m_dscVec) { @@ -138,6 +140,10 @@ uint16_t NimBLECharacteristic::getHandle() { } // getHandle +/** + * @brief Get the properties of the characteristic. + * @return The properties of the characteristic. + */ uint16_t NimBLECharacteristic::getProperties() { return m_properties; } // getProperties @@ -162,7 +168,7 @@ NimBLEUUID NimBLECharacteristic::getUUID() { /** * @brief Retrieve the current value of the characteristic. - * @return A pointer to storage containing the current characteristic value. + * @return A std::string containing the current characteristic value. */ std::string NimBLECharacteristic::getValue(time_t *timestamp) { portENTER_CRITICAL(&m_valMux); @@ -189,6 +195,9 @@ size_t NimBLECharacteristic::getDataLength() { } +/** + * @brief STATIC callback to handle events from the NimBLE stack. + */ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) @@ -253,9 +262,8 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han /** - * @brief Set the subscribe status for this characteristic. - * This will maintain a map of subscribed clients and their indicate/notify status. - * @return N/A + * @brief Set the subscribe status for this characteristic.\n + * This will maintain a vector of subscribed clients and their indicate/notify status. */ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) { uint16_t subVal = 0; @@ -313,10 +321,9 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) { /** - * @brief Send an indication. - * An indication is a transmission of up to the first 20 bytes of the characteristic value. An indication - * will block waiting a positive confirmation from the client. - * @return N/A + * @brief Send an indication.\n + * An indication is a transmission of up to the first 20 bytes of the characteristic value.\n + * An indication will block waiting for a positive confirmation from the client. */ void NimBLECharacteristic::indicate() { NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", getDataLength()); @@ -325,10 +332,10 @@ void NimBLECharacteristic::indicate() { } // indicate /** - * @brief Send a notify. - * A notification is a transmission of up to the first 20 bytes of the characteristic value. An notification - * will not block; it is a fire and forget. - * @return N/A. + * @brief Send a notification.\n + * A notification is a transmission of up to the first 20 bytes of the characteristic value.\n + * A notification will not block; it is a fire and forget. + * @param[in] is_notification if true sends a notification, false sends an indication. */ void NimBLECharacteristic::notify(bool is_notification) { NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", getDataLength()); @@ -435,7 +442,8 @@ void NimBLECharacteristic::notify(bool is_notification) { /** * @brief Set the callback handlers for this characteristic. - * @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic. + * @param [in] pCallbacks An instance of a NimBLECharacteristicCallbacks class\n + * used to define any callbacks for the characteristic. */ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) { if (pCallbacks != nullptr){ @@ -473,11 +481,9 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { /** - * @brief Set the value of the characteristic from string data. - * We set the value of the characteristic from the bytes contained in the - * string. - * @param [in] Set the value of the characteristic. - * @return N/A. + * @brief Set the value of the characteristic from string data.\n + * We set the value of the characteristic from the bytes contained in the string. + * @param [in] value the std::string value of the characteristic. */ void NimBLECharacteristic::setValue(const std::string &value) { setValue((uint8_t*)(value.data()), value.length()); @@ -537,8 +543,8 @@ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacterist /** * @brief Callback function to support a Notify/Indicate Status report. * @param [in] pCharacteristic The characteristic that is the source of the event. - * @param [in] s Status of the notification/indication - * @param [in] code Additional code of underlying errors + * @param [in] s Status of the notification/indication. + * @param [in] code Additional return code from the NimBLE stack. */ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) { NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default"); diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index 4474e5f..a5ac901 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -75,6 +75,15 @@ public: NimBLEUUID getUUID(); std::string getValue(time_t *timestamp = nullptr); + /** + * @brief A template to convert the characteristic data to . + * @tparam T The type to convert the data to. + * @param [in] timestamp A pointer to a time_t struct to store the time the value was read. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: getValue(×tamp, skipSizeCheck); + */ template T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) { std::string value = getValue(); @@ -90,6 +99,10 @@ public: void setValue(const uint8_t* data, size_t size); void setValue(const std::string &value); + /** + * @brief Convenience template to set the characteristic value to val. + * @param [in] s The value to set. + */ template void setValue(const T &s) { setValue((uint8_t*)&s, sizeof(T)); @@ -144,6 +157,12 @@ private: */ class NimBLECharacteristicCallbacks { public: + +/** + * @brief An enum to provide the callback the status of the + * notification/indication, implemented for backward compatibility. + * @deprecated To be removed in the future as the NimBLE stack return code is also provided. + */ typedef enum { SUCCESS_INDICATE, SUCCESS_NOTIFY, diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 71f1c9a..4266474 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -48,6 +48,11 @@ static NimBLEClientCallbacks defaultCallbacks; * */ + +/** + * @brief Constructor, private - only callable by NimBLEDevice::createClient + * to ensure proper handling of the list of client objects. + */ NimBLEClient::NimBLEClient() { m_pClientCallbacks = &defaultCallbacks; @@ -86,7 +91,7 @@ NimBLEClient::~NimBLEClient() { /** - * @brief Delete any existing services. + * @brief Delete all service objects created by this client and clear the vector. */ void NimBLEClient::deleteServices() { NIMBLE_LOGD(LOG_TAG, ">> deleteServices"); @@ -123,16 +128,11 @@ size_t NimBLEClient::deleteService(const NimBLEUUID &uuid) { /** - * NOT NEEDED - */ - /* -void NimBLEClient::onHostReset() { - -} - */ - -/** - * Add overloaded function to ease connect to peer device with not public address + * @brief Connect to an advertising device. + * @param [in] device The device to connect to. + * @param [in] refreshServices If true this will delete any attribute objects this client may already\n + * have created and clears the vectors after successful connection. + * @return True on success. */ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices) { NimBLEAddress address(device->getAddress()); @@ -142,8 +142,11 @@ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices) /** - * @brief Connect to the partner (BLE Server). - * @param [in] address The address of the partner. + * @brief Connect to the BLE Server. + * @param [in] address The address of the server. + * @param [in] type The address type of the server (Random/public/other) + * @param [in] refreshServices If true this will delete any attribute objects this client may already\n + * have created and clears the vectors after successful connection. * @return True on success. */ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) { @@ -173,7 +176,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr}; m_pTaskData = &taskData; - /** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for + /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for * timeout (default value of m_connectTimeout). * Loop on BLE_HS_EBUSY if the scan hasn't stopped yet. */ @@ -218,8 +221,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr /** - * @brief Called when a characteristic or descriptor requires encryption or authentication to access it. - * This will pair with the device and bond if enabled. + * @brief Initiate a secure connection (pair/bond) with the server.\n + * Called automatically when a characteristic or descriptor requires encryption or authentication to access it. * @return True on success. */ bool NimBLEClient::secureConnection() { @@ -239,12 +242,12 @@ bool NimBLEClient::secureConnection() { } return true; -} +} // secureConnection /** * @brief Disconnect from the peer. - * @return N/A. + * @return Error code from NimBLE stack, 0 = success. */ int NimBLEClient::disconnect(uint8_t reason) { NIMBLE_LOGD(LOG_TAG, ">> disconnect()"); @@ -264,6 +267,12 @@ int NimBLEClient::disconnect(uint8_t reason) { /** * @brief Set the connection paramaters to use when connecting to a server. + * @param [in] minInterval minimum connection interval in 0.625ms units. + * @param [in] maxInterval maximum connection interval in 0.625ms units. + * @param [in] latency number of packets allowed to skip (extends max interval) + * @param [in] timeout the timeout time in 10ms units before disconnecting + * @param [in] scanInterval the scan interval to use when attempting to connect in 0.625ms units. + * @param [in] scanWindow the scan window to use when attempting to connect in 0.625ms units. */ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout, @@ -271,12 +280,12 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva uint16_t minConnTime, uint16_t maxConnTime)*/ { - m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units - m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units - m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms - m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms - m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval) - m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms + m_pConnParams.scan_itvl = scanInterval; + m_pConnParams.scan_window = scanWindow; + m_pConnParams.itvl_min = minInterval; + m_pConnParams.itvl_max = maxInterval; + m_pConnParams.latency = latency; + m_pConnParams.supervision_timeout = timeout; // These are not used by NimBLE at this time - Must leave at defaults //m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units @@ -284,11 +293,16 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva int rc = NimBLEUtils::checkConnParams(&m_pConnParams); assert(rc == 0 && "Invalid Connection parameters"); -} +} // setConnectionParams /** - * Update connection parameters can be called only after connection has been established + * @brief Update the connection parameters: + * * Can only be used after a connection has been established. + * @param [in] minInterval minimum connection interval in 0.625ms units. + * @param [in] maxInterval maximum connection interval in 0.625ms units. + * @param [in] latency number of packets allowed to skip (extends max interval) + * @param [in] timeout the timeout time in 10ms units before disconnecting */ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout) @@ -308,16 +322,16 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval, NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); } -} +} // updateConnParams /** - * @brief Set the timeout to wait for connection attempt to complete - * @params[in] Time to wait in seconds. + * @brief Set the timeout to wait for connection attempt to complete. + * @param [in] time The number of seconds before timeout. */ void NimBLEClient::setConnectTimeout(uint8_t time) { m_connectTimeout = (uint32_t)(time * 1000); -} +} // setConnectTimeout /** @@ -381,7 +395,7 @@ std::vector::iterator NimBLEClient::end() { /** * @brief Get the service BLE Remote Service instance corresponding to the uuid. * @param [in] uuid The UUID of the service being sought. - * @return A reference to the Service or nullptr if don't know about it. + * @return A pointer to the service or nullptr if not found. */ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { return getService(NimBLEUUID(uuid)); @@ -391,7 +405,7 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { /** * @brief Get the service object corresponding to the uuid. * @param [in] uuid The UUID of the service being sought. - * @return A reference to the Service or nullptr if don't know about it. + * @return A pointer to the service or nullptr if not found. */ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) { NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); @@ -416,12 +430,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) { /** - * @Get a pointer to the vector of found services. - * @param [in] bool value to indicate if the current vector should be cleared and - * subsequently all services retrieved from the peripheral. - * If false the vector will be returned with the currently stored services, - * If true it will retrieve all services from the peripheral and return the vector with all services - * @return a pointer to the vector of available services. + * @brief Get a pointer to the vector of found services. + * @param [in] refresh If true the current services vector will be cleared and\n + * all services will be retrieved from the peripheral.\n + * If false the vector will be returned with the currently stored services. + * @return A pointer to the vector of available services. */ std::vector* NimBLEClient::getServices(bool refresh) { if(refresh) { @@ -435,11 +448,11 @@ std::vector* NimBLEClient::getServices(bool refresh) { } } return &m_servicesVector; -} +} // getServices /** - * @ Retrieves the full database of attributes that the peripheral has available. + * @brief Retrieves the full database of attributes that the peripheral has available. */ void NimBLEClient::discoverAttributes() { for(auto svc: *getServices(true)) { @@ -447,14 +460,12 @@ void NimBLEClient::discoverAttributes() { chr->getDescriptors(true); } } -} +} // discoverAttributes /** - * @brief Ask the remote %BLE server for its services. - * A %BLE Server exposes a set of services for its partners. Here we ask the server for its set of - * services and wait until we have received them all. - * We then ask for the characteristics for each service found and their desciptors. + * @brief Ask the remote %BLE server for its services.\n + * Here we ask the server for its set of services and wait until we have received them all. * @return true on success otherwise false if an error occurred */ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { @@ -502,7 +513,7 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) { /** - * @brief STATIC Callback for the service discovery API function. + * @brief STATIC Callback for the service discovery API function.\n * When a service is found or there is none left or there was an error * the API will call this and report findings. */ @@ -574,6 +585,7 @@ std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUU * @brief Set the value of a specific characteristic associated with a specific service. * @param [in] serviceUUID The service that owns the characteristic. * @param [in] characteristicUUID The characteristic whose value we wish to write. + * @param [in] value The value to write to the characteristic. * @returns true if successful otherwise false */ bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, @@ -600,17 +612,17 @@ bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &cha /** * @brief Get the current mtu of this connection. + * @returns The MTU value. */ uint16_t NimBLEClient::getMTU() { return ble_att_mtu(m_conn_id); -} +} // getMTU /** * @brief Handle a received GAP event. - * - * @param [in] event - * @param [in] arg = pointer to the client instance + * @param [in] event The event structure sent by the NimBLE stack. + * @param [in] arg A pointer to the client instance that registered for this callback. */ /*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { NimBLEClient* client = (NimBLEClient*)arg; @@ -893,7 +905,9 @@ bool NimBLEClient::isConnected() { /** - * @brief Set the callbacks that will be invoked. + * @brief Set the callbacks that will be invoked when events are received. + * @param [in] pClientCallbacks A pointer to a class to receive the event callbacks. + * @param [in] deleteCallbacks If true this will delete the callback class sent when the client is destructed. */ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) { if (pClientCallbacks != nullptr){ @@ -938,7 +952,7 @@ uint32_t NimBLEClientCallbacks::onPassKeyRequest(){ NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyRequest: default: 123456"); return 123456; } - +/* void NimBLEClientCallbacks::onPassKeyNotify(uint32_t pass_key){ NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyNotify: default: %d", pass_key); } @@ -946,7 +960,7 @@ void NimBLEClientCallbacks::onPassKeyNotify(uint32_t pass_key){ bool NimBLEClientCallbacks::onSecurityRequest(){ NIMBLE_LOGD("NimBLEClientCallbacks", "onSecurityRequest: default: true"); return true; -} +}*/ void NimBLEClientCallbacks::onAuthenticationComplete(ble_gap_conn_desc* desc){ NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default"); } diff --git a/src/NimBLEClient.h b/src/NimBLEClient.h index 888b42d..8f26048 100644 --- a/src/NimBLEClient.h +++ b/src/NimBLEClient.h @@ -107,13 +107,48 @@ private: class NimBLEClientCallbacks { public: virtual ~NimBLEClientCallbacks() {}; + + /** + * @brief Called after client connects. + * @param [in] pClient A pointer to the calling client object. + */ virtual void onConnect(NimBLEClient* pClient); + + /** + * @brief Called when disconnected from the server. + * @param [in] pClient A pointer to the calling client object. + */ virtual void onDisconnect(NimBLEClient* pClient); + + /** + * @brief Called when server requests to update the connection parameters. + * @param [in] pClient A pointer to the calling client object. + * @param [in] params A pointer to the struct containing the connection parameters requested. + * @return True to accept the parmeters. + */ virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params); + + /** + * @brief Called when server requests a passkey for pairing. + * @return The passkey to be sent to the server. + */ virtual uint32_t onPassKeyRequest(); - virtual void onPassKeyNotify(uint32_t pass_key); - virtual bool onSecurityRequest(); + + /*virtual void onPassKeyNotify(uint32_t pass_key); + virtual bool onSecurityRequest();*/ + + /** + * @brief Called when the pairing procedure is complete. + * @param [in] desc A pointer to the struct containing the connection information.\n + * This can be used to check the status of the connection encryption/pairing. + */ virtual void onAuthenticationComplete(ble_gap_conn_desc* desc); + + /** + * @brief Called when using numeric comparision for pairing. + * @param [in] pin The pin to compare with the server. + * @return True to accept the pin. + */ virtual bool onConfirmPIN(uint32_t pin); }; diff --git a/src/NimBLEDescriptor.h b/src/NimBLEDescriptor.h index f4978f5..633e189 100644 --- a/src/NimBLEDescriptor.h +++ b/src/NimBLEDescriptor.h @@ -52,6 +52,10 @@ public: void setValue(const std::string &value); std::string toString(); + /** + * @brief Convenience template to set the descriptor value to val. + * @param [in] s The value to set. + */ template void setValue(const T &s) { setValue((uint8_t*)&s, sizeof(T)); diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index b3d882b..a2dc882 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -90,6 +90,10 @@ NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +/** + * @brief Get the instance of the advertising object. + * @return A pointer to the advertising object. + */ NimBLEAdvertising* NimBLEDevice::getAdvertising() { if(m_bleAdvertising == nullptr) { m_bleAdvertising = new NimBLEAdvertising(); @@ -98,11 +102,17 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() { } +/** + * @brief Convenience function to begin advertising. + */ void NimBLEDevice::startAdvertising() { getAdvertising()->start(); } // startAdvertising +/** + * @brief Convenience function to stop advertising. + */ void NimBLEDevice::stopAdvertising() { getAdvertising()->stop(); } // stopAdvertising @@ -123,6 +133,7 @@ void NimBLEDevice::stopAdvertising() { } // getScan #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) + /** * @brief Creates a new client object and maintains a list of all client objects * each client can connect to 1 peripheral device. @@ -143,9 +154,9 @@ void NimBLEDevice::stopAdvertising() { /** - * @brief Delete the client object and remove it from the list. - * Check if it is connected or trying to connect and close/stop it first. - * @param [in] Pointer to the client object. + * @brief Delete the client object and remove it from the list.\n + * Checks if it is connected or trying to connect and disconnects/stops it first. + * @param [in] pClient A pointer to the client object. */ /* STATIC */ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { if(pClient == nullptr) { @@ -183,8 +194,8 @@ void NimBLEDevice::stopAdvertising() { /** - * @brief get the list of clients. - * @return a pointer to the list of clients. + * @brief Get the list of created client objects. + * @return A pointer to the list of clients. */ /* STATIC */std::list* NimBLEDevice::getClientList() { return &m_cList; @@ -192,8 +203,8 @@ void NimBLEDevice::stopAdvertising() { /** - * @brief get the size of the list of clients. - * @return a pointer to the list of clients. + * @brief Get the number of created client objects. + * @return Number of client objects created. */ /* STATIC */size_t NimBLEDevice::getClientListSize() { return m_cList.size(); @@ -202,8 +213,8 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Get a reference to a client by connection ID. - * @param [in] The client connection ID to search for. - * @return A reference pointer to the client with the spcified connection ID. + * @param [in] conn_id The client connection ID to search for. + * @return A pointer to the client object with the spcified connection ID. */ /* STATIC */NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { @@ -218,8 +229,8 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Get a reference to a client by peer address. - * @param [in] a NimBLEAddress of the peer to search for. - * @return A reference pointer to the client with the peer address. + * @param [in] peer_addr The address of the peer to search for. + * @return A pointer to the client object with the peer address. */ /* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { @@ -233,7 +244,7 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Finds the first disconnected client in the list. - * @return A reference pointer to the first client that is not connected to a peer. + * @return A pointer to the first client object that is not connected to a peer. */ /* STATIC */NimBLEClient* NimBLEDevice::getDisconnectedClient() { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { @@ -249,16 +260,28 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Set the transmission power. - * The power level can be one of: - * * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm - * * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm - * * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm - * * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm - * * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm - * * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm - * * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm - * * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm - * @param [in] powerLevel. + * @param [in] powerLevel The power level to set, can be one of: + * * ESP_PWR_LVL_N12 = 0, Corresponding to -12dbm + * * ESP_PWR_LVL_N9 = 1, Corresponding to -9dbm + * * ESP_PWR_LVL_N6 = 2, Corresponding to -6dbm + * * ESP_PWR_LVL_N3 = 3, Corresponding to -3dbm + * * ESP_PWR_LVL_N0 = 4, Corresponding to 0dbm + * * ESP_PWR_LVL_P3 = 5, Corresponding to +3dbm + * * ESP_PWR_LVL_P6 = 6, Corresponding to +6dbm + * * ESP_PWR_LVL_P9 = 7, Corresponding to +9dbm + * @param [in] powerType The BLE function to set the power level for, 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 + * * ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, For connection handle 2 + * * ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, For connection handle 3 + * * ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, For connection handle 4 + * * ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, For connection handle 5 + * * ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, For connection handle 6 + * * ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, For connection handle 7 + * * ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, For connection handle 8 + * * ESP_BLE_PWR_TYPE_ADV = 9, For advertising + * * ESP_BLE_PWR_TYPE_SCAN = 10, For scan + * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value */ /* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType); @@ -270,6 +293,24 @@ void NimBLEDevice::stopAdvertising() { } // setPower +/** + * @brief Set 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 + * * ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, For connection handle 2 + * * ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, For connection handle 3 + * * ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, For connection handle 4 + * * ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, For connection handle 5 + * * ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, For connection handle 6 + * * ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, For connection handle 7 + * * ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, For connection handle 8 + * * ESP_BLE_PWR_TYPE_ADV = 9, For advertising + * * ESP_BLE_PWR_TYPE_SCAN = 10, For scan + * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value + * @return the power level currently used by the type specified. + */ + /* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { switch(esp_ble_tx_power_get(powerType)) { @@ -302,7 +343,6 @@ void NimBLEDevice::stopAdvertising() { */ /* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; - //ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL) if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random"); @@ -324,9 +364,9 @@ void NimBLEDevice::stopAdvertising() { /** - * @brief Setup local mtu that will be used to negotiate mtu during request from client peer - * @param [in] mtu Value to set local mtu, should be larger than 23 and lower or equal to - * BLE_ATT_MTU_MAX = 527 + * @brief Setup local mtu that will be used to negotiate mtu during request from client peer. + * @param [in] mtu Value to set local mtu: + * * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527. */ /* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); @@ -344,6 +384,7 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Get local MTU value set. + * @return The current preferred MTU setting. */ /* STATIC */uint16_t NimBLEDevice::getMTU() { return ble_att_preferred_mtu(); @@ -352,6 +393,7 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Host reset, we pass the message so we don't make calls until resynced. + * @param [in] reason The reason code for the reset. */ /* STATIC */ void NimBLEDevice::onReset(int reason) { @@ -389,7 +431,7 @@ void NimBLEDevice::stopAdvertising() { /** - * @brief Host resynced with controller, all clear to make calls. + * @brief Host resynced with controller, all clear to make calls to the stack. */ /* STATIC */ void NimBLEDevice::onSync(void) { @@ -439,7 +481,7 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Initialize the %BLE environment. - * @param deviceName The device name of the device. + * @param [in] deviceName The device name of the device. */ /* STATIC */ void NimBLEDevice::init(const std::string &deviceName) { if(!initialized){ @@ -516,6 +558,7 @@ void NimBLEDevice::stopAdvertising() { /** * @brief Check if the initialization is complete. + * @return true if initialized. */ bool NimBLEDevice::getInitialized() { return initialized; @@ -524,9 +567,9 @@ bool NimBLEDevice::getInitialized() { /** * @brief Set the authorization mode for this device. - * @param bonding, if true we allow bonding, false no bonding will be performed. - * @param mitm, if true we are capable of man in the middle protection, false if not. - * @param sc, if true we will perform secure connection pairing, false we will use legacy pairing. + * @param bonding If true we allow bonding, false no bonding will be performed. + * @param mitm If true we are capable of man in the middle protection, false if not. + * @param sc If true we will perform secure connection pairing, false we will use legacy pairing. */ /*STATIC*/ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc); @@ -538,13 +581,12 @@ bool NimBLEDevice::getInitialized() { /** * @brief Set the authorization mode for this device. - * @param A bitmap indicating what modes are supported. - * The bits are defined as follows: - ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND - ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM - ** 0x08 BLE_SM_PAIR_AUTHREQ_SC - ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. - ** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only. + * @param auth_req A bitmap indicating what modes are supported.\n + * The available bits are defined as: + * * 0x01 BLE_SM_PAIR_AUTHREQ_BOND + * * 0x04 BLE_SM_PAIR_AUTHREQ_MITM + * * 0x08 BLE_SM_PAIR_AUTHREQ_SC + * * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. */ /*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, @@ -555,12 +597,12 @@ bool NimBLEDevice::getInitialized() { /** * @brief Set the Input/Output capabilities of this device. - * @param One of the following: - ** 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability - ** 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability - ** 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability - ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability - ** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability + * @param iocap One of the following values: + * * 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability + * * 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability + * * 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability + * * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability + * * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability */ /*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { ble_hs_cfg.sm_io_cap = iocap; @@ -569,12 +611,12 @@ bool NimBLEDevice::getInitialized() { /** * @brief If we are the initiator of the security procedure this sets the keys we will distribute. - * @param A bitmap indicating which keys to distribute during pairing. - * The bits are defined as follows: - ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key. - ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK). - ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK + * @param init_key A bitmap indicating which keys to distribute during pairing.\n + * The available bits are defined as: + * * 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key. + * * 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK). + * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN + * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ /*STATIC*/void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { ble_hs_cfg.sm_our_key_dist = init_key; @@ -583,20 +625,21 @@ bool NimBLEDevice::getInitialized() { /** * @brief Set the keys we are willing to accept during pairing. - * @param A bitmap indicating which keys to accept during pairing. - * The bits are defined as follows: - ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key. - ** 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK). - ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN - ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK + * @param resp_key A bitmap indicating which keys to accept during pairing. + * The available bits are defined as: + * * 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key. + * * 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK). + * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN + * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK */ -/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t init_key) { - ble_hs_cfg.sm_their_key_dist = init_key; +/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { + ble_hs_cfg.sm_their_key_dist = resp_key; } // setsSecurityRespKey /** - * @brief Set the passkey for pairing. + * @brief Set the passkey the server will ask for when pairing. + * @param [in] pin The passkey to use. */ /*STATIC*/void NimBLEDevice::setSecurityPasskey(uint32_t pin) { m_passkey = pin; @@ -604,7 +647,8 @@ bool NimBLEDevice::getInitialized() { /** - * @brief Get the passkey for pairing. + * @brief Get the current passkey used for pairing. + * @return The current passkey. */ /*STATIC*/uint32_t NimBLEDevice::getSecurityPasskey() { return m_passkey; @@ -613,7 +657,8 @@ bool NimBLEDevice::getInitialized() { /** * @brief Set callbacks that will be used to handle encryption negotiation events and authentication events - * @param [in] cllbacks Pointer to NimBLESecurityCallbacks class + * @param [in] callbacks Pointer to NimBLESecurityCallbacks class + * @deprecated For backward compatibility, New code should use client/server callback methods. */ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { NimBLEDevice::m_securityCallbacks = callbacks; @@ -622,8 +667,8 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { /** * @brief Start the connection securing and authorization for this connection. - * @param Connection id of the client. - * @returns host return code 0 if success. + * @param conn_id The connection id of the peer device. + * @returns NimBLE stack return code, 0 = success. */ /* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { /* if(m_securityCallbacks != nullptr) { @@ -641,6 +686,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { /** * @brief Check if the device address is on our ignore list. + * @param [in] address The address to look for. * @return True if ignoring. */ /*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) { @@ -656,7 +702,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { /** * @brief Add a device to the ignore list. - * @param Address of the device we want to ignore. + * @param [in] address The address of the device we want to ignore. */ /*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { m_ignoreList.push_back(address); @@ -665,7 +711,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { /** * @brief Remove a device from the ignore list. - * @param Address of the device we want to remove from the list. + * @param [in] address The address of the device we want to remove from the list. */ /*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) { for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) { @@ -679,6 +725,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { /** * @brief Set a custom callback for gap events. + * @param [in] handler The function to call when gap events occur. */ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { m_customGapHandler = handler; diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index 4126479..767f825 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -81,13 +81,13 @@ #define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS #endif -/** - * @brief BLE functions. - */ - typedef int (*gap_event_handler)(ble_gap_event *event, void *arg); +typedef int (*gap_event_handler)(ble_gap_event *event, void *arg); extern "C" void ble_store_config_init(void); +/** + * @brief A model of a %BLE Device from which all the BLE roles are created. + */ class NimBLEDevice { public: static void init(const std::string &deviceName); @@ -181,8 +181,6 @@ private: static NimBLESecurityCallbacks* m_securityCallbacks; static uint32_t m_passkey; static ble_gap_event_listener m_listener; - -public: static gap_event_handler m_customGapHandler; }; diff --git a/src/NimBLEEddystoneTLM.cpp b/src/NimBLEEddystoneTLM.cpp index 990a36f..a072942 100644 --- a/src/NimBLEEddystoneTLM.cpp +++ b/src/NimBLEEddystoneTLM.cpp @@ -24,7 +24,9 @@ static const char LOG_TAG[] = "NimBLEEddystoneTLM"; - +/** + * @brief Construct a default EddystoneTLM beacon object. + */ NimBLEEddystoneTLM::NimBLEEddystoneTLM() { beaconUUID = 0xFEAA; m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE; @@ -35,34 +37,73 @@ NimBLEEddystoneTLM::NimBLEEddystoneTLM() { m_eddystoneData.tmil = 0; } // NimBLEEddystoneTLM + +/** + * @brief Retrieve the data that is being advertised. + * @return The advertised data. + */ std::string NimBLEEddystoneTLM::getData() { return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); } // getData + +/** + * @brief Get the UUID being advertised. + * @return The UUID advertised. + */ NimBLEUUID NimBLEEddystoneTLM::getUUID() { return NimBLEUUID(beaconUUID); } // getUUID + +/** + * @brief Get the version being advertised. + * @return The version number. + */ uint8_t NimBLEEddystoneTLM::getVersion() { return m_eddystoneData.version; } // getVersion + +/** + * @brief Get the battery voltage. + * @return The battery voltage. + */ uint16_t NimBLEEddystoneTLM::getVolt() { return ENDIAN_CHANGE_U16(m_eddystoneData.volt); } // getVolt + +/** + * @brief Get the temperature being advertised. + * @return The temperature value. + */ float NimBLEEddystoneTLM::getTemp() { return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f; } // getTemp +/** + * @brief Get the count of advertisments sent. + * @return The number of advertisments. + */ uint32_t NimBLEEddystoneTLM::getCount() { return ENDIAN_CHANGE_U32(m_eddystoneData.advCount); } // getCount + +/** + * @brief Get the advertisment time. + * @return The advertisment time. + */ uint32_t NimBLEEddystoneTLM::getTime() { return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10; } // getTime + +/** + * @brief Get a string representation of the beacon. + * @return The string representation. + */ std::string NimBLEEddystoneTLM::toString() { std::string out = ""; uint32_t rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil); @@ -113,8 +154,10 @@ std::string NimBLEEddystoneTLM::toString() { return out; } // toString + /** - * Set the raw data for the beacon record. + * @brief Set the raw data for the beacon advertisment. + * @param [in] data The raw data to advertise. */ void NimBLEEddystoneTLM::setData(const std::string &data) { if (data.length() != sizeof(m_eddystoneData)) { @@ -125,26 +168,56 @@ void NimBLEEddystoneTLM::setData(const std::string &data) { memcpy(&m_eddystoneData, data.data(), data.length()); } // setData + +/** + * @brief Set the UUID to advertise. + * @param [in] l_uuid The UUID. + */ void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) { beaconUUID = l_uuid.getNative()->u16.value; } // setUUID + +/** + * @brief Set the version to advertise. + * @param [in] version The version number. + */ void NimBLEEddystoneTLM::setVersion(uint8_t version) { m_eddystoneData.version = version; } // setVersion + +/** + * @brief Set the battery voltage to advertise. + * @param [in] volt The voltage in millivolts. + */ void NimBLEEddystoneTLM::setVolt(uint16_t volt) { m_eddystoneData.volt = volt; } // setVolt + +/** + * @brief Set the temperature to advertise. + * @param [in] temp The temperature value. + */ void NimBLEEddystoneTLM::setTemp(float temp) { m_eddystoneData.temp = (uint16_t)temp; } // setTemp + +/** + * @brief Set the advertisment count. + * @param [in] advCount The advertisment number. + */ void NimBLEEddystoneTLM::setCount(uint32_t advCount) { m_eddystoneData.advCount = advCount; } // setCount + +/** + * @brief Set the advertisment time. + * @param [in] tmil The advertisment time in milliseconds. + */ void NimBLEEddystoneTLM::setTime(uint32_t tmil) { m_eddystoneData.tmil = tmil; } // setTime diff --git a/src/NimBLEEddystoneURL.cpp b/src/NimBLEEddystoneURL.cpp index ce79759..7c3194c 100644 --- a/src/NimBLEEddystoneURL.cpp +++ b/src/NimBLEEddystoneURL.cpp @@ -21,6 +21,10 @@ static const char LOG_TAG[] = "NimBLEEddystoneURL"; + +/** + * @brief Construct a default EddystoneURL beacon object. + */ NimBLEEddystoneURL::NimBLEEddystoneURL() { beaconUUID = 0xFEAA; lengthURL = 0; @@ -29,22 +33,47 @@ NimBLEEddystoneURL::NimBLEEddystoneURL() { memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url)); } // BLEEddystoneURL + +/** + * @brief Retrieve the data that is being advertised. + * @return The advertised data. + */ std::string NimBLEEddystoneURL::getData() { return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData)); } // getData + +/** + * @brief Get the UUID being advertised. + * @return The UUID advertised. + */ NimBLEUUID NimBLEEddystoneURL::getUUID() { return NimBLEUUID(beaconUUID); } // getUUID + +/** + * @brief Get the transmit power being advertised. + * @return The transmit power. + */ int8_t NimBLEEddystoneURL::getPower() { return m_eddystoneData.advertisedTxPower; } // getPower + +/** + * @brief Get the raw URL being advertised. + * @return The raw URL. + */ std::string NimBLEEddystoneURL::getURL() { return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url)); } // getURL + +/** + * @brief Get the full URL being advertised. + * @return The full URL. + */ std::string NimBLEEddystoneURL::getDecodedURL() { std::string decodedURL = ""; @@ -123,7 +152,8 @@ std::string NimBLEEddystoneURL::getDecodedURL() { /** - * Set the raw data for the beacon record. + * @brief Set the raw data for the beacon advertisment. + * @param [in] data The raw data to advertise. */ void NimBLEEddystoneURL::setData(const std::string &data) { if (data.length() > sizeof(m_eddystoneData)) { @@ -136,14 +166,29 @@ void NimBLEEddystoneURL::setData(const std::string &data) { lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url)); } // setData + +/** + * @brief Set the UUID to advertise. + * @param [in] l_uuid The UUID. + */ void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) { beaconUUID = l_uuid.getNative()->u16.value; } // setUUID + +/** + * @brief Set the transmit power to advertise. + * @param [in] advertisedTxPower The transmit power level. + */ void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) { m_eddystoneData.advertisedTxPower = advertisedTxPower; } // setPower + +/** + * @brief Set the URL to advertise. + * @param [in] url The URL. + */ void NimBLEEddystoneURL::setURL(const std::string &url) { if (url.length() > sizeof(m_eddystoneData.url)) { NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d", diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 23089ca..b044bd4 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -260,13 +260,12 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU /** - * @Get a pointer to the vector of found descriptors. - * @param [in] bool value to indicate if the current vector should be cleared and - * subsequently all descriptors for this characteristic retrieved from the peripheral. - * If false the vector will be returned with the currently stored descriptors, - * if the vector is empty it will retrieve all descriptors for this characteristic - * from the peripheral. - * @return a pointer to the vector of descriptors for this characteristic. + * @brief Get a pointer to the vector of found descriptors. + * @param [in] refresh If true the current descriptor vector will be cleared and\n + * all descriptors for this characteristic retrieved from the peripheral.\n + * If false the vector will be returned with the currently stored descriptors + * of this characteristic. + * @return A pointer to the vector of descriptors for this characteristic. */ std::vector* NimBLERemoteCharacteristic::getDescriptors(bool refresh) { if(refresh) { @@ -338,6 +337,7 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() { /** * @brief Get the value of the remote characteristic. + * @param [in] timestamp A pointer to a time_t struct to store the time the value was read. * @return The value of the remote characteristic. */ std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { @@ -355,6 +355,7 @@ std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { /** * @brief Read an unsigned 16 bit value * @return The unsigned 16 bit value. + * @deprecated Use readValue(). */ uint16_t NimBLERemoteCharacteristic::readUInt16() { return readValue(); @@ -364,6 +365,7 @@ uint16_t NimBLERemoteCharacteristic::readUInt16() { /** * @brief Read an unsigned 32 bit value. * @return the unsigned 32 bit value. + * @deprecated Use readValue(). */ uint32_t NimBLERemoteCharacteristic::readUInt32() { return readValue(); @@ -373,6 +375,7 @@ uint32_t NimBLERemoteCharacteristic::readUInt32() { /** * @brief Read a byte value * @return The value as a byte + * @deprecated Use readValue(). */ uint8_t NimBLERemoteCharacteristic::readUInt8() { return readValue(); @@ -390,6 +393,7 @@ float NimBLERemoteCharacteristic::readFloat() { /** * @brief Read the value of the remote characteristic. + * @param [in] timestamp A pointer to a time_t struct to store the time the value was read. * @return The value of the remote characteristic. */ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { @@ -458,7 +462,7 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { /** * @brief Callback for characteristic read operation. - * @return 0 or error code. + * @return success == 0 or error code. */ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, @@ -498,9 +502,10 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, /** * @brief Subscribe or unsubscribe for notifications or indications. - * @param [in] uint16_t val 0x00 to unsubscribe, 0x01 for notifications, 0x02 for indications. - * @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then no callback - * is performed for notifications. + * @param [in] val 0x00 to unsubscribe, 0x01 for notifications, 0x02 for indications. + * @param [in] response If write response required set this to true. + * @param [in] notifyCallback A callback to be invoked for a notification. + * If NULL is provided then no callback is performed. * @return true if successful. */ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, bool response, notify_callback notifyCallback) { @@ -522,10 +527,10 @@ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, bool response, notify_c /** * @brief Subscribe for notifications or indications. - * @param [in] bool if true, subscribe for notifications, false subscribe for indications. - * @param [in] bool if true, require a write response from the descriptor write operation. - * @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then no callback - * is performed for notifications. + * @param [in] notifications If true, subscribe for notifications, false subscribe for indications. + * @param [in] response If true, require a write response from the descriptor write operation. + * @param [in] notifyCallback A callback to be invoked for a notification. + * If NULL is provided then no callback is performed. * @return true if successful. */ bool NimBLERemoteCharacteristic::subscribe(bool notifications, bool response, notify_callback notifyCallback) { @@ -539,7 +544,7 @@ bool NimBLERemoteCharacteristic::subscribe(bool notifications, bool response, no /** * @brief Unsubscribe for notifications or indications. - * @param [in] bool if true, require a write response from the descriptor write operation. + * @param [in] response bool if true, require a write response from the descriptor write operation. * @return true if successful. */ bool NimBLERemoteCharacteristic::unsubscribe(bool response) { @@ -549,11 +554,12 @@ bool NimBLERemoteCharacteristic::unsubscribe(bool response) { /** * @brief backward-compatibility method for subscribe/unsubscribe notifications/indications - * @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then we are - * unregistering for notifications. - * @param [in] bool if true, register for notifications, false register for indications. - * @param [in] bool if true, require a write response from the descriptor write operation. + * @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then we + * will unregister for notifications. + * @param [in] notifications If true, register for notifications, false register for indications. + * @param [in] response If true, require a write response from the descriptor write operation. * @return true if successful. + * @deprecated Use subscribe() / unsubscribe() instead. */ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications, bool response) { bool success; @@ -568,10 +574,9 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac /** * @brief Delete the descriptors in the descriptor vector. - * We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors + * @details We maintain a vector called m_descriptorVector that contains pointers to NimBLERemoteDescriptors * object references. Since we allocated these in this class, we are also responsible for deleting * them. This method does just that. - * @return N/A. */ void NimBLERemoteCharacteristic::deleteDescriptors() { NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptors"); @@ -587,7 +592,7 @@ void NimBLERemoteCharacteristic::deleteDescriptors() { /** * @brief Delete descriptor by UUID * @param [in] uuid The UUID of the descriptor to be deleted. - * @return Number of services left. + * @return Number of descriptors left in the vector. */ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) { NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptor"); @@ -607,7 +612,7 @@ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) { /** - * @brief Convert a BLERemoteCharacteristic to a string representation; + * @brief Convert a NimBLERemoteCharacteristic to a string representation; * @return a String representation. */ std::string NimBLERemoteCharacteristic::toString() { @@ -725,7 +730,7 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, /** * @brief Callback for characteristic write operation. - * @return 0 or error code. + * @return success == 0 or error code. */ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 364efb5..df2d6de 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -63,6 +63,15 @@ public: NimBLEUUID getUUID(); std::string readValue(time_t *timestamp = nullptr); + /** + * @brief A template to convert the remote characteristic data to . + * @tparam T The type to convert the data to. + * @param [in] timestamp A pointer to a time_t struct to store the time the value was read. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: readValue(×tamp, skipSizeCheck); + */ template T readValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) { std::string value = readValue(timestamp); @@ -77,6 +86,15 @@ public: float readFloat() __attribute__ ((deprecated("Use template readValue()"))); std::string getValue(time_t *timestamp = nullptr); + /** + * @brief A template to convert the remote characteristic data to . + * @tparam T The type to convert the data to. + * @param [in] timestamp A pointer to a time_t struct to store the time the value was read. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: getValue(×tamp, skipSizeCheck); + */ template T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) { std::string value = getValue(timestamp); @@ -98,6 +116,11 @@ public: bool response = false); bool writeValue(const std::string &newValue, bool response = false); + /** + * @brief Convenience template to set the remote characteristic value to val. + * @param [in] s The value to write. + * @param [in] response True == request write response. + */ template bool writeValue(const T &s, bool response = false) { return writeValue((uint8_t*)&s, sizeof(T), response); diff --git a/src/NimBLERemoteDescriptor.cpp b/src/NimBLERemoteDescriptor.cpp index d17ae6a..9281e7d 100644 --- a/src/NimBLERemoteDescriptor.cpp +++ b/src/NimBLERemoteDescriptor.cpp @@ -25,8 +25,8 @@ static const char* LOG_TAG = "NimBLERemoteDescriptor"; /** * @brief Remote descriptor constructor. - * @param [in] Reference to the Characteristic that this belongs to. - * @param [in] Reference to the struct that contains the descriptor information. + * @param [in] pRemoteCharacteristic A pointer to the Characteristic that this belongs to. + * @param [in] dsc A pointer to the struct that contains the descriptor information. */ NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, const struct ble_gatt_dsc *dsc) @@ -78,6 +78,11 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() { } // getUUID +/** + * @brief Read a byte value + * @return The value as a byte + * @deprecated Use readValue(). + */ uint8_t NimBLERemoteDescriptor::readUInt8() { std::string value = readValue(); if (value.length() >= 1) { @@ -87,6 +92,11 @@ uint8_t NimBLERemoteDescriptor::readUInt8() { } // readUInt8 +/** + * @brief Read an unsigned 16 bit value + * @return The unsigned 16 bit value. + * @deprecated Use readValue(). + */ uint16_t NimBLERemoteDescriptor::readUInt16() { std::string value = readValue(); if (value.length() >= 2) { @@ -96,6 +106,11 @@ uint16_t NimBLERemoteDescriptor::readUInt16() { } // readUInt16 +/** + * @brief Read an unsigned 32 bit value. + * @return the unsigned 32 bit value. + * @deprecated Use readValue(). + */ uint32_t NimBLERemoteDescriptor::readUInt32() { std::string value = readValue(); if (value.length() >= 4) { @@ -105,6 +120,10 @@ uint32_t NimBLERemoteDescriptor::readUInt32() { } // readUInt32 +/** + * @brief Read the value of the remote descriptor. + * @return The value of the remote descriptor. + */ std::string NimBLERemoteDescriptor::readValue() { NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str()); @@ -161,7 +180,7 @@ std::string NimBLERemoteDescriptor::readValue() { /** * @brief Callback for Descriptor read operation. - * @return 0 or error code. + * @return success == 0 or error code. */ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, @@ -200,8 +219,8 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle, /** - * @brief Return a string representation of this BLE Remote Descriptor. - * @retun A string representation of this BLE Remote Descriptor. + * @brief Return a string representation of this Remote Descriptor. + * @return A string representation of this Remote Descriptor. */ std::string NimBLERemoteDescriptor::toString() { std::string res = "Descriptor: uuid: " + getUUID().toString(); @@ -216,7 +235,7 @@ std::string NimBLERemoteDescriptor::toString() { /** * @brief Callback for descriptor write operation. - * @return 0 or error code. + * @return success == 0 or error code. */ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, @@ -242,7 +261,8 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle, * @brief Write data to the BLE Remote Descriptor. * @param [in] data The data to send to the remote descriptor. * @param [in] length The length of the data to send. - * @param [in] response True if we expect a response. + * @param [in] response True if we expect a write response. + * @return True if successful */ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) { @@ -322,11 +342,11 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool * @brief Write data represented as a string to the BLE Remote Descriptor. * @param [in] newValue The data to send to the remote descriptor. * @param [in] response True if we expect a response. + * @return True if successful */ bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) { return writeValue((uint8_t*) newValue.data(), newValue.length(), response); } // writeValue - #endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED */ diff --git a/src/NimBLERemoteDescriptor.h b/src/NimBLERemoteDescriptor.h index 554e9dc..b52738e 100644 --- a/src/NimBLERemoteDescriptor.h +++ b/src/NimBLERemoteDescriptor.h @@ -33,6 +33,14 @@ public: NimBLEUUID getUUID(); std::string readValue(); + /** + * @brief A template to convert the remote descriptor data to . + * @tparam T The type to convert the data to. + * @param [in] skipSizeCheck If true it will skip checking if the data size is less than sizeof(). + * @return The data converted to or NULL if skipSizeCheck is false and the data is + * less than sizeof(). + * @details Use: readValue(skipSizeCheck); + */ template T readValue(bool skipSizeCheck = false) { std::string value = readValue(); @@ -41,12 +49,18 @@ public: return *((T *)pData); } - uint8_t readUInt8() __attribute__ ((deprecated)); - uint16_t readUInt16() __attribute__ ((deprecated)); - uint32_t readUInt32() __attribute__ ((deprecated)); + uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue()"))); + uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue()"))); + uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue()"))); std::string toString(void); bool writeValue(const uint8_t* data, size_t length, bool response = false); bool writeValue(const std::string &newValue, bool response = false); + + /** + * @brief Convenience template to set the remote descriptor value to val. + * @param [in] s The value to write. + * @param [in] response True == request write response. + */ template bool writeValue(const T &s, bool response = false) { return writeValue((uint8_t*)&s, sizeof(T), response); diff --git a/src/NimBLERemoteService.cpp b/src/NimBLERemoteService.cpp index db9eabc..8901175 100644 --- a/src/NimBLERemoteService.cpp +++ b/src/NimBLERemoteService.cpp @@ -26,8 +26,8 @@ static const char* LOG_TAG = "NimBLERemoteService"; /** * @brief Remote Service constructor. - * @param [in] Reference to the client this belongs to. - * @param [in] Refernce to the structure with the services' information. + * @param [in] pClient A pointer to the client this belongs to. + * @param [in] service A pointer to the structure with the service information. */ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) { @@ -55,7 +55,6 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble /** * @brief When deleting the service make sure we delete all characteristics and descriptors. - * Also release any semaphores they may be holding. */ NimBLERemoteService::~NimBLERemoteService() { deleteCharacteristics(); @@ -83,7 +82,7 @@ std::vector::iterator NimBLERemoteService::end() { /** * @brief Get the remote characteristic object for the characteristic UUID. * @param [in] uuid Remote characteristic uuid. - * @return Reference to the remote characteristic object. + * @return A pointer to the remote characteristic object. */ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) { return getCharacteristic(NimBLEUUID(uuid)); @@ -93,7 +92,7 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u /** * @brief Get the characteristic object for the UUID. * @param [in] uuid Characteristic uuid. - * @return Reference to the characteristic object, or nullptr if not found. + * @return A pointer to the characteristic object, or nullptr if not found. */ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) { for(auto &it: m_characteristicVector) { @@ -114,15 +113,12 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU /** - * @Get a pointer to the vector of found characteristics. - * @param [in] bool value to indicate if the current vector should be cleared and - * subsequently all characteristics for this service retrieved from the peripheral. - * If false the vector will be returned with the currently stored characteristics, - * If true it will retrieve all characteristics of this service from the peripheral - * and return the vector with all characteristics for this service. - * @return a pointer to the vector of descriptors for this characteristic. + * @brief Get a pointer to the vector of found characteristics. + * @param [in] refresh If true the current characteristics vector will cleared and + * all characteristics for this service retrieved from the peripheral. + * If false the vector will be returned with the currently stored characteristics of this service. + * @return A pointer to the vector of descriptors for this characteristic. */ - std::vector* NimBLERemoteService::getCharacteristics(bool refresh) { if(refresh) { deleteCharacteristics(); @@ -140,6 +136,7 @@ std::vector* NimBLERemoteService::getCharacteristic /** * @brief Callback for Characterisic discovery. + * @return success == 0 or error code. */ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error, @@ -182,7 +179,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle, /** * @brief Retrieve all the characteristics for this service. * This function will not return until we have all the characteristics. - * @return N/A + * @return True if successful. */ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) { NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str()); @@ -299,10 +296,9 @@ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const s /** * @brief Delete the characteristics in the characteristics vector. - * We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic + * @details We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic * object references. Since we allocated these in this class, we are also responsible for deleting * them. This method does just that. - * @return N/A. */ void NimBLERemoteService::deleteCharacteristics() { NIMBLE_LOGD(LOG_TAG, ">> deleteCharacteristics"); @@ -316,7 +312,7 @@ void NimBLERemoteService::deleteCharacteristics() { /** * @brief Delete characteristic by UUID - * @param [in] uuid The UUID of the characteristic to be cleared. + * @param [in] uuid The UUID of the characteristic to be removed from the local database. * @return Number of characteristics left. */ size_t NimBLERemoteService::deleteCharacteristic(const NimBLEUUID &uuid) { diff --git a/src/NimBLERemoteService.h b/src/NimBLERemoteService.h index 2d63c5d..751c9ef 100644 --- a/src/NimBLERemoteService.h +++ b/src/NimBLERemoteService.h @@ -45,7 +45,7 @@ public: void deleteCharacteristics(); size_t deleteCharacteristic(const NimBLEUUID &uuid); NimBLEClient* getClient(void); - uint16_t getHandle(); + //uint16_t getHandle(); NimBLEUUID getUUID(void); std::string getValue(const NimBLEUUID &characteristicUuid); bool setValue(const NimBLEUUID &characteristicUuid, diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index dbf8874..7e16260 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -151,7 +151,6 @@ 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. * @param [in] active If true, we perform an active scan otherwise a passive scan. - * @return N/A. */ void NimBLEScan::setActiveScan(bool active) { if (active) { @@ -187,18 +186,18 @@ void NimBLEScan::setLimitedOnly(bool active) { /** * @brief Sets the scan filter policy. * @param [in] filter Can be one of: - * BLE_HCI_SCAN_FILT_NO_WL (0) - * Scanner processes all advertising packets (white list not used) except + * * BLE_HCI_SCAN_FILT_NO_WL (0) + * Scanner processes all advertising packets (white list not used) except\n * directed, connectable advertising packets not sent to the scanner. - * BLE_HCI_SCAN_FILT_USE_WL (1) - * Scanner processes advertisements from white list only. A connectable, + * * BLE_HCI_SCAN_FILT_USE_WL (1) + * Scanner processes advertisements from white list only. A connectable,\n * directed advertisment is ignored unless it contains scanners address. - * BLE_HCI_SCAN_FILT_NO_WL_INITA (2) - * Scanner process all advertising packets (white list not used). A + * * BLE_HCI_SCAN_FILT_NO_WL_INITA (2) + * Scanner process all advertising packets (white list not used). A\n * connectable, directed advertisement shall not be ignored if the InitA * is a resolvable private address. - * BLE_HCI_SCAN_FILT_USE_WL_INITA (3) - * Scanner process advertisements from white list only. A connectable, + * * BLE_HCI_SCAN_FILT_USE_WL_INITA (3) + * Scanner process advertisements from white list only. A connectable,\n * directed advertisement shall not be ignored if the InitA is a * resolvable private address. */ @@ -221,7 +220,7 @@ void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* p /** * @brief Set the interval to scan. - * @param [in] The interval in msecs. + * @param [in] intervalMSecs The scan interval (how often) in milliseconds. */ void NimBLEScan::setInterval(uint16_t intervalMSecs) { m_scan_params.itvl = intervalMSecs / 0.625; @@ -241,7 +240,7 @@ void NimBLEScan::setWindow(uint16_t windowMSecs) { * @brief Start scanning. * @param [in] duration The duration in seconds for which to scan. * @param [in] scanCompleteCB A function to be called when scanning has completed. - * @param [in] are we continue scan (true) or we want to clear stored devices (false) + * @param [in] is_continue Set to true to save previous scan results, false to clear them. * @return True if scan started or false if there was an error. */ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) { @@ -309,7 +308,8 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul /** * @brief Start scanning and block until scanning has been completed. * @param [in] duration The duration in seconds for which to scan. - * @return The BLEScanResults. + * @param [in] is_continue Set to true to save previous scan results, false to clear them. + * @return The NimBLEScanResults. */ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) { if(duration == 0) { @@ -330,7 +330,7 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) { /** * @brief Stop an in progress scan. - * @return N/A. + * @return True if successful. */ bool NimBLEScan::stop() { NIMBLE_LOGD(LOG_TAG, ">> stop()"); @@ -356,7 +356,11 @@ bool NimBLEScan::stop() { } // stop -// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address +/** + * @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()); @@ -371,8 +375,7 @@ void NimBLEScan::erase(const NimBLEAddress &address) { /** - * @brief If the host reset the scan will have stopped so we should flag it and release the semaphore. - * @return N/A. + * @brief If the host reset the scan will have stopped so we should set the flag as stopped. */ void NimBLEScan::onHostReset() { m_stopped = true; @@ -411,7 +414,7 @@ void NimBLEScanResults::dump() { /** - * @brief Return the count of devices found in the last scan. + * @brief Get the count of devices found in the last scan. * @return The number of devices found in the last scan. */ int NimBLEScanResults::getCount() { @@ -449,7 +452,7 @@ std::vector::iterator NimBLEScanResults::end() { /** - * @brief Return a pointer to the specified device at the given address. + * @brief Get a pointer to the specified device at the given address. * If the address is not found a nullptr is returned. * @param [in] address The address of the device. * @return A pointer to the device at the specified address. diff --git a/src/NimBLEScan.h b/src/NimBLEScan.h index 5bc7bcf..28abd1c 100644 --- a/src/NimBLEScan.h +++ b/src/NimBLEScan.h @@ -33,9 +33,9 @@ class NimBLEAdvertisedDeviceCallbacks; class NimBLEAddress; /** - * @brief The result of having performed a scan. - * When a scan completes, we have a set of found devices. Each device is described - * by a BLEAdvertisedDevice object. The number of items in the set is given by + * @brief A class that contains and operates on the results of a BLE scan. + * @details When a scan completes, we have a set of found devices. Each device is described + * by a NimBLEAdvertisedDevice object. The number of items in the set is given by * getCount(). We can retrieve a device by calling getDevice() passing in the * index (starting at 0) of the desired device. */ diff --git a/src/NimBLESecurity.cpp b/src/NimBLESecurity.cpp index 8a0dbd9..aa06296 100644 --- a/src/NimBLESecurity.cpp +++ b/src/NimBLESecurity.cpp @@ -18,12 +18,6 @@ #include "NimBLESecurity.h" #include "NimBLEDevice.h" -/** - * @brief This class is for backward compatibility with the bluedroid based library. - * Use the new security functions in NimBLEDevice instead. - * New callback functions in NimBLEServer and NimBLEClient. - */ - NimBLESecurity::NimBLESecurity() { } @@ -33,6 +27,15 @@ NimBLESecurity::~NimBLESecurity() { /** * @brief Set requested authentication mode + * @param [in] auth_req A bitmask containing one or more of: + * * ESP_LE_AUTH_NO_BOND 0x00 + * * ESP_LE_AUTH_BOND 0x01 + * * ESP_LE_AUTH_REQ_MITM (1 << 2) + * * ESP_LE_AUTH_REQ_BOND_MITM (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM) + * * ESP_LE_AUTH_REQ_SC_ONLY (1 << 3) + * * ESP_LE_AUTH_REQ_SC_BOND (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY) + * * ESP_LE_AUTH_REQ_SC_MITM (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY) + * * ESP_LE_AUTH_REQ_SC_MITM_BOND (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY | ESP_LE_AUTH_BOND) */ void NimBLESecurity::setAuthenticationMode(esp_ble_auth_req_t auth_req) { NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, @@ -42,8 +45,15 @@ void NimBLESecurity::setAuthenticationMode(esp_ble_auth_req_t auth_req) { /** - * @brief Set our device IO capability to let end user perform authorization - * either by displaying or entering generated 6-digits pin code + * @brief Set our device IO capability to let end user perform authorization + * either by displaying or entering generated 6-digit pin code or use \"just works\". + * @param [in] iocap The IO capabilites our device has.\n + * Can be set to one of: + * * ESP_IO_CAP_OUT 0 + * * ESP_IO_CAP_IO 1 + * * ESP_IO_CAP_IN 2 + * * ESP_IO_CAP_NONE 3 + * * ESP_IO_CAP_KBDISP 4 */ void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) { NimBLEDevice::setSecurityIOCap(iocap); @@ -51,8 +61,13 @@ void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) { /** - * @brief Init encryption key by server - * @param key_size is value between 7 and 16 + * @brief Sets the keys we will distibute during encryption. + * @param [in] init_key A bitmask of the keys we will distibute.\n + * Can be one or more of: + * * ESP_BLE_ENC_KEY_MASK (1 << 0) + * * ESP_BLE_ID_KEY_MASK (1 << 1) + * * ESP_BLE_CSR_KEY_MASK (1 << 2) + * * ESP_BLE_LINK_KEY_MASK (1 << 3) */ void NimBLESecurity::setInitEncryptionKey(uint8_t init_key) { NimBLEDevice::setSecurityInitKey(init_key); @@ -60,8 +75,13 @@ void NimBLESecurity::setInitEncryptionKey(uint8_t init_key) { /** - * @brief Init encryption key by client - * @param key_size is value between 7 and 16 + * @brief Sets the keys we will accept during encryption. + * @param [in] resp_key A bitmask of the keys we will accept.\n + * Can be one or more of: + * * ESP_BLE_ENC_KEY_MASK (1 << 0) + * * ESP_BLE_ID_KEY_MASK (1 << 1) + * * ESP_BLE_CSR_KEY_MASK (1 << 2) + * * ESP_BLE_LINK_KEY_MASK (1 << 3) */ void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) { NimBLEDevice::setSecurityRespKey(resp_key); @@ -70,7 +90,6 @@ void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) { /** *@todo Requires implementation - * */ void NimBLESecurity::setKeySize(uint8_t key_size) { @@ -80,7 +99,8 @@ void NimBLESecurity::setKeySize(uint8_t key_size) { /** - * Setup for static PIN connection. + * @brief Sets a static PIN used to authenticate/encrypt the connection. + * @param [in] pin The 6 digit pin code to accept. */ void NimBLESecurity::setStaticPIN(uint32_t pin){ //uint32_t passkey = pin; diff --git a/src/NimBLESecurity.h b/src/NimBLESecurity.h index 50c732c..5a7619f 100644 --- a/src/NimBLESecurity.h +++ b/src/NimBLESecurity.h @@ -12,10 +12,6 @@ * Author: chegewara */ -/** This class exists for backward compatibility - Should not be used in new code - * See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient - */ - #ifndef COMPONENTS_NIMBLESECURITY_H_ #define COMPONENTS_NIMBLESECURITY_H_ #include "sdkconfig.h" @@ -56,6 +52,12 @@ typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit pattern */ typedef uint8_t esp_ble_io_cap_t; /*!< combination of the io capability */ + +/** + * @brief A class to handle BLE security operations. + * Deprecated - provided for backward compatibility only. + * @deprecated Use the security methods provided in NimBLEDevice instead. + */ class NimBLESecurity { public: NimBLESecurity(); @@ -78,8 +80,10 @@ private: }; // BLESecurity -/* - * @brief Callbacks to handle GAP events related to authorization +/** + * @brief Callbacks to handle GAP events related to authorization. + * Deprecated - provided for backward compatibility only. + * @deprecated Use the callbacks provided in NimBLEClientCallbacks and NimBLEServerCallbacks instead. */ class NimBLESecurityCallbacks { public: @@ -95,21 +99,25 @@ public: /** * @brief Provide us 6-digits code to perform authentication. * It requires that our device is capable to display this code to end user - * @param + * @param [in] pass_key The PIN provided by the peer. */ virtual void onPassKeyNotify(uint32_t pass_key) = 0; /** * @brief Here we can make decision if we want to let negotiate authorization with peer device or not - * return Return true if we accept this peer device request + * @return Return true if we accept this peer device request */ - virtual bool onSecurityRequest() = 0 ; /** - * Provide us information when authentication process is completed + * @brief Provides us information when authentication process is completed */ virtual void onAuthenticationComplete(ble_gap_conn_desc*) = 0; + /** + * @brief Called when using numeric comparison for authentication. + * @param [in] pin The PIN to compare. + * @return True to accept and pair. + */ virtual bool onConfirmPIN(uint32_t pin) = 0; }; // BLESecurityCallbacks diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 376b021..2a9bd13 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -168,8 +168,8 @@ void NimBLEServer::start() { /** * @brief Disconnect the specified client with optional reason. - * @param [in] Connection Id of the client to disconnect. - * @param [in] Reason code for disconnecting. + * @param [in] connId Connection Id of the client to disconnect. + * @param [in] reason code for disconnecting. * @return NimBLE host return code. */ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) { @@ -188,7 +188,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) { /** * @brief Set the server to automatically start advertising when a client disconnects. - * @param [in] bool true == advertise, false == don't advertise. + * @param [in] aod true == advertise, false == don't advertise. */ void NimBLEServer::advertiseOnDisconnect(bool aod) { m_advertiseOnDisconnect = aod; @@ -516,7 +516,7 @@ uint32_t NimBLEServerCallbacks::onPassKeyRequest(){ NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyRequest: default: 123456"); return 123456; } - +/* void NimBLEServerCallbacks::onPassKeyNotify(uint32_t pass_key){ NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyNotify: default: %d", pass_key); } @@ -525,6 +525,7 @@ bool NimBLEServerCallbacks::onSecurityRequest(){ NIMBLE_LOGD("NimBLEServerCallbacks", "onSecurityRequest: default: true"); return true; } +*/ void NimBLEServerCallbacks::onAuthenticationComplete(ble_gap_conn_desc*){ NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default"); } diff --git a/src/NimBLEServer.h b/src/NimBLEServer.h index cfaa8ac..44e98ea 100644 --- a/src/NimBLEServer.h +++ b/src/NimBLEServer.h @@ -54,7 +54,7 @@ public: uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout); uint16_t getPeerMTU(uint16_t conn_id); - std::vector getPeerDevices(); +// std::vector getPeerDevices(); void advertiseOnDisconnect(bool); private: @@ -83,29 +83,52 @@ private: class NimBLEServerCallbacks { public: virtual ~NimBLEServerCallbacks() {}; + /** - * @brief Handle a new client connection. - * - * When a new client connects, we are invoked. - * - * @param [in] pServer A reference to the %BLE server that received the client connection. + * @brief Handle a client connection. + * This is called when a client connects. + * @param [in] pServer A pointer to the %BLE server that received the client connection. */ virtual void onConnect(NimBLEServer* pServer); - virtual void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc); + /** - * @brief Handle an existing client disconnection. - * - * When an existing client disconnects, we are invoked. - * + * @brief Handle a client connection. + * This is called when a client connects. + * @param [in] pServer A pointer to the %BLE server that received the client connection. + * @param [in] desc A pointer to the connection description structure containig information + * about the connection parameters. + */ + virtual void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc); + + /** + * @brief Handle a client disconnection. + * This is called when a client disconnects. * @param [in] pServer A reference to the %BLE server that received the existing client disconnection. */ virtual void onDisconnect(NimBLEServer* pServer); - virtual uint32_t onPassKeyRequest(); //{return 0;} - virtual void onPassKeyNotify(uint32_t pass_key); //{} - virtual bool onSecurityRequest(); //{return true;} - virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);//{}; - virtual bool onConfirmPIN(uint32_t pin);//{return true;} + /** + * @brief Called when a client requests a passkey for pairing. + * @return The passkey to be sent to the client. + */ + virtual uint32_t onPassKeyRequest(); + + //virtual void onPassKeyNotify(uint32_t pass_key); + //virtual bool onSecurityRequest(); + + /** + * @brief Called when the pairing procedure is complete. + * @param [in] desc A pointer to the struct containing the connection information.\n + * This can be used to check the status of the connection encryption/pairing. + */ + virtual void onAuthenticationComplete(ble_gap_conn_desc* desc); + + /** + * @brief Called when using numeric comparision for pairing. + * @param [in] pin The pin to compare with the client. + * @return True to accept the pin. + */ + virtual bool onConfirmPIN(uint32_t pin); }; // NimBLEServerCallbacks diff --git a/src/NimBLEService.cpp b/src/NimBLEService.cpp index c2631ab..35bbdf3 100644 --- a/src/NimBLEService.cpp +++ b/src/NimBLEService.cpp @@ -238,11 +238,21 @@ 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)); } +/** + * @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 NimBLEUUID &uuid) { for (auto &it : m_chrVec) { if (it->getUUID() == uuid) { diff --git a/src/NimBLEUUID.cpp b/src/NimBLEUUID.cpp index 4a9d7e8..f008e20 100644 --- a/src/NimBLEUUID.cpp +++ b/src/NimBLEUUID.cpp @@ -73,15 +73,11 @@ static const char* LOG_TAG = "NimBLEUUID"; /** * @brief Create a UUID from 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) { -/*** TODO: change this to use the Nimble function for various lenght UUIDs: - int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len); -***/ if (size != 16) { NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes"); return; @@ -99,7 +95,6 @@ NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) { /** * @brief Create a UUID from the 16bit value. - * * @param [in] uuid The 16bit short form UUID. */ NimBLEUUID::NimBLEUUID(uint16_t uuid) { @@ -111,7 +106,6 @@ NimBLEUUID::NimBLEUUID(uint16_t uuid) { /** * @brief Create a UUID from the 32bit value. - * * @param [in] uuid The 32bit short form UUID. */ NimBLEUUID::NimBLEUUID(uint32_t uuid) { @@ -123,7 +117,6 @@ NimBLEUUID::NimBLEUUID(uint32_t uuid) { /** * @brief Create a UUID from the native UUID. - * * @param [in] uuid The native UUID. */ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) { @@ -135,8 +128,8 @@ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) { /** * @brief Create a UUID from the 128bit value using hex parts instead of string, - * instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes - * BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6) + * instead of NimBLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes + * NimBLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6) * * @param [in] first The first 32bit of the UUID. * @param [in] second The next 16bit of the UUID. @@ -153,6 +146,9 @@ NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t } +/** + * @brief Creates an empty UUID. + */ NimBLEUUID::NimBLEUUID() { m_valueSet = false; } // NimBLEUUID @@ -180,29 +176,31 @@ bool NimBLEUUID::equals(const NimBLEUUID &uuid) const { /** - * Create a BLEUUID from a string of the form: + * Create a NimBLEUUID from a string of the form: * 0xNNNN * 0xNNNNNNNN * 0x * NNNN * NNNNNNNN - * + * + * + * @param [in] uuid The string to create the UUID from. */ -NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) { +NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) { uint8_t start = 0; - if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters. + if (strstr(uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters. start = 2; } - uint8_t len = _uuid.length() - start; // Calculate the length of the string we are going to use. + uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use. if(len == 4) { - uint16_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16); + uint16_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16); return NimBLEUUID(x); } else if (len == 8) { - uint32_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16); + uint32_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16); return NimBLEUUID(x); } else if (len == 36) { - return NimBLEUUID(_uuid); + return NimBLEUUID(uuid); } return NimBLEUUID(); } // fromString @@ -210,8 +208,7 @@ NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) { /** * @brief Get the native UUID value. - * - * @return The native UUID value or NULL if not set. + * @return The native UUID value or nullptr if not set. */ const ble_uuid_any_t* NimBLEUUID::getNative() const { if (m_valueSet == false) { @@ -224,9 +221,9 @@ const ble_uuid_any_t* NimBLEUUID::getNative() const { /** * @brief Convert a UUID to its 128 bit representation. - * - * A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method + * @details A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method * will convert 16 or 32 bit representations to the full 128bit. + * @return The NimBLEUUID converted to 128bit. */ const NimBLEUUID &NimBLEUUID::to128() { // If we either don't have a value or are already a 128 bit UUID, nothing further to do. @@ -248,19 +245,23 @@ const NimBLEUUID &NimBLEUUID::to128() { /** * @brief Get a string representation of the UUID. - * + * @details * The format of a string is: * 01234567 8901 2345 6789 012345678901 * 0000180d-0000-1000-8000-00805f9b34fb * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * * @return A string representation of the UUID. + * @deprecated Use std::string() operator instead. */ std::string NimBLEUUID::toString() const { return std::string(*this); } // toString +/** + * @brief Convienience operator to check if this UUID is equal to another. + */ bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const { if(m_valueSet && rhs.m_valueSet) { return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0; @@ -270,11 +271,19 @@ bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const { } +/** + * @brief Convienience operator to check if this UUID is not equal to another. + */ bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const { return !this->operator==(rhs); } +/** + * @brief Convienience operator to convert this UUID to string representation. + * @details This allows passing NimBLEUUID to functions + * that accept std::string and/or or it's methods as a parameter. + */ NimBLEUUID::operator std::string() const { if (!m_valueSet) return std::string(); // If we have no value, nothing to format. diff --git a/src/NimBLEUUID.h b/src/NimBLEUUID.h index f07bb3d..982f9c3 100644 --- a/src/NimBLEUUID.h +++ b/src/NimBLEUUID.h @@ -3,7 +3,7 @@ * * Created: on Jan 24 2020 * Author H2zero - * + * * Originally: * * BLEUUID.h @@ -37,20 +37,21 @@ public: NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst); NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth); NimBLEUUID(); - uint8_t bitSize() const; // Get the number of bits in this uuid. - bool equals(const NimBLEUUID &uuid) const; + + uint8_t bitSize() const; + bool equals(const NimBLEUUID &uuid) const; const ble_uuid_any_t* getNative() const; - const NimBLEUUID & to128(); - std::string toString() const; - static NimBLEUUID fromString(const std::string &uuid); // Create a NimBLEUUID from a string + const NimBLEUUID & to128(); + std::string toString() const; + static NimBLEUUID fromString(const std::string &uuid); bool operator ==(const NimBLEUUID & rhs) const; bool operator !=(const NimBLEUUID & rhs) const; operator std::string() const; private: - ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps. - bool m_valueSet = false; // Is there a value set for this instance. + ble_uuid_any_t m_uuid; + bool m_valueSet = false; }; // NimBLEUUID #endif /* CONFIG_BT_ENABLED */ #endif /* COMPONENTS_NIMBLEUUID_H_ */ diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index 1f1f22c..8a4d60a 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -16,6 +16,11 @@ static const char* LOG_TAG = "NimBLEUtils"; +/** + * @brief A function for checking validity of connection parameters. + * @param [in] params A pointer to the structure containing the parameters to check. + * @return valid == 0 or error code. + */ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) { /* Check connection interval min */ if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || @@ -49,6 +54,11 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) { } +/** + * @brief Converts a return code from the NimBLE stack to a text string. + * @param [in] rc The return code to convert. + * @return A string representation of the return code. + */ const char* NimBLEUtils::returnCodeToString(int rc) { #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) switch(rc) { @@ -338,9 +348,9 @@ const char* NimBLEUtils::returnCodeToString(int rc) { /** - * @brief Convert the BLE Advertising Data flags to a string. - * @param adFlags The flags to convert - * @return std::string A string representation of the advertising flags. + * @brief Convert the advertising type flag to a string. + * @param advType The type to convert. + * @return A string representation of the advertising flags. */ const char* NimBLEUtils::advTypeToString(uint8_t advType) { #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) @@ -367,7 +377,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) { /** * @brief Create a hex representation of data. * - * @param [in] target Where to write the hex string. If this is null, we malloc storage. + * @param [in] target Where to write the hex string. If this is null, we malloc storage. * @param [in] source The start of the binary data. * @param [in] length The length of the data to convert. * @return A pointer to the formatted buffer. @@ -400,6 +410,11 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t } // buildHexData +/** + * @brief Utility function to log the gap event info. + * @param [in] event A pointer to the gap event structure. + * @param [in] arg Unused. + */ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type)); @@ -408,7 +423,7 @@ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ /** - * @brief Convert a BT GAP event type to a string representation. + * @brief Convert a GAP event type to a string representation. * @param [in] eventType The type of event. * @return A string representation of the event type. */ @@ -495,22 +510,29 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) { /** - * Utility function to log an array of bytes. + * @brief Utility function to log an array of bytes. + * @param [in] bytes The buffer to print. + * @param [in] len The length of the buffer. */ void print_bytes(const uint8_t *bytes, int len) { int i; for (i = 0; i < len; i++) { - MODLOG_DFLT(ERROR, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); + NIMBLE_LOGD(LOG_TAG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); if(i % 30 == 0){ - MODLOG_DFLT(ERROR, "\n"); + NIMBLE_LOGD(LOG_TAG, "\n"); } } - MODLOG_DFLT(ERROR, "\n"); + NIMBLE_LOGD(LOG_TAG, "\n"); } + +/** + * @brief Utility function to log an os_mbuf. + * @param [in] om The buffer to print. + */ void print_mbuf(const struct os_mbuf *om) { int colon; @@ -655,20 +677,21 @@ void print_adv_fields(const struct ble_hs_adv_fields *fields) /** - * Logs information about a connection to the console. - */ + * @brief Logs information about a connection to the console. + * @param [in] desc The connection description struct to print. + */ void print_conn_desc(const struct ble_gap_conn_desc *desc) { - MODLOG_DFLT(DEBUG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ", + NIMBLE_LOGD(LOG_TAG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ", desc->conn_handle, desc->our_ota_addr.type, addr_str(desc->our_ota_addr.val)); - MODLOG_DFLT(DEBUG, "our_id_addr_type=%d our_id_addr=%s ", + NIMBLE_LOGD(LOG_TAG, "our_id_addr_type=%d our_id_addr=%s ", desc->our_id_addr.type, addr_str(desc->our_id_addr.val)); - MODLOG_DFLT(DEBUG, "peer_ota_addr_type=%d peer_ota_addr=%s ", + NIMBLE_LOGD(LOG_TAG, "peer_ota_addr_type=%d peer_ota_addr=%s ", desc->peer_ota_addr.type, addr_str(desc->peer_ota_addr.val)); - MODLOG_DFLT(DEBUG, "peer_id_addr_type=%d peer_id_addr=%s ", + NIMBLE_LOGD(LOG_TAG, "peer_id_addr_type=%d peer_id_addr=%s ", desc->peer_id_addr.type, addr_str(desc->peer_id_addr.val)); - MODLOG_DFLT(DEBUG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d " + NIMBLE_LOGD(LOG_TAG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d " "encrypted=%d authenticated=%d bonded=%d", desc->conn_itvl, desc->conn_latency, desc->supervision_timeout, diff --git a/src/NimBLEUtils.h b/src/NimBLEUtils.h index 891f835..babc12b 100644 --- a/src/NimBLEUtils.h +++ b/src/NimBLEUtils.h @@ -35,6 +35,10 @@ void print_addr(const void *addr); void print_bytes(const uint8_t *bytes, int len); } + +/** + * @brief A BLE Utility class with methods for debugging and general purpose use. + */ class NimBLEUtils { public: static void dumpGapEvent(ble_gap_event *event, void *arg);