mirror of https://github.com/arendst/Tasmota.git
update NimBLE-Arduino to 1.0.2
This commit is contained in:
parent
bf115647c3
commit
3368b73753
|
@ -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.
|
|
@ -0,0 +1,38 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.0.2] - 2020-09-13
|
||||
|
||||
### Changed
|
||||
|
||||
- `NimBLEAdvertising::start` Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a
|
||||
callback that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
- (Arduino) Maximum BLE connections can now be altered by only changing the value of `CONFIG_BT_NIMBLE_MAX_CONNECTIONS` in `nimconfig.h`.
|
||||
Any changes to the controller max connection settings in `sdkconfig.h` will now have no effect when using this library.
|
||||
|
||||
- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
|
||||
a task running on core 0 (same as the controller) has been implemented. This improves response times and reliability for all BLE functions.
|
||||
|
||||
## [1.0.1] - 2020-09-02
|
||||
|
||||
### Added
|
||||
|
||||
- Empty `NimBLEAddress` constructor: `NimBLEAddress()` produces an address of 00:00:00:00:00:00 type 0.
|
||||
- Documentation of the difference of NimBLEAddress::getNative vs the original bluedroid library.
|
||||
|
||||
### Changed
|
||||
|
||||
- notify_callback typedef is now defined as std::function to enable the use of std::bind to call a class member function.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix advertising start delay when first called.
|
||||
|
||||
|
||||
## [1.0.0] - 2020-08-22
|
||||
|
||||
First stable release.
|
||||
|
||||
All the original library functionality is complete and many extras added with full documentation.
|
|
@ -1,36 +1,19 @@
|
|||
# *** 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.
|
||||
[Latest release ![Release Version](https://img.shields.io/github/release/h2zero/NimBLE-Arduino.svg?style=plastic)
|
||||
![Release Date](https://img.shields.io/github/release-date/h2zero/NimBLE-Arduino.svg?style=plastic)](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
|
||||
<br/>
|
||||
|
||||
# NimBLE-Arduino
|
||||
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
||||
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
||||
|
||||
**Note for IDF users: This repo will not compile correctly in ESP-IDF. An ESP-IDF component version of this library can be [found here.](https://github.com/h2zero/esp-nimble-cpp)**
|
||||
|
||||
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.
|
||||
to provide improved capabilites and stability over the original.
|
||||
<br/>
|
||||
|
||||
## Resource use improvement:
|
||||
## Resource use improvement
|
||||
|
||||
### (Original) BLE_client example comparison (Debug):
|
||||
#### Arduino BLE Library
|
||||
|
@ -50,21 +33,29 @@ Memory after connection: Free Heap: **173300**
|
|||
Sketch uses **603432** bytes (28%) of program storage space.
|
||||
Memory after connection: Free Heap: **269792**
|
||||
|
||||
**As shown: there is nearly a 50% reduction in flash use and approx. 100kB less ram consumed!**
|
||||
|
||||
|
||||
# Installation:
|
||||
**As shown: there is nearly a 50% reduction in flash use and approx. 100kB less ram consumed!**
|
||||
<br/>
|
||||
|
||||
Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
|
||||
# Installation
|
||||
**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
|
||||
|
||||
**Alternatively:** 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.
|
||||
Tested and working with esp32-arduino in Arduino IDE and platform IO.
|
||||
<br/>
|
||||
|
||||
# Using
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
|
||||
# Usage:
|
||||
If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
|
||||
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
If you are familiar with the original library, see: [The migration guide](docs/Migration_guide.md) for details about breaking changes and migration.
|
||||
|
||||
Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes.
|
||||
|
||||
[Full API documentation and class list can be found here.](https://h2zero.github.io/esp-nimble-cpp/)
|
||||
|
||||
Check the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
||||
|
||||
|
@ -72,26 +63,25 @@ More advanced examples highlighting many available features are in examples/ Nim
|
|||
|
||||
Beacon examples provided by @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 is 3.
|
||||
Change the settings in the `src/nimconfig.h` file to customize NimBLE to your project,
|
||||
such as increasing max connections, default is 3, absolute maximum connections is 9.
|
||||
<br/>
|
||||
|
||||
# Development Status
|
||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@95bd864.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
# Continuing development:
|
||||
|
||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@46c1d9f.](https://github.com/espressif/esp-nimble)
|
||||
|
||||
Also tracking the NimBLE related changes in esp-idf, master branch, currently [@2ef4890.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
|
||||
# Acknowledgments:
|
||||
|
||||
* @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. Create documentation.
|
||||
2. Add BLE Mesh code.
|
||||
3. Expose more NimBLE features.
|
||||
Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@2ef4890.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||
<br/>
|
||||
|
||||
# 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.
|
||||
<br/>
|
||||
|
||||
# Todo
|
||||
- Improve host reset handler
|
||||
- Implement random address handling
|
||||
- Implement bond management
|
||||
- Add Bluetooth Mesh
|
||||
<br/>
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
# Improvements and updates
|
||||
|
||||
Many improvements have been made to this library vs the original, this is a brief overview of the most significant changes.
|
||||
Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) for futher information on class specifics.
|
||||
|
||||
* [Server](#server)
|
||||
* [Advertising](#advertising)
|
||||
* [Client](#client)
|
||||
* [General](#general)
|
||||
<br/>
|
||||
|
||||
<a name="server"></a>
|
||||
# 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<myStruct>(×tamp); // timestamp optional
|
||||
```
|
||||
<br/>
|
||||
|
||||
**Advertising will automatically start when a client disconnects.**
|
||||
|
||||
A new method `NimBLEServer::advertiseOnDisconnect(bool)` has been implemented to control this, true(default) = enabled.
|
||||
<br/>
|
||||
|
||||
`NimBLEServer::removeService` takes an additional parameter `bool deleteSvc` that if true will delete the service
|
||||
and all characteristics / descriptors belonging to it and invalidating any pointers to them.
|
||||
|
||||
If false the service is only removed from visibility by clients. The pointers to the service and
|
||||
it's characteristics / descriptors will remain valid and the service can be re-added in the future
|
||||
using `NimBLEServer::addService`.
|
||||
<br/>
|
||||
|
||||
<a name="advertising"></a>
|
||||
# Advertising
|
||||
`NimBLEAdvertising::start`
|
||||
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
|
||||
that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
This provides an opportunity to update the advertisment data if desired.
|
||||
<br/>
|
||||
|
||||
<a name="client"></a>
|
||||
# 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<myStruct>(×tamp); // timestamp optional
|
||||
```
|
||||
<br/>
|
||||
|
||||
`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
|
||||
> 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.
|
||||
<br/>
|
||||
|
||||
`NimBLEClient::connect()` can now be called without an address or advertised device parameter. This will connect to the
|
||||
device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
|
||||
|
||||
<a name="general"></a>
|
||||
# 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.
|
||||
<br/>
|
||||
|
|
@ -0,0 +1,398 @@
|
|||
# Migrating from Bluedroid to NimBLE
|
||||
|
||||
This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
|
||||
|
||||
**The changes listed here are only the required changes that must be made**, and a short overview of options for migrating existing applications.
|
||||
|
||||
For more information on the improvements and additions please refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) and [Improvements and updates](Improvements_and_updates.md)
|
||||
|
||||
* [General Changes](#general-information)
|
||||
* [Server](#server-api)
|
||||
* [Services](#services)
|
||||
* [characteristics](#characteristics)
|
||||
* [descriptors](#descriptors)
|
||||
* [Security](#server-security)
|
||||
* [Advertising](#advertising-api)
|
||||
* [Client](#client-api)
|
||||
* [Remote Services](#remote-services)
|
||||
* [Remote characteristics](#remote-characteristics)
|
||||
* [Security](#client-security)
|
||||
* [General Security](#security-api)
|
||||
* [Configuration](#arduino-configuration)
|
||||
<br/>
|
||||
|
||||
<a name="general-information"></a>
|
||||
## General Information
|
||||
|
||||
### Header Files
|
||||
All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
|
||||
|
||||
(Mainly for Arduino) You may choose to include `NimBLELog.h` in your appplication if you want to use the `NIMBLE_LOGx` macros for debugging.
|
||||
These macros are used the same way as the `ESP_LOGx` macros.
|
||||
<br/>
|
||||
|
||||
### Class Names
|
||||
Class names remain the same as the original with the addition of a "Nim" prefix.
|
||||
For example `BLEDevice` is now `NimBLEDevice` and `BLEServer` is now `NimBLEServer` etc.
|
||||
|
||||
For convienience definitions have been added to allow applications to use either name for all classes
|
||||
this means **no class names need to be changed in existing code** and makes migrating easier.
|
||||
<br/>
|
||||
|
||||
### BLE Addresses
|
||||
`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *(optional)* `uint8_t type` paramameter
|
||||
to specify the address type. Default is (0) Public static address.
|
||||
|
||||
For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address object with an address type of: 1 (Random).
|
||||
|
||||
As this paramameter is optional no changes to existing code are needed, it is mentioned here for information.
|
||||
<br/>
|
||||
`BLEAddress::getNative` (`NimBLEAddress::getNative`) returns a uint8_t pointer to the native address byte array.
|
||||
In this library the address bytes are stored in reverse order from the original library. This is due to the way
|
||||
the NimBLE stack expects addresses to be presented to it. All other functions such as `toString` are
|
||||
not affected as the endian change is made within them.
|
||||
<br/>
|
||||
|
||||
<a name="server-api"></a>
|
||||
## Server API
|
||||
Creating a `BLEServer` instance is the same as original, no changes required.
|
||||
For example `BLEDevice::createServer()` will work just as it did before.
|
||||
|
||||
`BLEServerCallbacks` (`NimBLEServerCallbacks`) has new methods for handling security operations.
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
<a name="services"></a>
|
||||
### Services
|
||||
Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
|
||||
For example `BLEServer::createService(SERVICE_UUID)` will work just as it did before.
|
||||
|
||||
<a name="characteristics"></a>
|
||||
### Characteristics
|
||||
`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
|
||||
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
|
||||
#### Originally
|
||||
> BLECharacteristic::PROPERTY_READ |
|
||||
> BLECharacteristic::PROPERTY_WRITE
|
||||
|
||||
#### Is Now
|
||||
> NIMBLE_PROPERTY::READ |
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
<br/>
|
||||
|
||||
#### 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
|
||||
<br/>
|
||||
|
||||
**Example:**
|
||||
```
|
||||
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID,
|
||||
BLECharacteristic::PROPERTY_READ |
|
||||
BLECharacteristic::PROPERTY_WRITE
|
||||
);
|
||||
|
||||
```
|
||||
Needs to be changed to:
|
||||
```
|
||||
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::WRITE
|
||||
);
|
||||
```
|
||||
<br/>
|
||||
|
||||
`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe`
|
||||
which is called when a client subscribes to notifications/indications.
|
||||
|
||||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
> BLECharacteristic::getData
|
||||
|
||||
**Has been removed from the API.**
|
||||
Originally this returned a `uint8_t*` to the internal data, which is volatile.
|
||||
To prevent possibly throwing exceptions this has been removed and `NimBLECharacteristic::getValue` should be used
|
||||
to get a copy of the data first which can then safely be accessed via pointer.
|
||||
|
||||
**Example:**
|
||||
```
|
||||
std::string value = pCharacteristic->getValue();
|
||||
uint8_t *pData = (uint8_t*)value.data();
|
||||
```
|
||||
Alternatively use the `getValue` template:
|
||||
```
|
||||
my_struct_t myStruct = pChr->getValue<my_struct_t>();
|
||||
```
|
||||
<br/>
|
||||
|
||||
<a name="descriptors"></a>
|
||||
### Descriptors
|
||||
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||
|
||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor` method.
|
||||
|
||||
BLE2902 or NimBLE2902 class has been removed.
|
||||
NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
|
||||
|
||||
It was no longer useful to have a class for the 0x2902 descriptor as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
|
||||
to handle callback functionality and the client subscription status is handled internally.
|
||||
|
||||
**Note:** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
|
||||
allowing the creation of it would cause a fault in the NimBLE stack.
|
||||
|
||||
All other descriptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` method (except 0x2904, see below).
|
||||
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.
|
||||
<br/>
|
||||
|
||||
For the 0x2904, 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");
|
||||
```
|
||||
<br/>
|
||||
|
||||
<a name="server-security"></a>
|
||||
### 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 API](#security-api) for details.
|
||||
<br/>
|
||||
|
||||
<a name="advertising-api"></a>
|
||||
## Advertising API
|
||||
Advertising works the same as the original API except:
|
||||
> BLEAdvertising::setMinPreferred
|
||||
> BLEAdvertising::setMaxPreferred
|
||||
|
||||
These methods were found to not provide useful functionality and consumed valuable advertising space (6 bytes of 31) if used unknowingly.
|
||||
If you wish to advertise these parameters you can still do so manually via `BLEAdvertisementData::addData` (`NimBLEAdvertisementData::addData`).
|
||||
<br/>
|
||||
|
||||
Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
|
||||
`NimBLEAdvertising::setAppearance`. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
|
||||
|
||||
Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
|
||||
When using custom scan response data you must also use custom advertisement data.
|
||||
<br/>
|
||||
|
||||
> BLEAdvertising::start (NimBLEAdvertising::start)
|
||||
|
||||
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
|
||||
that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
|
||||
|
||||
This provides an opportunity to update the advertisment data if desired.
|
||||
<br/>
|
||||
|
||||
<a name="client-api"></a>
|
||||
## Client API
|
||||
|
||||
Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
|
||||
|
||||
Multiple client instances can be created, up to the maximum number of connections set in the config file (default: 3).
|
||||
To delete a client instance you must use `NimBLEDevice::deleteClient`.
|
||||
|
||||
`BLEClient::connect`(`NimBLEClient::connect`) Has had it's parameters altered.
|
||||
Defined as:
|
||||
> NimBLEClient::connect(bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool deleteServices = true);
|
||||
> NimBLEClient::connect(NimBLEAddress address, bool deleteServices = true);
|
||||
|
||||
The type parameter has been removed and a new bool parameter has been added to indicate if the client should
|
||||
delete the attribute database previously retrieved (if applicable) for the peripheral, default value is true.
|
||||
If set to false the client will use the attribute database it retrieved from the peripheral when previously connected.
|
||||
This allows for faster connections and power saving if the devices dropped connection and are reconnecting.
|
||||
<br/>
|
||||
|
||||
> `BLEClient::getServices` (`NimBLEClient::getServices`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the services should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
**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 automatic functionality.
|
||||
<br/>
|
||||
|
||||
<a name="remote-services"></a>
|
||||
### Remote Services
|
||||
`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
|
||||
|
||||
> BLERemoteService::getCharacteristicsByHandle
|
||||
|
||||
This method has been removed.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the characteristics should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
<a name="remote-characteristics"></a>
|
||||
### Remote Characteristics
|
||||
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
|
||||
|
||||
> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
|
||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
|
||||
|
||||
Is now **deprecated**.
|
||||
> `NimBLERemoteCharacteristic::subscribe`
|
||||
> `NimBLERemoteCharacteristic::unsubscribe`
|
||||
|
||||
Are the new methods added to replace it.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`)
|
||||
> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`)
|
||||
> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`)
|
||||
> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`)
|
||||
|
||||
Are **deprecated** a template: NimBLERemoteCharacteristic::readValue<type\>(time_t\*, bool) has been added to replace them.
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::readRawData`
|
||||
|
||||
**Has been removed from the API**
|
||||
Originally it stored an unnecessary copy of the data and was returning a `uint8_t` pointer to volatile internal data.
|
||||
The user application should use `NimBLERemoteCharacteristic::readValue` or `NimBLERemoteCharacteristic::getValue`.
|
||||
To obatain a copy of the data, then cast the returned std::string to the type required such as:
|
||||
```
|
||||
std::string value = pChr->readValue();
|
||||
uint8_t *data = (uint8_t*)value.data();
|
||||
```
|
||||
Alternatively use the `readValue` template:
|
||||
```
|
||||
my_struct_t myStruct = pChr->readValue<my_struct_t>();
|
||||
```
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
|
||||
|
||||
This method now takes an optional (bool) parameter to indicate if the descriptors should be retrieved from the server (true) or
|
||||
the currently known database returned (false : default).
|
||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
<a name="client-security"></a>
|
||||
### 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.
|
||||
<br/>
|
||||
|
||||
<a name="security-api"></a>
|
||||
## Security API
|
||||
Security operations have been moved to `BLEDevice` (`NimBLEDevice`).
|
||||
|
||||
Also security callback methods are now incorporated in the `NimBLEServerCallbacks` / `NimBLEClientCallbacks` classes.
|
||||
However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
|
||||
|
||||
The callback methods are:
|
||||
|
||||
> `bool onConfirmPIN(uint32_t pin)`
|
||||
|
||||
Receives the pin when using numeric comparison authentication, `return true;` to accept.
|
||||
<br/>
|
||||
|
||||
> `uint32_t onPassKeyRequest()`
|
||||
|
||||
For server callback; return the passkey expected from the client.
|
||||
For client callback; return the passkey to send to the server.
|
||||
<br/>
|
||||
|
||||
> `void onAuthenticationComplete(ble_gap_conn_desc\* desc)`
|
||||
|
||||
Authentication complete, success or failed information is in `desc`.
|
||||
<br/>
|
||||
|
||||
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.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityIOCap(uint8_t iocap)`
|
||||
|
||||
Sets the Input/Output capabilities of this device.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityInitKey(uint8_t init_key)`
|
||||
|
||||
If we are the initiator of the security procedure this sets the keys we will distribute.
|
||||
<br/>
|
||||
|
||||
> `NimBLEDevice::setSecurityRespKey(uint8_t resp_key)`
|
||||
|
||||
Sets the keys we are willing to accept from the peer during pairing.
|
||||
<br/>
|
||||
|
||||
<a name="arduino-configuration"></a>
|
||||
## Arduino Configuration
|
||||
|
||||
Unlike the original library pre-packaged in the esp32-arduino, this library has all the configuration
|
||||
options that are normally set in menuconfig available in the *src/nimconfig.h* file.
|
||||
|
||||
This allows Arduino users to fully customize the build, such as increasing max connections
|
||||
or loading the BLE stack into external PSRAM.
|
||||
|
||||
For details on the options, they are fully commented in *nimconfig.h*
|
||||
<br/>
|
|
@ -0,0 +1,339 @@
|
|||
# New User Guide
|
||||
|
||||
**Note:** If you are migrating an existing project from the original Bluedroid library please see the [Migration Guide.](Migration_guide.md)
|
||||
|
||||
If you are a new user this will guide you through a simple server and client application.
|
||||
|
||||
* [Creating a Server](#creating-a-server)
|
||||
* [Creating a Client](#creating-a-client)
|
||||
<br/>
|
||||
|
||||
## Include Files
|
||||
At the top of your application file add `#include NimBLEDevice.h`, this is the only header required and provides access to all classes.
|
||||
<br/>
|
||||
|
||||
## Using the Library
|
||||
In order to perform any BLE tasks you must first initialize the library, this prepares the NimBLE stack to be ready for commands.
|
||||
|
||||
To do this you must call `NimBLEDevice::init("your device name here")`, the parameter passed is a character string containing the name you want to advertise.
|
||||
If you're not creating a server or do not want to advertise a name, simply pass an empty string for the parameter.
|
||||
|
||||
This can be called any time you wish to use BLE functions and does not need to be called from app_main(IDF) or setup(Arduino) but usually is.
|
||||
<br/>
|
||||
|
||||
<a name="creating-a-server"></a>
|
||||
## Creating a Server
|
||||
BLE servers perform 2 tasks, they advertise their existance for clients to find them and they provide services which contain information for the connecting client.
|
||||
|
||||
After initializing the NimBLE stack we create a server by calling `NimBLEDevice::createServer()`, this will create a server instance and return a pointer to it.
|
||||
|
||||
Once we have created the server we need to tell it the services it hosts.
|
||||
To do this we call `NimBLEServer::createService(const char* uuid)`. Which returns a pointer to an instance of `NimBLEService`.
|
||||
The `uuid` parameter is a hexadecimal string with the uuid we want to give the service, it can be 16, 32, or 128 bits.
|
||||
|
||||
For this example we will keep it simple and use a 16 bit value: ABCD.
|
||||
<br/>
|
||||
|
||||
**Example code:**
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
NimBLEService *pService = pServer->createService("ABCD");
|
||||
}
|
||||
```
|
||||
|
||||
Now we have NimBLE initialized, a server created and a service assigned to it.
|
||||
We can't do much with this yet so now we should add a characteristic to the service to provide some data.
|
||||
|
||||
Next we call `NimBLEService::createCharacteristic` which returns a pointer to an instance of `NimBLECharacteristic`, and takes two parameters:
|
||||
A `uuid` to specify the UUID of the characteristic and a bitmask of the properties we want applied to it.
|
||||
|
||||
Just as with the service UUID we will use a simple 16 bit value: 1234.
|
||||
The properties bitmask is a little more involved. It is a combination of NIMBLE_PROPERTY:: values.
|
||||
|
||||
Here is the list of options:
|
||||
> 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
|
||||
|
||||
For this example we won't need to specify these as the default value is `NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE`
|
||||
which will allow reading and writing values to the characteristic without encryption or security.
|
||||
The function call will simply be `pService->createCharacteristic("1234");`
|
||||
<br/>
|
||||
|
||||
**Our example code now is:**
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
NimBLEService *pService = pServer->createService("ABCD");
|
||||
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic("1234");
|
||||
}
|
||||
```
|
||||
|
||||
All that's left to do now is start the sevice, give the characteristic a value and start advertising for clients.
|
||||
|
||||
Fist we start the service by calling `NimBLEService::start()`.
|
||||
|
||||
Next we need to call `NimBLECharacteristic::setValue` to set the characteristic value that the client will read.
|
||||
There are many different types you can send as parameters for the value but for this example we will use a simple string.
|
||||
`pCharacteristic->setValue("Hello BLE");`
|
||||
|
||||
Next we need to advertise for connections.
|
||||
To do this we create an instance of `NimBLEAdvertising` add our service to it (optional) and start advertisng.
|
||||
|
||||
**The code for this will be:**
|
||||
```
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); // create advertising instance
|
||||
pAdvertising->addServiceUUID("ABCD"); // tell advertising the UUID of our service
|
||||
pAdvertising->start(); // start advertising
|
||||
```
|
||||
That's it, this will be enough to create a BLE server with a service and a characteristic and advertise for client connections.
|
||||
|
||||
**The full example code:**
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
NimBLEService *pService = pServer->createService("ABCD");
|
||||
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic("1234");
|
||||
|
||||
pService->start();
|
||||
pCharacteristic->setValue("Hello BLE");
|
||||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID("ABCD");
|
||||
pAdvertising->start();
|
||||
}
|
||||
```
|
||||
|
||||
Now if you scan with your phone using nRFConnect or any other BLE app you should see a device named "NimBLE" with a service of "ABCD".
|
||||
|
||||
For more advanced features and options please see the server examples in the examples folder.
|
||||
<br/>
|
||||
|
||||
<a name="creating-a-client"></a>
|
||||
## Creating a Client
|
||||
|
||||
BLE clients perform 2 tasks, they scan for advertising servers and form connections to them to read and write to their characteristics/descriptors.
|
||||
|
||||
After initializing the NimBLE stack we create a scan instance by calling `NimBLEDevice::getScan()`, this will create a `NimBLEScan` instance and return a pointer to it.
|
||||
|
||||
Once we have created the scan we can start looking for advertising servers.
|
||||
|
||||
To do this we call `NimBLEScan::start(duration)`, the duration parameter is a uint32_t that specifies the number of seconds to scan for,
|
||||
passing 0 will scan forever.
|
||||
|
||||
In this example we will scan for 10 seconds. This is a blocking function (a non blocking overload is also available).
|
||||
This call returns an instance of `NimBLEScanResults` when the scan completes which can be parsed for advertisers we are interested in.
|
||||
|
||||
**Example Code:**
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::init("");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
NimBLEScanResults results = pScan->start(10);
|
||||
}
|
||||
```
|
||||
<br/>
|
||||
|
||||
Now that we have scanned we need to check the results for any advertisers we are interested in connecting to.
|
||||
|
||||
To do this we iterate through the results and check if any of the devices found are advertising the service we want `ABCD`.
|
||||
Each result in `NimBLEScanResults` is a `NimBLEAdvertisedDevice` instance that we can access data from.
|
||||
|
||||
We will check each device found for the `ABCD` service by calling `NimBLEAdvertisedDevice::isAdvertisingService`.
|
||||
This takes an instance of `NimBLEUUID` as a parameter so we will need to create one.
|
||||
|
||||
**The code for this looks like:**
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
// create a client and connect
|
||||
}
|
||||
}
|
||||
```
|
||||
<br/>
|
||||
|
||||
Now that we can scan and parse advertisers we need to be able to create a `NimBLEClient` instance and use it to connect.
|
||||
|
||||
To do this we call `NimBLEDevice::createClient` which creates the `NimBLEClient` instance and returns a pointer to it.
|
||||
|
||||
After this we call `NimBLEClient::connect` to connect to the advertiser.
|
||||
This takes a pointer to the `NimBLEAdvertisedDevice` and returns `true` if successful.
|
||||
|
||||
**Lets do that now:**
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if(pClient->connect(&device)) {
|
||||
//success
|
||||
} else {
|
||||
// failed to connect
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As shown, the call to `NimBLEClient::connect` should have it's eturn value tested to make sure it succeeded before proceeding to get data.
|
||||
<br/>
|
||||
|
||||
Next we need to access the servers data by asking it for the service and the characteristic we are interested in, then read the characteristic value.
|
||||
|
||||
To do this we call `NimBLEClient::getService`, which takes as a parameter the UUID of the service and returns
|
||||
a pointer an instance to `NimBLERemoteService` or `nullptr` if the service was not found.
|
||||
|
||||
Next we will call `NimBLERemoteService::getCharateristic` which takes as a parameter the UUID of the service and returns
|
||||
a pointer to an instance of `NimBLERemoteCharacteristic` or `nullptr` if not found.
|
||||
|
||||
Finally we will read the characteristic value with `NimBLERemoteCharacteristic::readValue()`.
|
||||
|
||||
**Here is what that looks like:**
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
|
||||
if (pService != nullptr) {
|
||||
NimBLERemoteCharacteristic *pCharacteristic = pService->getCharacteristic("1234");
|
||||
|
||||
if (pCharacteristic != nullptr) {
|
||||
std::string value = pCharacteristic->readValue();
|
||||
// print or do whatever you need with the value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
<br/>
|
||||
|
||||
The last thing we should do is clean up once we are done with the connection.
|
||||
Because multiple clients are supported and can be created we should delete them when finished with them to conserve resources.
|
||||
This is done by calling `NimBLEDevice::deleteClient`.
|
||||
|
||||
**Lets add that now:**
|
||||
```
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
|
||||
if (pService != nullptr) {
|
||||
NimBLERemoteCharacteristic *pCharacteristic = pService->getCharacteristic("1234");
|
||||
|
||||
if (pCharacteristic != nullptr) {
|
||||
std::string value = pCharacteristic->readValue();
|
||||
// print or do whatever you need with the value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
}
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
}
|
||||
}
|
||||
```
|
||||
Note that there is no need to disconnect as that will be done when deleting the client instance.
|
||||
<br/>
|
||||
|
||||
**Here is the full example code:**
|
||||
```
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::init("");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
NimBLEScanResults results = pScan->start(10);
|
||||
|
||||
NimBLEUUID serviceUuid("ABCD");
|
||||
|
||||
for(int i = 0; i < results.getCount(); i++) {
|
||||
NimBLEAdvertisedDevice device = results.getDevice(i);
|
||||
|
||||
if (device.isAdvertisingService(serviceUuid)) {
|
||||
NimBLEClient *pClient = NimBLEDevice::createClient();
|
||||
|
||||
if (pClient->connect(&device)) {
|
||||
NimBLERemoteService *pService = pClient->getService(serviceUuid);
|
||||
|
||||
if (pService != nullptr) {
|
||||
NimBLERemoteCharacteristic *pCharacteristic = pService->getCharacteristic("1234");
|
||||
|
||||
if (pCharacteristic != nullptr) {
|
||||
std::string value = pCharacteristic->readValue();
|
||||
// print or do whatever you need with the value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// failed to connect
|
||||
}
|
||||
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
<br/>
|
||||
|
||||
For more advanced features and options please see the client examples in the examples folder.
|
||||
<br/>
|
||||
|
|
@ -107,9 +107,10 @@ class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
|||
void notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify){
|
||||
std::string str = (isNotify == true) ? "Notification" : "Indication";
|
||||
str += " from ";
|
||||
str += pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress().toString();
|
||||
str += ": Service = " + pRemoteCharacteristic->getRemoteService()->getUUID().toString();
|
||||
str += ", Characteristic = " + pRemoteCharacteristic->getUUID().toString();
|
||||
/** NimBLEAddress and NimBLEUUID have std::string operators */
|
||||
str += std::string(pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
|
||||
str += ": Service = " + std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
|
||||
str += ", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
|
||||
str += ", Value = " + std::string((char*)pData, length);
|
||||
Serial.println(str.c_str());
|
||||
}
|
||||
|
@ -228,17 +229,22 @@ bool connectToServer() {
|
|||
}
|
||||
}
|
||||
|
||||
/** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
|
||||
* Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
|
||||
* Unsubscribe parameter defaults are: response=false.
|
||||
*/
|
||||
if(pChr->canNotify()) {
|
||||
/** Must send a callback to subscribe, if nullptr it will unsubscribe */
|
||||
if(!pChr->registerForNotify(notifyCB)) {
|
||||
//if(!pChr->registerForNotify(notifyCB)) {
|
||||
if(!pChr->subscribe(true, notifyCB)) {
|
||||
/** Disconnect if subscribe failed */
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(pChr->canIndicate()) {
|
||||
/** Send false as second argument to subscribe to indications instead of notifications */
|
||||
if(!pChr->registerForNotify(notifyCB, false)) {
|
||||
/** Send false as first argument to subscribe to indications instead of notifications */
|
||||
//if(!pChr->registerForNotify(notifyCB, false)) {
|
||||
if(!pChr->subscribe(false, notifyCB)) {
|
||||
/** Disconnect if subscribe failed */
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
|
@ -289,17 +295,22 @@ bool connectToServer() {
|
|||
}
|
||||
}
|
||||
|
||||
/** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
|
||||
* Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
|
||||
* Unsubscribe parameter defaults are: response=false.
|
||||
*/
|
||||
if(pChr->canNotify()) {
|
||||
/** Must send a callback to subscribe, if nullptr it will unsubscribe */
|
||||
if(!pChr->registerForNotify(notifyCB)) {
|
||||
//if(!pChr->registerForNotify(notifyCB)) {
|
||||
if(!pChr->subscribe(true, notifyCB)) {
|
||||
/** Disconnect if subscribe failed */
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(pChr->canIndicate()) {
|
||||
/** Send false as second argument to subscribe to indications instead of notifications */
|
||||
if(!pChr->registerForNotify(notifyCB, false)) {
|
||||
/** Send false as first argument to subscribe to indications instead of notifications */
|
||||
//if(!pChr->registerForNotify(notifyCB, false)) {
|
||||
if(!pChr->subscribe(false, notifyCB)) {
|
||||
/** Disconnect if subscribe failed */
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
*/
|
||||
|
||||
#include <NimBLEDevice.h>
|
||||
#include <NimBLE2904.h>
|
||||
#include <NimBLE2902.h>
|
||||
|
||||
static NimBLEServer* pServer;
|
||||
|
||||
|
@ -102,24 +100,33 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
|
|||
str += NimBLEUtils::returnCodeToString(code);
|
||||
Serial.println(str);
|
||||
};
|
||||
|
||||
void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue) {
|
||||
String str = "Client ID: ";
|
||||
str += desc->conn_handle;
|
||||
str += " Address: ";
|
||||
str += std::string(NimBLEAddress(desc->peer_ota_addr)).c_str();
|
||||
if(subValue == 0) {
|
||||
str += " Unsubscribed to ";
|
||||
}else if(subValue == 1) {
|
||||
str += " Subscribed to notfications for ";
|
||||
} else if(subValue == 2) {
|
||||
str += " Subscribed to indications for ";
|
||||
} else if(subValue == 3) {
|
||||
str += " Subscribed to notifications and indications for ";
|
||||
}
|
||||
str += std::string(pCharacteristic->getUUID()).c_str();
|
||||
|
||||
Serial.println(str);
|
||||
};
|
||||
};
|
||||
|
||||
/** Handler class for descriptor actions */
|
||||
class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
|
||||
void onWrite(NimBLEDescriptor* pDescriptor) {
|
||||
if(pDescriptor->getUUID().equals(NimBLEUUID("2902"))) {
|
||||
/** Cast to NimBLE2902 to use the class specific functions. **/
|
||||
NimBLE2902* p2902 = (NimBLE2902*)pDescriptor;
|
||||
if(p2902->getNotifications()) {
|
||||
Serial.println("Client Subscribed to notfications");
|
||||
} else {
|
||||
Serial.println("Client Unubscribed to notfications");
|
||||
}
|
||||
} else {
|
||||
std::string dscVal((char*)pDescriptor->getValue(), pDescriptor->getLength());
|
||||
Serial.print("Descriptor witten value:");
|
||||
Serial.println(dscVal.c_str());
|
||||
}
|
||||
std::string dscVal((char*)pDescriptor->getValue(), pDescriptor->getLength());
|
||||
Serial.print("Descriptor witten value:");
|
||||
Serial.println(dscVal.c_str());
|
||||
};
|
||||
|
||||
void onRead(NimBLEDescriptor* pDescriptor) {
|
||||
|
@ -176,9 +183,9 @@ void setup() {
|
|||
pBeefCharacteristic->setValue("Burger");
|
||||
pBeefCharacteristic->setCallbacks(&chrCallbacks);
|
||||
|
||||
/** 2902 and 2904 descriptors are a special case, when createDescriptor is called with
|
||||
* either of those uuid's it will create the associated class with the correct properties
|
||||
* and sizes. However we must cast the returned reference to the correct type as the method
|
||||
/** 2904 descriptors are a special case, when createDescriptor is called with
|
||||
* 0x2904 a NimBLE2904 class is created with the correct properties and sizes.
|
||||
* However we must cast the returned reference to the correct type as the method
|
||||
* only returns a pointer to the base NimBLEDescriptor class.
|
||||
*/
|
||||
NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904");
|
||||
|
@ -197,6 +204,10 @@ void setup() {
|
|||
pFoodCharacteristic->setValue("Fries");
|
||||
pFoodCharacteristic->setCallbacks(&chrCallbacks);
|
||||
|
||||
/** Note a 0x2902 descriptor MUST NOT be created as NimBLE will create one automatically
|
||||
* if notification or indication properties are assigned to a characteristic.
|
||||
*/
|
||||
|
||||
/** Custom descriptor: Arguments are UUID, Properties, max length in bytes of the value */
|
||||
NimBLEDescriptor* pC01Ddsc = pFoodCharacteristic->createDescriptor(
|
||||
"C01D",
|
||||
|
@ -208,14 +219,6 @@ void setup() {
|
|||
pC01Ddsc->setValue("Send it back!");
|
||||
pC01Ddsc->setCallbacks(&dscCallbacks);
|
||||
|
||||
/** Note a 2902 descriptor does NOT need to be created as any chactateristic with
|
||||
* notification or indication properties will have one created autmatically.
|
||||
* Manually creating it is only useful if you wish to handle callback functions
|
||||
* as shown here. Otherwise this can be removed without loss of functionality.
|
||||
*/
|
||||
NimBLE2902* pFood2902 = (NimBLE2902*)pFoodCharacteristic->createDescriptor("2902");
|
||||
pFood2902->setCallbacks(&dscCallbacks);
|
||||
|
||||
/** Start the services when finished creating all Characteristics and Descriptors */
|
||||
pDeadService->start();
|
||||
pBaadService->start();
|
||||
|
@ -247,4 +250,4 @@ void loop() {
|
|||
}
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
}
|
|
@ -102,16 +102,13 @@ void setup() {
|
|||
|
||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
||||
// Create a BLE Descriptor
|
||||
/*********** New createDescriptor method ************
|
||||
NOTE: There is no need to create the 2902 descriptor
|
||||
as it will be created automatically if notifications
|
||||
/***************************************************
|
||||
NOTE: DO NOT create a 2902 descriptor.
|
||||
it will be created automatically if notifications
|
||||
or indications are enabled on a characteristic.
|
||||
|
||||
pCharacteristic->addDescriptor(new BLE2902());
|
||||
****************************************************/
|
||||
/** Add properties the same way as characteristics now **/
|
||||
|
||||
pCharacteristic->createDescriptor("2902" /** , NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE **/);
|
||||
// Start the service
|
||||
pService->start();
|
||||
|
||||
|
@ -119,7 +116,9 @@ void setup() {
|
|||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||
pAdvertising->setScanResponse(false);
|
||||
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
|
||||
/**This method is removed as it was no longer useful and consumed advertising space
|
||||
* pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
|
||||
*/
|
||||
BLEDevice::startAdvertising();
|
||||
Serial.println("Waiting a client connection to notify...");
|
||||
}
|
||||
|
|
|
@ -44,8 +44,10 @@ void setup() {
|
|||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||
pAdvertising->setScanResponse(true);
|
||||
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
|
||||
pAdvertising->setMinPreferred(0x12);
|
||||
/**These methods are removed as they are no longer useful and consumed advertising space
|
||||
* pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
|
||||
* pAdvertising->setMinPreferred(0x12);
|
||||
*/
|
||||
BLEDevice::startAdvertising();
|
||||
Serial.println("Characteristic defined! Now you can read it in your phone!");
|
||||
}
|
||||
|
|
|
@ -105,16 +105,13 @@ void setup() {
|
|||
|
||||
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
||||
// Create a BLE Descriptor
|
||||
/*********** New createDescriptor method ************
|
||||
NOTE: There is no need to create the 2902 descriptor
|
||||
as it will be created automatically if notifications
|
||||
/***************************************************
|
||||
NOTE: DO NOT create a 2902 descriptor
|
||||
it will be created automatically if notifications
|
||||
or indications are enabled on a characteristic.
|
||||
|
||||
pCharacteristic->addDescriptor(new BLE2902());
|
||||
****************************************************/
|
||||
/** Add properties the same way as characteristics now **/
|
||||
|
||||
pCharacteristic->createDescriptor("2902" /** , NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE **/);
|
||||
|
||||
// Start the service
|
||||
pService->start();
|
||||
|
@ -123,7 +120,9 @@ void setup() {
|
|||
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||
pAdvertising->setScanResponse(false);
|
||||
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
|
||||
/**This method is removed it was no longer useful and consumed advertising space
|
||||
* pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
|
||||
*/
|
||||
BLEDevice::startAdvertising();
|
||||
Serial.println("Waiting a client connection to notify...");
|
||||
}
|
||||
|
|
|
@ -112,15 +112,13 @@ void setup() {
|
|||
NIMBLE_PROPERTY::NOTIFY
|
||||
);
|
||||
|
||||
/******* New createDescriptor method ********
|
||||
NOTE: There is no need to create the 2902 descriptor
|
||||
as it will be created automatically if notifications or
|
||||
indications are enabled on a characteristic.
|
||||
/***************************************************
|
||||
NOTE: DO NOT create a 2902 descriptor
|
||||
it will be created automatically if notifications
|
||||
or indications are enabled on a characteristic.
|
||||
|
||||
pCharacteristic->addDescriptor(new BLE2902());
|
||||
********************************************/
|
||||
/** Add properties the same way as characteristics now **/
|
||||
pTxCharacteristic->createDescriptor("2902" /** , NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE **/);
|
||||
pCharacteristic->addDescriptor(new BLE2902());
|
||||
****************************************************/
|
||||
|
||||
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
|
||||
CHARACTERISTIC_UUID_RX,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
name=NimBLE-Arduino
|
||||
version=0.9.0
|
||||
author=H2zero
|
||||
version=1.0.2
|
||||
author=h2zero
|
||||
maintainer=h2zero <powellperalta@gmail.com>
|
||||
sentence=NimBLE library for Arduino
|
||||
paragraph=A lighter-weight alternative to the bluedroid library for esp32.
|
||||
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
|
||||
paragraph=This is a more updated and lower resource alternative to the original bluedroid BLE library for esp32. Uses 50% less flash space and approximately 100KB less ram with the same functionality. Nearly 100% compatible with existing application code, migration guide included.
|
||||
url=https://github.com/h2zero/NimBLE-Arduino
|
||||
category=Communication
|
||||
architectures=esp32
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 = "<Unknown>");
|
||||
|
@ -42,6 +45,10 @@ public:
|
|||
std::string toString();
|
||||
bool timedWait(std::string owner = "<Unknown>", uint32_t timeoutMs = portMAX_DELAY);
|
||||
uint32_t wait(std::string owner = "<Unknown>");
|
||||
/**
|
||||
* @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:
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* NimBLE2902.cpp
|
||||
*
|
||||
* Created: on March 10, 2020
|
||||
* Author H2zero
|
||||
*
|
||||
* Originally:
|
||||
*
|
||||
* BLE2902.cpp
|
||||
*
|
||||
* Created on: Jun 25, 2017
|
||||
* Author: kolban
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* See also:
|
||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLE2902.h"
|
||||
|
||||
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
|
||||
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902),
|
||||
BLE_GATT_CHR_F_READ |
|
||||
BLE_GATT_CHR_F_WRITE,
|
||||
2, pCharacterisitic)
|
||||
{
|
||||
uint8_t data[2] = { 0, 0 };
|
||||
setValue(data, 2);
|
||||
} // NimBLE2902
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the notifications value.
|
||||
* @return The notifications value. True if notifications are enabled and false if not.
|
||||
*/
|
||||
bool NimBLE2902::getNotifications() {
|
||||
return (getValue()[0] & (1 << 0)) != 0;
|
||||
} // getNotifications
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the indications value.
|
||||
* @return The indications value. True if indications are enabled and false if not.
|
||||
*/
|
||||
bool NimBLE2902::getIndications() {
|
||||
return (getValue()[0] & (1 << 1)) != 0;
|
||||
} // getIndications
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the indications flag.
|
||||
* @param [in] flag The indications flag.
|
||||
*/
|
||||
void NimBLE2902::setIndications(bool flag) {
|
||||
uint8_t *pValue = getValue();
|
||||
if (flag) pValue[0] |= 1 << 1;
|
||||
else pValue[0] &= ~(1 << 1);
|
||||
} // setIndications
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the notifications flag.
|
||||
* @param [in] flag The notifications flag.
|
||||
*/
|
||||
void NimBLE2902::setNotifications(bool flag) {
|
||||
uint8_t *pValue = getValue();
|
||||
if (flag) pValue[0] |= 1 << 0;
|
||||
else pValue[0] &= ~(1 << 0);
|
||||
} // setNotifications
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* NimBLE2902.h
|
||||
*
|
||||
* Created: on March 10, 2020
|
||||
* Author H2zero
|
||||
*
|
||||
* Originally:
|
||||
*
|
||||
* BLE2902.h
|
||||
*
|
||||
* Created on: Jun 25, 2017
|
||||
* Author: kolban
|
||||
*/
|
||||
|
||||
#ifndef MAIN_NIMBLE2902_H_
|
||||
#define MAIN_NIMBLE2902_H_
|
||||
#include "sdkconfig.h"
|
||||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLEDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define NIMBLE_DESC_FLAG_NOTIFY 0x0001
|
||||
#define NIMBLE_DESC_FLAG_INDICATE 0x0002
|
||||
|
||||
typedef struct {
|
||||
uint16_t conn_id;
|
||||
uint16_t sub_val;
|
||||
} chr_sub_status_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Descriptor for Client Characteristic Configuration.
|
||||
*
|
||||
* This is a convenience descriptor for the Client Characteristic Configuration which has a UUID of 0x2902.
|
||||
*
|
||||
* See also:
|
||||
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
|
||||
*/
|
||||
class NimBLE2902: public NimBLEDescriptor {
|
||||
public:
|
||||
bool getNotifications();
|
||||
bool getIndications();
|
||||
void setNotifications(bool flag);
|
||||
void setIndications(bool flag);
|
||||
private:
|
||||
NimBLE2902(NimBLECharacteristic* pCharacterisitic);
|
||||
friend class NimBLECharacteristic;
|
||||
std::vector<chr_sub_status_t> m_subscribedVec;
|
||||
|
||||
}; // NimBLE2902
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLE2902_H_ */
|
|
@ -23,17 +23,26 @@
|
|||
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
|
||||
m_addrType = address.type;
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a blank address, i.e. 00:00:00:00:00:00, type 0.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress() {
|
||||
NimBLEAddress("");
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
/**
|
||||
|
@ -45,9 +54,12 @@ 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.
|
||||
* @param [in] type The type of the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(const std::string &stringAddress) {
|
||||
NimBLEAddress::NimBLEAddress(const std::string &stringAddress, uint8_t type) {
|
||||
m_addrType = type;
|
||||
|
||||
if (stringAddress.length() == 0) {
|
||||
memset(m_address, 0, 6);
|
||||
return;
|
||||
|
@ -72,24 +84,29 @@ NimBLEAddress::NimBLEAddress(const std::string &stringAddress) {
|
|||
for(size_t index = 0; index < sizeof m_address; index++) {
|
||||
m_address[index] = data[index];
|
||||
}
|
||||
} // BLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Constructor for compatibility with bluedroid esp library.
|
||||
* @param [in] uint8_t[6] or esp_bd_addr_t struct containing the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(uint8_t address[6]) {
|
||||
std::reverse_copy(address, address + sizeof m_address, m_address);
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Constructor for address using a hex value. Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16"
|
||||
* @param [in] uint64_t containing the address.
|
||||
* @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.
|
||||
* @param [in] type The type of the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(const uint64_t &address) {
|
||||
NimBLEAddress::NimBLEAddress(uint8_t address[6], uint8_t type) {
|
||||
std::reverse_copy(address, address + sizeof m_address, m_address);
|
||||
m_addrType = type;
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @param [in] type The type of the address.
|
||||
*/
|
||||
NimBLEAddress::NimBLEAddress(const uint64_t &address, uint8_t type) {
|
||||
memcpy(m_address, &address, sizeof m_address);
|
||||
m_addrType = type;
|
||||
} // NimBLEAddress
|
||||
|
||||
|
||||
|
@ -104,14 +121,23 @@ 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;
|
||||
} // getNative
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the address type.
|
||||
* @return The address type.
|
||||
*/
|
||||
uint8_t NimBLEAddress::getType() const {
|
||||
return m_addrType;
|
||||
} // getType
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert a BLE address to a string.
|
||||
*
|
||||
|
@ -122,30 +148,50 @@ 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]);
|
||||
snprintf(buffer, sizeof(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
|
||||
|
|
|
@ -33,13 +33,15 @@
|
|||
*/
|
||||
class NimBLEAddress {
|
||||
public:
|
||||
NimBLEAddress();
|
||||
NimBLEAddress(ble_addr_t address);
|
||||
NimBLEAddress(uint8_t address[6]);
|
||||
NimBLEAddress(const std::string &stringAddress);
|
||||
NimBLEAddress(const uint64_t &address);
|
||||
bool equals(const NimBLEAddress &otherAddress) const;
|
||||
const uint8_t* getNative() const;
|
||||
std::string toString() const;
|
||||
NimBLEAddress(uint8_t address[6], uint8_t type = BLE_ADDR_PUBLIC);
|
||||
NimBLEAddress(const std::string &stringAddress, uint8_t type = BLE_ADDR_PUBLIC);
|
||||
NimBLEAddress(const uint64_t &address, uint8_t type = BLE_ADDR_PUBLIC);
|
||||
bool equals(const NimBLEAddress &otherAddress) const;
|
||||
const uint8_t* getNative() const;
|
||||
std::string toString() const;
|
||||
uint8_t getType() const;
|
||||
|
||||
bool operator ==(const NimBLEAddress & rhs) const;
|
||||
bool operator !=(const NimBLEAddress & rhs) const;
|
||||
|
@ -48,6 +50,7 @@ public:
|
|||
|
||||
private:
|
||||
uint8_t m_address[6];
|
||||
uint8_t m_addrType;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nimconfig.h"
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
#include "NimBLEDevice.h"
|
||||
#include "NimBLEAdvertisedDevice.h"
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLELog.h"
|
||||
|
@ -30,13 +31,10 @@ static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
|||
NimBLEAdvertisedDevice::NimBLEAdvertisedDevice() {
|
||||
m_advType = 0;
|
||||
m_appearance = 0;
|
||||
m_deviceType = 0;
|
||||
m_manufacturerData = "";
|
||||
m_name = "";
|
||||
m_rssi = -9999;
|
||||
m_serviceData = "";
|
||||
m_txPower = 0;
|
||||
m_pScan = nullptr;
|
||||
m_payloadLength = 0;
|
||||
m_payload = nullptr;
|
||||
|
||||
|
@ -53,11 +51,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,13 +60,17 @@ 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;
|
||||
} // getAddress
|
||||
} // getAdvType
|
||||
|
||||
|
||||
/**
|
||||
|
@ -98,7 +96,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,54 +114,100 @@ 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() {
|
||||
return m_pScan;
|
||||
return NimBLEDevice::getScan();
|
||||
} // getScan
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service data.
|
||||
* @return The ServiceData of the advertised device.
|
||||
* @param [in] index The vector index of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData() {
|
||||
return m_serviceData;
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||
if(index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: index out of range");
|
||||
return "";
|
||||
}
|
||||
return m_serviceDataVec[index].second;
|
||||
} //getServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the service data UUID.
|
||||
* @return The service data UUID.
|
||||
* @brief Get the service data.
|
||||
* @param [in] uuid The uuid of the service data requested.
|
||||
* @return The advertised service data or empty string if no data.
|
||||
*/
|
||||
std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) const {
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
return it.second;
|
||||
}
|
||||
}
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceData: uuid not found");
|
||||
return "";
|
||||
} //getServiceData
|
||||
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID() {
|
||||
return m_serviceDataUUID;
|
||||
|
||||
/**
|
||||
* @brief Get the advertised service UUID.
|
||||
* @param [in] index The vector index of the service data UUID requested.
|
||||
* @return The advertised service UUID or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
if(!haveServiceData() || index > m_serviceDataVec.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceDataUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
}
|
||||
return m_serviceDataVec[index].first;
|
||||
} // getServiceDataUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the Service UUID.
|
||||
* @return The Service UUID of the advertised device.
|
||||
* @brief Get the count of advertised service data UUIDS
|
||||
* @return The number of service data UUIDS in the vector.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
return m_serviceDataVec.size();
|
||||
} // getServiceDataCount
|
||||
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventually, is no longer useful
|
||||
return m_serviceUUIDs[0];
|
||||
|
||||
/**
|
||||
* @brief Get the Service UUID.
|
||||
* @param [in] index The vector index of the service UUID requested.
|
||||
* @return The Service UUID of the advertised service, or an empty UUID if not found.
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
if(!haveServiceUUID() || index > m_serviceUUIDs.size()) {
|
||||
NIMBLE_LOGW(LOG_TAG, "getServiceUUID: index out of range");
|
||||
return NimBLEUUID("");
|
||||
}
|
||||
return m_serviceUUIDs[index];
|
||||
} // getServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check advertised serviced for existence required UUID
|
||||
* @brief Get the number of services advertised
|
||||
* @return The count of services in the advertising packet.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
return m_serviceUUIDs.size();
|
||||
} // getServiceUUIDCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check advertised services for existance of the required UUID
|
||||
* @return Return true if service is advertised
|
||||
*/
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){
|
||||
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) const {
|
||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Comparing UUIDS: %s %s", m_serviceUUIDs[i].toString().c_str(), uuid.toString().c_str());
|
||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // isAdvertisingService
|
||||
|
||||
|
||||
/**
|
||||
|
@ -250,121 +294,126 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
|
|||
*
|
||||
* https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::parseAdvertisement(ble_hs_adv_fields *fields) {
|
||||
//char s[BLE_HS_ADV_MAX_SZ];
|
||||
uint8_t *u8p;
|
||||
uint8_t length;
|
||||
int i;
|
||||
void NimBLEAdvertisedDevice::parseAdvertisement(uint8_t* payload, uint8_t length) {
|
||||
struct ble_hs_adv_fields fields;
|
||||
int rc = ble_hs_adv_parse_fields(&fields, payload, length);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields->uuids16 != NULL) {
|
||||
for (i = 0; i < fields->num_uuids16; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields->uuids16[i].value));
|
||||
m_payload = payload;
|
||||
m_payloadLength = length;
|
||||
|
||||
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, m_payload, m_payloadLength);
|
||||
NIMBLE_LOGD(LOG_TAG,"payload: %s", pHex);
|
||||
free(pHex);
|
||||
#endif
|
||||
|
||||
if (fields.uuids16 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids16; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids16[i].value));
|
||||
}
|
||||
}
|
||||
|
||||
if (fields->uuids32 != NULL) {
|
||||
for (i = 0; i < fields->num_uuids32; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields->uuids32[i].value));
|
||||
if (fields.uuids32 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids32; i++) {
|
||||
setServiceUUID(NimBLEUUID(fields.uuids32[i].value));
|
||||
}
|
||||
}
|
||||
|
||||
if (fields->uuids128 != NULL) {
|
||||
for (i = 0; i < fields->num_uuids128; i++) {
|
||||
setServiceUUID(NimBLEUUID(&fields->uuids128[i]));
|
||||
if (fields.uuids128 != NULL) {
|
||||
for (int i = 0; i < fields.num_uuids128; i++) {
|
||||
setServiceUUID(NimBLEUUID(&fields.uuids128[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (fields->name != NULL) {
|
||||
setName(std::string(reinterpret_cast<char*>(fields->name), fields->name_len));
|
||||
if (fields.name != NULL) {
|
||||
setName(std::string(reinterpret_cast<char*>(fields.name), fields.name_len));
|
||||
}
|
||||
|
||||
if (fields->tx_pwr_lvl_is_present) {
|
||||
setTXPower(fields->tx_pwr_lvl);
|
||||
if (fields.tx_pwr_lvl_is_present) {
|
||||
setTXPower(fields.tx_pwr_lvl);
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid16 != NULL) {
|
||||
if (fields.svc_data_uuid16 != NULL ||
|
||||
fields.svc_data_uuid32 != NULL ||
|
||||
fields.svc_data_uuid128 != NULL)
|
||||
{
|
||||
ble_hs_adv_field *field;
|
||||
uint8_t *data = payload;
|
||||
while(length > 1) {
|
||||
field = (ble_hs_adv_field*)data;
|
||||
|
||||
u8p = fields->svc_data_uuid16;
|
||||
length = fields->svc_data_uuid16_len;
|
||||
|
||||
if (length < 2) {
|
||||
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_SERVICE_DATA");
|
||||
}
|
||||
else{
|
||||
uint16_t uuid = *(uint16_t*)u8p;
|
||||
setServiceDataUUID(NimBLEUUID(uuid));
|
||||
if (length > 2) {
|
||||
setServiceData(std::string(reinterpret_cast<char*>(u8p + 2), length - 2));
|
||||
if(field->length > length) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID16) {
|
||||
if(field->length > 2) {
|
||||
uint16_t uuid;
|
||||
memcpy(&uuid, field->value, 2);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 2), field->length - 3));
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID32) {
|
||||
if(field->length > 4) {
|
||||
uint32_t uuid;
|
||||
memcpy(&uuid, field->value, 4);
|
||||
setServiceData(NimBLEUUID(uuid), std::string(reinterpret_cast<char*>(field->value + 4), field->length - 5));
|
||||
}
|
||||
}
|
||||
|
||||
if(field->type == BLE_HS_ADV_TYPE_SVC_DATA_UUID128) {
|
||||
if(field->length > 16) {
|
||||
NimBLEUUID uuid(field->value, (size_t)16, false);
|
||||
setServiceData(uuid, std::string(reinterpret_cast<char*>(field->value + 16), field->length - 17));
|
||||
}
|
||||
}
|
||||
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid32 != NULL) {
|
||||
|
||||
u8p = fields->svc_data_uuid16;
|
||||
length = fields->svc_data_uuid16_len;
|
||||
|
||||
if (length < 4) {
|
||||
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_32SERVICE_DATA");
|
||||
}
|
||||
|
||||
uint32_t uuid = *(uint32_t*) u8p;
|
||||
setServiceDataUUID(NimBLEUUID(uuid));
|
||||
if (length > 4) {
|
||||
setServiceData(std::string(reinterpret_cast<char*>(u8p + 4), length - 4));
|
||||
}
|
||||
if (fields.appearance_is_present) {
|
||||
setAppearance(fields.appearance);
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid128 != NULL) {
|
||||
|
||||
u8p = fields->svc_data_uuid16;
|
||||
length = fields->svc_data_uuid16_len;
|
||||
|
||||
if (length < 16) {
|
||||
NIMBLE_LOGE(LOG_TAG,"Length too small for ESP_BLE_AD_TYPE_128SERVICE_DATA");
|
||||
}
|
||||
|
||||
setServiceDataUUID(NimBLEUUID(u8p, (size_t)16, false));
|
||||
if (length > 16) {
|
||||
setServiceData(std::string(reinterpret_cast<char*>(u8p + 16), length - 16));
|
||||
}
|
||||
if (fields.mfg_data != NULL) {
|
||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields.mfg_data), fields.mfg_data_len));
|
||||
}
|
||||
|
||||
if (fields->appearance_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " appearance=0x%04x", fields->appearance);
|
||||
setAppearance(fields->appearance);
|
||||
}
|
||||
|
||||
/**** TODO: create storage and fucntions for these parameters
|
||||
if (fields->public_tgt_addr != NULL) {
|
||||
/* TODO: create storage and fucntions for these parameters
|
||||
if (fields.public_tgt_addr != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
|
||||
u8p = fields->public_tgt_addr;
|
||||
for (i = 0; i < fields->num_public_tgt_addrs; i++) {
|
||||
u8p = fields.public_tgt_addr;
|
||||
for (i = 0; i < fields.num_public_tgt_addrs; i++) {
|
||||
NIMBLE_LOGD(LOG_TAG, "public_tgt_addr=%s ", addr_str(u8p));
|
||||
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields->slave_itvl_range != NULL) {
|
||||
if (fields.slave_itvl_range != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " slave_itvl_range=");
|
||||
print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
print_bytes(fields.slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
|
||||
if (fields->adv_itvl_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " adv_itvl=0x%04x\n", fields->adv_itvl);
|
||||
if (fields.adv_itvl_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " adv_itvl=0x%04x\n", fields.adv_itvl);
|
||||
}
|
||||
|
||||
if (fields->uri != NULL) {
|
||||
if (fields.uri != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " uri=");
|
||||
print_bytes(fields->uri, fields->uri_len);
|
||||
print_bytes(fields.uri, fields.uri_len);
|
||||
NIMBLE_LOGD(LOG_TAG, "\n");
|
||||
}
|
||||
*/
|
||||
if (fields->mfg_data != NULL) {
|
||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields->mfg_data), fields->mfg_data_len));
|
||||
}
|
||||
|
||||
} //parseAdvertisement
|
||||
|
||||
|
||||
|
@ -393,7 +442,6 @@ void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
|||
void NimBLEAdvertisedDevice::setAppearance(uint16_t appearance) {
|
||||
m_appearance = appearance;
|
||||
m_haveAppearance = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- appearance: %d", m_appearance);
|
||||
} // setAppearance
|
||||
|
||||
|
||||
|
@ -404,10 +452,6 @@ void NimBLEAdvertisedDevice::setAppearance(uint16_t appearance) {
|
|||
void NimBLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
|
||||
m_manufacturerData = manufacturerData;
|
||||
m_haveManufacturerData = true;
|
||||
|
||||
char* pHex = NimBLEUtils::buildHexData(nullptr, (uint8_t*) m_manufacturerData.data(), (uint8_t) m_manufacturerData.length());
|
||||
NIMBLE_LOGD(LOG_TAG,"- manufacturer data: %s", pHex);
|
||||
free(pHex);
|
||||
} // setManufacturerData
|
||||
|
||||
|
||||
|
@ -418,7 +462,6 @@ void NimBLEAdvertisedDevice::setManufacturerData(std::string manufacturerData) {
|
|||
void NimBLEAdvertisedDevice::setName(std::string name) {
|
||||
m_name = name;
|
||||
m_haveName = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- setName(): name: %s", m_name.c_str());
|
||||
} // setName
|
||||
|
||||
|
||||
|
@ -429,19 +472,9 @@ void NimBLEAdvertisedDevice::setName(std::string name) {
|
|||
void NimBLEAdvertisedDevice::setRSSI(int rssi) {
|
||||
m_rssi = rssi;
|
||||
m_haveRSSI = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- setRSSI(): rssi: %d", m_rssi);
|
||||
} // setRSSI
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Scan that created this advertised device.
|
||||
* @param pScan The Scan that created this advertised device.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setScan(NimBLEScan* pScan) {
|
||||
m_pScan = pScan;
|
||||
} // setScan
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Service UUID for this device.
|
||||
* @param [in] serviceUUID The discovered serviceUUID
|
||||
|
@ -459,36 +492,32 @@ 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;
|
||||
}
|
||||
}
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
m_haveServiceUUID = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
|
||||
} // setServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the ServiceData value.
|
||||
* @param [in] data ServiceData value.
|
||||
* @param [in] uuid The UUID that the service data belongs to.
|
||||
* @param [in] data The service data.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceData(std::string serviceData) {
|
||||
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
||||
m_serviceData = serviceData; // Save the service data that we received.
|
||||
void NimBLEAdvertisedDevice::setServiceData(NimBLEUUID uuid, std::string data) {
|
||||
m_haveServiceData = true;
|
||||
for(auto &it : m_serviceDataVec) {
|
||||
if(it.first == uuid) {
|
||||
it.second = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_serviceDataVec.push_back({uuid, data});
|
||||
} //setServiceData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the ServiceDataUUID value.
|
||||
* @param [in] data ServiceDataUUID value.
|
||||
*/
|
||||
void NimBLEAdvertisedDevice::setServiceDataUUID(NimBLEUUID uuid) {
|
||||
m_haveServiceData = true; // Set the flag that indicates we have service data.
|
||||
m_serviceDataUUID = uuid;
|
||||
} // setServiceDataUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the power level for this device.
|
||||
* @param [in] txPower The discovered power level.
|
||||
|
@ -496,7 +525,6 @@ void NimBLEAdvertisedDevice::setServiceDataUUID(NimBLEUUID uuid) {
|
|||
void NimBLEAdvertisedDevice::setTXPower(int8_t txPower) {
|
||||
m_txPower = txPower;
|
||||
m_haveTXPower = true;
|
||||
NIMBLE_LOGD(LOG_TAG,"- txPower: %d", m_txPower);
|
||||
} // setTXPower
|
||||
|
||||
|
||||
|
@ -532,43 +560,60 @@ std::string NimBLEAdvertisedDevice::toString() {
|
|||
res += val;
|
||||
}
|
||||
|
||||
res += ", advType: " + std::string(NimBLEUtils::advTypeToString(m_advType));
|
||||
if(haveServiceData()) {
|
||||
size_t count = getServiceDataCount();
|
||||
res += "\nService Data:";
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
||||
res += ", Data: " + getServiceData(i);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
} // 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;
|
||||
}
|
||||
return m_address.getType();
|
||||
} // 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;
|
||||
}
|
||||
|
||||
|
||||
void NimBLEAdvertisedDevice::setAddressType(uint8_t type) {
|
||||
m_addressType = type;
|
||||
}
|
||||
} // getTimestamp
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
|
||||
void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t length){
|
||||
m_payload = payload;
|
||||
m_payloadLength = length;
|
||||
}
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
||||
|
|
|
@ -46,8 +46,16 @@ public:
|
|||
uint16_t getAppearance();
|
||||
std::string getManufacturerData();
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <type\>.
|
||||
* @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 <tt>sizeof(<type\>)</tt>.
|
||||
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
|
||||
* less than <tt>sizeof(<type\>)</tt>.
|
||||
* @details <b>Use:</b> <tt>getManufacturerData<type>(skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T getManufacturerData(bool skipSizeCheck = false) {
|
||||
T getManufacturerData(bool skipSizeCheck = false) {
|
||||
std::string data = getManufacturerData();
|
||||
if(!skipSizeCheck && data.size() < sizeof(T)) return T();
|
||||
const char *pData = data.data();
|
||||
|
@ -57,51 +65,73 @@ public:
|
|||
std::string getName();
|
||||
int getRSSI();
|
||||
NimBLEScan* getScan();
|
||||
std::string getServiceData();
|
||||
size_t getServiceDataCount();
|
||||
std::string getServiceData(uint8_t index = 0);
|
||||
std::string getServiceData(const NimBLEUUID &uuid) const;
|
||||
|
||||
/**
|
||||
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||
* @tparam T The type to convert the data to.
|
||||
* @param [in] index The vector index of the service data requested.
|
||||
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
|
||||
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
|
||||
* less than <tt>sizeof(<type\>)</tt>.
|
||||
* @details <b>Use:</b> <tt>getServiceData<type>(skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T getServiceData(bool skipSizeCheck = false) {
|
||||
std::string data = getServiceData();
|
||||
T getServiceData(uint8_t index = 0, bool skipSizeCheck = false) {
|
||||
std::string data = getServiceData(index);
|
||||
if(!skipSizeCheck && data.size() < sizeof(T)) return T();
|
||||
const char *pData = data.data();
|
||||
return *((T *)pData);
|
||||
}
|
||||
|
||||
NimBLEUUID getServiceDataUUID();
|
||||
NimBLEUUID getServiceUUID();
|
||||
/**
|
||||
* @brief A template to convert the service data to <tt><type\></tt>.
|
||||
* @tparam T The type to convert the data to.
|
||||
* @param [in] uuid The uuid of the service data requested.
|
||||
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
|
||||
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
|
||||
* less than <tt>sizeof(<type\>)</tt>.
|
||||
* @details <b>Use:</b> <tt>getServiceData<type>(skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T getServiceData(const NimBLEUUID &uuid, bool skipSizeCheck = false) {
|
||||
std::string data = getServiceData(uuid);
|
||||
if(!skipSizeCheck && data.size() < sizeof(T)) return T();
|
||||
const char *pData = data.data();
|
||||
return *((T *)pData);
|
||||
}
|
||||
|
||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||
size_t getServiceUUIDCount();
|
||||
int8_t getTXPower();
|
||||
uint8_t* getPayload();
|
||||
size_t getPayloadLength();
|
||||
uint8_t getAddressType();
|
||||
time_t getTimestamp();
|
||||
void setAddressType(uint8_t type);
|
||||
|
||||
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
bool haveRSSI();
|
||||
bool haveServiceData();
|
||||
bool haveServiceUUID();
|
||||
bool haveTXPower();
|
||||
|
||||
std::string toString();
|
||||
bool isAdvertisingService(const NimBLEUUID &uuid) const;
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
bool haveRSSI();
|
||||
bool haveServiceData();
|
||||
bool haveServiceUUID();
|
||||
bool haveTXPower();
|
||||
std::string toString();
|
||||
|
||||
private:
|
||||
friend class NimBLEScan;
|
||||
|
||||
void parseAdvertisement(ble_hs_adv_fields *fields);
|
||||
void parseAdvertisement(uint8_t* payload, uint8_t length);
|
||||
void setAddress(NimBLEAddress address);
|
||||
void setAdvType(uint8_t advType);
|
||||
void setAdvertisementResult(uint8_t* payload, uint8_t length);
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setManufacturerData(std::string manufacturerData);
|
||||
void setName(std::string name);
|
||||
void setRSSI(int rssi);
|
||||
void setScan(NimBLEScan* pScan);
|
||||
void setServiceData(std::string data);
|
||||
void setServiceDataUUID(NimBLEUUID uuid);
|
||||
void setServiceData(NimBLEUUID serviceUUID, std::string data);
|
||||
void setServiceUUID(const char* serviceUUID);
|
||||
void setServiceUUID(NimBLEUUID serviceUUID);
|
||||
void setTXPower(int8_t txPower);
|
||||
|
@ -118,20 +148,17 @@ private:
|
|||
NimBLEAddress m_address = NimBLEAddress("");
|
||||
uint8_t m_advType;
|
||||
uint16_t m_appearance;
|
||||
int m_deviceType;
|
||||
std::string m_manufacturerData;
|
||||
std::string m_name;
|
||||
NimBLEScan* m_pScan;
|
||||
int m_rssi;
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
int8_t m_txPower;
|
||||
std::string m_serviceData;
|
||||
NimBLEUUID m_serviceDataUUID;
|
||||
uint8_t* m_payload;
|
||||
size_t m_payloadLength;
|
||||
uint8_t m_addressType;
|
||||
time_t m_timestamp;
|
||||
bool m_callbackSent;
|
||||
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
std::vector<std::pair<NimBLEUUID, std::string>>m_serviceDataVec;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -150,7 +177,6 @@ public:
|
|||
* As we are scanning, we will find new devices. When found, this call back is invoked with a reference to the
|
||||
* device that was found. During any individual scan, a device will only be detected one time.
|
||||
*/
|
||||
//virtual void onResult(NimBLEAdvertisedDevice advertisedDevice) = 0;
|
||||
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -55,6 +54,11 @@ NimBLEAdvertising::NimBLEAdvertising() {
|
|||
m_advParams.itvl_min = 0;
|
||||
m_advParams.itvl_max = 0;
|
||||
|
||||
m_customAdvData = false;
|
||||
m_customScanResponseData = false;
|
||||
m_scanResp = true;
|
||||
m_advDataSet = false;
|
||||
|
||||
} // NimBLEAdvertising
|
||||
|
||||
|
||||
|
@ -64,6 +68,7 @@ NimBLEAdvertising::NimBLEAdvertising() {
|
|||
*/
|
||||
void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||
m_serviceUUIDs.push_back(serviceUUID);
|
||||
m_advDataSet = false;
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
|
@ -76,45 +81,74 @@ void NimBLEAdvertising::addServiceUUID(const char* serviceUUID) {
|
|||
} // addServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a service uuid to exposed list of services.
|
||||
* @param [in] serviceUUID The UUID of the service to expose.
|
||||
*/
|
||||
void NimBLEAdvertising::removeServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||
//m_serviceUUIDs.erase(std::remove_if(m_serviceUUIDs.begin(), m_serviceUUIDs.end(),[serviceUUID](const NimBLEUUID &s) {return serviceUUID == s;}), m_serviceUUIDs.end());
|
||||
for(auto it = m_serviceUUIDs.begin(); it != m_serviceUUIDs.end(); ++it) {
|
||||
if((*it) == serviceUUID) {
|
||||
m_serviceUUIDs.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_advDataSet = false;
|
||||
} // addServiceUUID
|
||||
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
void NimBLEAdvertising::setMinPreferred(uint16_t mininterval) {
|
||||
//m_advData.min_interval = mininterval;
|
||||
} //
|
||||
|
||||
void NimBLEAdvertising::setMaxPreferred(uint16_t maxinterval) {
|
||||
//m_advData.max_interval = maxinterval;
|
||||
} //
|
||||
/*******************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @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,9 +179,13 @@ 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.
|
||||
* @details The use of this function will replace any data set with addServiceUUID\n
|
||||
* or setAppearance. If you wish for these to be advertised you must include them\n
|
||||
* in the advertisementData parameter sent.
|
||||
*/
|
||||
|
||||
void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisementData) {
|
||||
|
@ -166,6 +204,8 @@ void NimBLEAdvertising::setAdvertisementData(NimBLEAdvertisementData& advertisem
|
|||
/**
|
||||
* @brief Set the advertisement data that is to be published in a scan response.
|
||||
* @param [in] advertisementData The data to be advertised.
|
||||
* @details Calling this without also using setAdvertisementData will have no effect.\n
|
||||
* When using custom scan response data you must also use custom advertisement data.
|
||||
*/
|
||||
void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertisementData) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setScanResponseData");
|
||||
|
@ -182,10 +222,10 @@ void NimBLEAdvertising::setScanResponseData(NimBLEAdvertisementData& advertiseme
|
|||
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
* Start advertising.
|
||||
* @return N/A.
|
||||
* @param [in] duration The duration, in seconds, to advertise, 0 == advertise forever.
|
||||
* @param [in] advCompleteCB A pointer to a callback to be invoked when advertising ends.
|
||||
*/
|
||||
void NimBLEAdvertising::start() {
|
||||
void NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdvertising *pAdv)) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Advertising start: customAdvData: %d, customScanResponseData: %d", m_customAdvData, m_customScanResponseData);
|
||||
|
||||
// If Host is not synced we cannot start advertising.
|
||||
|
@ -211,6 +251,15 @@ void NimBLEAdvertising::start() {
|
|||
return;
|
||||
}
|
||||
|
||||
if(duration == 0){
|
||||
duration = BLE_HS_FOREVER;
|
||||
}
|
||||
else{
|
||||
duration = duration*1000; // convert duration to milliseconds
|
||||
}
|
||||
|
||||
m_advCompCB = advCompleteCB;
|
||||
|
||||
int rc = 0;
|
||||
|
||||
if (!m_customAdvData && !m_advDataSet) {
|
||||
|
@ -356,13 +405,13 @@ void NimBLEAdvertising::start() {
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
rc = ble_gap_adv_start(0, NULL, BLE_HS_FOREVER,
|
||||
rc = ble_gap_adv_start(0, NULL, duration,
|
||||
&m_advParams,
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent : NULL,
|
||||
pServer);
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent : NimBLEAdvertising::handleGapEvent,
|
||||
(pServer != nullptr) ? (void*)pServer : (void*)this);
|
||||
#else
|
||||
rc = ble_gap_adv_start(0, NULL, BLE_HS_FOREVER,
|
||||
&m_advParams, NULL,NULL);
|
||||
rc = ble_gap_adv_start(0, NULL, duration,
|
||||
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
|
||||
#endif
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
|
@ -375,8 +424,6 @@ void NimBLEAdvertising::start() {
|
|||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* Stop advertising.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEAdvertising::stop() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||
|
@ -391,6 +438,25 @@ void NimBLEAdvertising::stop() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Handles the callback when advertising stops.
|
||||
*/
|
||||
void NimBLEAdvertising::advCompleteCB() {
|
||||
if(m_advCompCB != nullptr) {
|
||||
m_advCompCB(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if currently advertising.
|
||||
* @return true if advertising is active.
|
||||
*/
|
||||
bool NimBLEAdvertising::isAdvertising() {
|
||||
return ble_gap_adv_active();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Host reset seems to clear advertising data,
|
||||
* we need clear the flag so it reloads it.
|
||||
*/
|
||||
|
@ -399,6 +465,22 @@ void NimBLEAdvertising::onHostReset() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handler for gap events when not using peripheral role.
|
||||
* @param [in] event the event data.
|
||||
* @param [in] arg pointer to the advertising instance.
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEAdvertising *pAdv = (NimBLEAdvertising*)arg;
|
||||
|
||||
if(event->type == BLE_GAP_EVENT_ADV_COMPLETE) {
|
||||
pAdv->advCompleteCB();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add data to the payload to be advertised.
|
||||
* @param [in] data The data to be added to the payload.
|
||||
|
@ -411,6 +493,19 @@ void NimBLEAdvertisementData::addData(const std::string &data) {
|
|||
} // addData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add data to the payload to be advertised.
|
||||
* @param [in] data The data to be added to the payload.
|
||||
* @param [in] length The size of data to be added to the payload.
|
||||
*/
|
||||
void NimBLEAdvertisementData::addData(char * data, size_t length){
|
||||
if ((m_payload.length() + length) > BLE_HS_ADV_MAX_SZ) {
|
||||
return;
|
||||
}
|
||||
m_payload.append(data,length);
|
||||
} // addData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the appearance.
|
||||
* @param [in] appearance The appearance code value.
|
||||
|
@ -427,8 +522,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 +560,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 +576,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 +589,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 +603,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 +641,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 +679,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());
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||
void setShortName(const std::string &name);
|
||||
void addData(const std::string &data); // Add data to the payload.
|
||||
void addData(char * data, size_t length);
|
||||
std::string getPayload(); // Retrieve the current advert payload.
|
||||
|
||||
private:
|
||||
|
@ -75,34 +76,35 @@ public:
|
|||
NimBLEAdvertising();
|
||||
void addServiceUUID(const NimBLEUUID &serviceUUID);
|
||||
void addServiceUUID(const char* serviceUUID);
|
||||
void start();
|
||||
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
||||
void start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||
void stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setAdvertisementType(uint8_t adv_type);
|
||||
void setMaxInterval(uint16_t maxinterval);
|
||||
void setMinInterval(uint16_t mininterval);
|
||||
void setAdvertisementData(NimBLEAdvertisementData& advertisementData);
|
||||
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
|
||||
void setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly);
|
||||
void setScanResponseData(NimBLEAdvertisementData& advertisementData);
|
||||
void setPrivateAddress(uint8_t type = BLE_ADDR_RANDOM);
|
||||
|
||||
void setMinPreferred(uint16_t);
|
||||
void setMaxPreferred(uint16_t);
|
||||
void setScanResponse(bool);
|
||||
void advCompleteCB();
|
||||
bool isAdvertising();
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
|
||||
void onHostReset();
|
||||
void onHostReset();
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
|
||||
ble_hs_adv_fields m_advData;
|
||||
ble_hs_adv_fields m_scanData;
|
||||
ble_gap_adv_params m_advParams;
|
||||
ble_hs_adv_fields m_advData;
|
||||
ble_hs_adv_fields m_scanData;
|
||||
ble_gap_adv_params m_advParams;
|
||||
std::vector<NimBLEUUID> m_serviceUUIDs;
|
||||
bool m_customAdvData = false; // Are we using custom advertising data?
|
||||
bool m_customScanResponseData = false; // Are we using custom scan response data?
|
||||
bool m_scanResp = true;
|
||||
bool m_advDataSet = false;
|
||||
bool m_customAdvData;
|
||||
bool m_customScanResponseData;
|
||||
bool m_scanResp;
|
||||
bool m_advDataSet;
|
||||
void (*m_advCompCB)(NimBLEAdvertising *pAdv);
|
||||
|
||||
};
|
||||
|
||||
|