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.
|
||||
|
||||
**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.
|
||||
<br/>
|
||||
|
||||
## Resource use improvement:
|
||||
## Resource use improvement
|
||||
|
||||
### (Original) BLE_client example comparison (Debug):
|
||||
#### Arduino BLE Library
|
||||
|
@ -51,47 +34,54 @@ 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!**
|
||||
<br/>
|
||||
|
||||
# Installation
|
||||
**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
|
||||
|
||||
# Installation:
|
||||
|
||||
Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
|
||||
**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.
|
||||
|
||||
|
||||
# Usage:
|
||||
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.
|
||||
|
||||
If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
|
||||
|
||||
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.
|
||||
|
||||
More advanced examples highlighting many available features are in examples/ NimBLE_Server, NimBLE_Client.
|
||||
|
||||
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());
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
|
|
|
@ -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 **/);
|
||||
****************************************************/
|
||||
|
||||
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);
|
||||
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 (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(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 (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(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 (fields->appearance_is_present) {
|
||||
NIMBLE_LOGD(LOG_TAG, " appearance=0x%04x", fields->appearance);
|
||||
setAppearance(fields->appearance);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/**** TODO: create storage and fucntions for these parameters
|
||||
if (fields->public_tgt_addr != NULL) {
|
||||
length -= 1 + field->length;
|
||||
data += 1 + field->length;
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.appearance_is_present) {
|
||||
setAppearance(fields.appearance);
|
||||
}
|
||||
|
||||
if (fields.mfg_data != NULL) {
|
||||
setManufacturerData(std::string(reinterpret_cast<char*>(fields.mfg_data), fields.mfg_data_len));
|
||||
}
|
||||
|
||||
/* TODO: create storage and fucntions for these parameters
|
||||
if (fields.public_tgt_addr != NULL) {
|
||||
NIMBLE_LOGD(LOG_TAG, " public_tgt_addr=");
|
||||
u8p = fields->public_tgt_addr;
|
||||
for (i = 0; i < fields->num_public_tgt_addrs; i++) {
|
||||
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,6 +46,14 @@ 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) {
|
||||
std::string data = getManufacturerData();
|
||||
|
@ -57,27 +65,53 @@ 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 isAdvertisingService(const NimBLEUUID &uuid) const;
|
||||
bool haveAppearance();
|
||||
bool haveManufacturerData();
|
||||
bool haveName();
|
||||
|
@ -85,23 +119,19 @@ public:
|
|||
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();
|
||||
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;
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#if defined(CONFIG_BT_ENABLED)
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include "NimBLEBeacon.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
|
@ -22,6 +23,10 @@
|
|||
|
||||
static const char* LOG_TAG = "NimBLEBeacon";
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a default beacon object.
|
||||
*/
|
||||
NimBLEBeacon::NimBLEBeacon() {
|
||||
m_beaconData.manufacturerId = 0x4c00;
|
||||
m_beaconData.subType = 0x02;
|
||||
|
@ -32,32 +37,64 @@ NimBLEBeacon::NimBLEBeacon() {
|
|||
memset(m_beaconData.proximityUUID, 0, sizeof(m_beaconData.proximityUUID));
|
||||
} // NimBLEBeacon
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the data that is being advertised.
|
||||
* @return The advertised data.
|
||||
*/
|
||||
std::string NimBLEBeacon::getData() {
|
||||
return std::string((char*) &m_beaconData, sizeof(m_beaconData));
|
||||
} // getData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the major value being advertised.
|
||||
* @return The major value advertised.
|
||||
*/
|
||||
uint16_t NimBLEBeacon::getMajor() {
|
||||
return m_beaconData.major;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the manufacturer ID being advertised.
|
||||
* @return The manufacturer ID value advertised.
|
||||
*/
|
||||
uint16_t NimBLEBeacon::getManufacturerId() {
|
||||
return m_beaconData.manufacturerId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the minor value being advertised.
|
||||
* @return minor value advertised.
|
||||
*/
|
||||
uint16_t NimBLEBeacon::getMinor() {
|
||||
return m_beaconData.minor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the proximity UUID being advertised.
|
||||
* @return The UUID advertised.
|
||||
*/
|
||||
NimBLEUUID NimBLEBeacon::getProximityUUID() {
|
||||
return NimBLEUUID(m_beaconData.proximityUUID, 16, false);
|
||||
return NimBLEUUID(m_beaconData.proximityUUID, 16, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the signal power being advertised.
|
||||
* @return signal power level advertised.
|
||||
*/
|
||||
int8_t NimBLEBeacon::getSignalPower() {
|
||||
return m_beaconData.signalPower;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
* @brief Set the raw data for the beacon record.
|
||||
* @param [in] data The raw beacon data.
|
||||
*/
|
||||
void NimBLEBeacon::setData(const std::string &data) {
|
||||
if (data.length() != sizeof(m_beaconData)) {
|
||||
|
@ -68,24 +105,51 @@ void NimBLEBeacon::setData(const std::string &data) {
|
|||
memcpy(&m_beaconData, data.data(), sizeof(m_beaconData));
|
||||
} // setData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the major value.
|
||||
* @param [in] major The major value.
|
||||
*/
|
||||
void NimBLEBeacon::setMajor(uint16_t major) {
|
||||
m_beaconData.major = ENDIAN_CHANGE_U16(major);
|
||||
} // setMajor
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the manufacturer ID.
|
||||
* @param [in] manufacturerId The manufacturer ID value.
|
||||
*/
|
||||
void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) {
|
||||
m_beaconData.manufacturerId = ENDIAN_CHANGE_U16(manufacturerId);
|
||||
} // setManufacturerId
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the minor value.
|
||||
* @param [in] minor The minor value.
|
||||
*/
|
||||
void NimBLEBeacon::setMinor(uint16_t minor) {
|
||||
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
||||
} // setMinior
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the proximity UUID.
|
||||
* @param [in] uuid The proximity UUID.
|
||||
*/
|
||||
void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) {
|
||||
NimBLEUUID temp_uuid = uuid;
|
||||
temp_uuid.to128();
|
||||
memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16);
|
||||
std::reverse_copy(temp_uuid.getNative()->u128.value,
|
||||
temp_uuid.getNative()->u128.value + 16,
|
||||
m_beaconData.proximityUUID);
|
||||
} // setProximityUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the signal power.
|
||||
* @param [in] signalPower The signal power value.
|
||||
*/
|
||||
void NimBLEBeacon::setSignalPower(int8_t signalPower) {
|
||||
m_beaconData.signalPower = signalPower;
|
||||
} // setSignalPower
|
||||
|
|
|
@ -16,16 +16,18 @@
|
|||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
||||
#include "NimBLECharacteristic.h"
|
||||
#include "NimBLE2902.h"
|
||||
#include "NimBLE2904.h"
|
||||
#include "NimBLEDevice.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
#define NULL_HANDLE (0xffff)
|
||||
#define NIMBLE_SUB_NOTIFY 0x0001
|
||||
#define NIMBLE_SUB_INDICATE 0x0002
|
||||
|
||||
static NimBLECharacteristicCallbacks defaultCallback;
|
||||
static const char* LOG_TAG = "NimBLECharacteristic";
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a characteristic
|
||||
* @param [in] uuid - UUID (const char*) for the characteristic.
|
||||
|
@ -58,6 +60,9 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop
|
|||
* @brief Destructor.
|
||||
*/
|
||||
NimBLECharacteristic::~NimBLECharacteristic() {
|
||||
for(auto &it : m_dscVec) {
|
||||
delete it;
|
||||
}
|
||||
} // ~NimBLECharacteristic
|
||||
|
||||
|
||||
|
@ -65,6 +70,7 @@ NimBLECharacteristic::~NimBLECharacteristic() {
|
|||
* @brief Create a new BLE Descriptor associated with this characteristic.
|
||||
* @param [in] uuid - The UUID of the descriptor.
|
||||
* @param [in] properties - The properties of the descriptor.
|
||||
* @param [in] max_len - The max length in bytes of the descriptor value.
|
||||
* @return The new BLE descriptor.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint32_t properties, uint16_t max_len) {
|
||||
|
@ -76,25 +82,15 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
|
|||
* @brief Create a new BLE Descriptor associated with this characteristic.
|
||||
* @param [in] uuid - The UUID of the descriptor.
|
||||
* @param [in] properties - The properties of the descriptor.
|
||||
* @param [in] max_len - The max length in bytes of the descriptor value.
|
||||
* @return The new BLE descriptor.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
||||
NimBLEDescriptor* pDescriptor = nullptr;
|
||||
if(uuid == NimBLEUUID(uint16_t(0x2902))) {
|
||||
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
|
||||
assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set");
|
||||
}
|
||||
// We cannot have more than one 2902 descriptor, if it's already been created just return a pointer to it.
|
||||
pDescriptor = getDescriptorByUUID(uuid);
|
||||
if(pDescriptor == nullptr) {
|
||||
pDescriptor = new NimBLE2902(this);
|
||||
} else {
|
||||
return pDescriptor;
|
||||
}
|
||||
|
||||
assert(0 && "0x2902 descriptors cannot be manually created");
|
||||
} else if (uuid == NimBLEUUID(uint16_t(0x2904))) {
|
||||
pDescriptor = new NimBLE2904(this);
|
||||
|
||||
} else {
|
||||
pDescriptor = new NimBLEDescriptor(uuid, properties, max_len, this);
|
||||
}
|
||||
|
@ -106,8 +102,8 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid,
|
|||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
|
||||
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
||||
return getDescriptorByUUID(NimBLEUUID(uuid));
|
||||
|
@ -116,8 +112,8 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* uuid) {
|
|||
|
||||
/**
|
||||
* @brief Return the BLE Descriptor for the given UUID if associated with this characteristic.
|
||||
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
|
||||
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
* @param [in] uuid The UUID of the descriptor that we wish to retrieve.
|
||||
* @return pointer to the NimBLEDescriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||
*/
|
||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &uuid) {
|
||||
for (auto &it : m_dscVec) {
|
||||
|
@ -138,6 +134,10 @@ uint16_t NimBLECharacteristic::getHandle() {
|
|||
} // getHandle
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the properties of the characteristic.
|
||||
* @return The properties of the characteristic.
|
||||
*/
|
||||
uint16_t NimBLECharacteristic::getProperties() {
|
||||
return m_properties;
|
||||
} // getProperties
|
||||
|
@ -162,7 +162,7 @@ NimBLEUUID NimBLECharacteristic::getUUID() {
|
|||
|
||||
/**
|
||||
* @brief Retrieve the current value of the characteristic.
|
||||
* @return A pointer to storage containing the current characteristic value.
|
||||
* @return A std::string containing the current characteristic value.
|
||||
*/
|
||||
std::string NimBLECharacteristic::getValue(time_t *timestamp) {
|
||||
portENTER_CRITICAL(&m_valMux);
|
||||
|
@ -189,12 +189,16 @@ size_t NimBLECharacteristic::getDataLength() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief STATIC callback to handle events from the NimBLE stack.
|
||||
*/
|
||||
int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
struct ble_gap_conn_desc desc;
|
||||
NimBLECharacteristic* pCharacteristic = (NimBLECharacteristic*)arg;
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "Characteristic %s %s event", pCharacteristic->getUUID().toString().c_str(),
|
||||
|
@ -207,7 +211,10 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||
// If the packet header is only 8 bytes this is a follow up of a long read
|
||||
// so we don't want to call the onRead() callback again.
|
||||
if(ctxt->om->om_pkthdr_len > 8) {
|
||||
rc = ble_gap_conn_find(conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
|
||||
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc);
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&pCharacteristic->m_valMux);
|
||||
|
@ -233,14 +240,15 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||
if((len + next->om_len) > BLE_ATT_ATTR_MAX_LEN) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
memcpy(&buf[len-1], next->om_data, next->om_len);
|
||||
memcpy(&buf[len], next->om_data, next->om_len);
|
||||
len += next->om_len;
|
||||
next = SLIST_NEXT(next, om_next);
|
||||
}
|
||||
|
||||
rc = ble_gap_conn_find(conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
pCharacteristic->setValue(buf, len);
|
||||
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic);
|
||||
|
||||
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic, &desc);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
|
@ -253,21 +261,34 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
|
|||
|
||||
|
||||
/**
|
||||
* @brief Set the subscribe status for this characteristic.
|
||||
* This will maintain a map of subscribed clients and their indicate/notify status.
|
||||
* @return N/A
|
||||
* @brief Get the number of clients subscribed to the characteristic.
|
||||
* @returns Number of clients subscribed to notifications / indications.
|
||||
*/
|
||||
size_t NimBLECharacteristic::getSubscribedCount() {
|
||||
return m_subscribedVec.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the subscribe status for this characteristic.\n
|
||||
* This will maintain a vector of subscribed clients and their indicate/notify status.
|
||||
*/
|
||||
void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
||||
uint16_t subVal = 0;
|
||||
if(event->subscribe.cur_notify) {
|
||||
subVal |= NIMBLE_DESC_FLAG_NOTIFY;
|
||||
ble_gap_conn_desc desc;
|
||||
if(ble_gap_conn_find(event->subscribe.conn_handle, &desc) != 0) {
|
||||
return;
|
||||
}
|
||||
if(event->subscribe.cur_indicate) {
|
||||
subVal |= NIMBLE_DESC_FLAG_INDICATE;
|
||||
|
||||
uint16_t subVal = 0;
|
||||
if(event->subscribe.cur_notify > 0 && (m_properties & NIMBLE_PROPERTY::NOTIFY)) {
|
||||
subVal |= NIMBLE_SUB_NOTIFY;
|
||||
}
|
||||
if(event->subscribe.cur_indicate && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
|
||||
subVal |= NIMBLE_SUB_INDICATE;
|
||||
}
|
||||
|
||||
if(m_pTaskData != nullptr) {
|
||||
m_pTaskData->rc = (subVal & NIMBLE_DESC_FLAG_INDICATE) ? 0 :
|
||||
m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 :
|
||||
NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED;
|
||||
xTaskNotifyGive(m_pTaskData->task);
|
||||
}
|
||||
|
@ -275,48 +296,35 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
|
|||
NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d",
|
||||
event->subscribe.conn_handle, subVal);
|
||||
|
||||
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID(uint16_t(0x2902));
|
||||
if(p2902 == nullptr){
|
||||
ESP_LOGE(LOG_TAG, "No 2902 descriptor found for %s",
|
||||
std::string(getUUID()).c_str());
|
||||
return;
|
||||
}
|
||||
m_pCallbacks->onSubscribe(this, &desc, subVal);
|
||||
|
||||
p2902->setNotifications(subVal & NIMBLE_DESC_FLAG_NOTIFY);
|
||||
p2902->setIndications(subVal & NIMBLE_DESC_FLAG_INDICATE);
|
||||
p2902->m_pCallbacks->onWrite(p2902);
|
||||
|
||||
|
||||
auto it = p2902->m_subscribedVec.begin();
|
||||
for(;it != p2902->m_subscribedVec.end(); ++it) {
|
||||
if((*it).conn_id == event->subscribe.conn_handle) {
|
||||
auto it = m_subscribedVec.begin();
|
||||
for(;it != m_subscribedVec.end(); ++it) {
|
||||
if((*it).first == event->subscribe.conn_handle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(subVal > 0) {
|
||||
if(it == p2902->m_subscribedVec.end()) {
|
||||
chr_sub_status_t client_sub;
|
||||
client_sub.conn_id = event->subscribe.conn_handle;
|
||||
client_sub.sub_val = subVal;
|
||||
p2902->m_subscribedVec.push_back(client_sub);
|
||||
if(it == m_subscribedVec.end()) {
|
||||
m_subscribedVec.push_back({event->subscribe.conn_handle, subVal});
|
||||
return;
|
||||
}
|
||||
|
||||
(*it).sub_val = subVal;
|
||||
(*it).second = subVal;
|
||||
|
||||
} else if(it != p2902->m_subscribedVec.end()) {
|
||||
p2902->m_subscribedVec.erase(it);
|
||||
p2902->m_subscribedVec.shrink_to_fit();
|
||||
} else if(it != m_subscribedVec.end()) {
|
||||
m_subscribedVec.erase(it);
|
||||
m_subscribedVec.shrink_to_fit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send an indication.
|
||||
* An indication is a transmission of up to the first 20 bytes of the characteristic value. An indication
|
||||
* will block waiting a positive confirmation from the client.
|
||||
* @return N/A
|
||||
* @brief Send an indication.\n
|
||||
* An indication is a transmission of up to the first 20 bytes of the characteristic value.\n
|
||||
* An indication will block waiting for a positive confirmation from the client.
|
||||
*/
|
||||
void NimBLECharacteristic::indicate() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", getDataLength());
|
||||
|
@ -325,23 +333,24 @@ void NimBLECharacteristic::indicate() {
|
|||
} // indicate
|
||||
|
||||
/**
|
||||
* @brief Send a notify.
|
||||
* A notification is a transmission of up to the first 20 bytes of the characteristic value. An notification
|
||||
* will not block; it is a fire and forget.
|
||||
* @return N/A.
|
||||
* @brief Send a notification.\n
|
||||
* A notification is a transmission of up to the first 20 bytes of the characteristic value.\n
|
||||
* A notification will not block; it is a fire and forget.
|
||||
* @param[in] is_notification if true sends a notification, false sends an indication.
|
||||
*/
|
||||
void NimBLECharacteristic::notify(bool is_notification) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", getDataLength());
|
||||
|
||||
NimBLE2902* p2902 = (NimBLE2902*)getDescriptorByUUID(uint16_t(0x2902));
|
||||
|
||||
if(p2902 == nullptr) {
|
||||
if(!(m_properties & NIMBLE_PROPERTY::NOTIFY) &&
|
||||
!(m_properties & NIMBLE_PROPERTY::INDICATE))
|
||||
{
|
||||
NIMBLE_LOGE(LOG_TAG,
|
||||
"<< notify-Error; Notify/indicate not enabled for characterisitc: %s",
|
||||
std::string(getUUID()).c_str());
|
||||
}
|
||||
|
||||
if (p2902->m_subscribedVec.size() == 0) {
|
||||
if (m_subscribedVec.size() == 0) {
|
||||
NIMBLE_LOGD(LOG_TAG, "<< notify: No clients subscribed.");
|
||||
return;
|
||||
}
|
||||
|
@ -355,18 +364,18 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
(m_properties & BLE_GATT_CHR_F_READ_ENC);
|
||||
int rc = 0;
|
||||
|
||||
for (auto &it : p2902->m_subscribedVec) {
|
||||
uint16_t _mtu = getService()->getServer()->getPeerMTU(it.conn_id);
|
||||
for (auto &it : m_subscribedVec) {
|
||||
uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first);
|
||||
|
||||
// check if connected and subscribed
|
||||
if(_mtu == 0 || it.sub_val == 0) {
|
||||
if(_mtu == 0 || it.second == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if security requirements are satisfied
|
||||
if(reqSec) {
|
||||
struct ble_gap_conn_desc desc;
|
||||
rc = ble_gap_conn_find(it.conn_id, &desc);
|
||||
rc = ble_gap_conn_find(it.first, &desc);
|
||||
if(rc != 0 || !desc.sec_state.encrypted) {
|
||||
continue;
|
||||
}
|
||||
|
@ -376,13 +385,13 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3);
|
||||
}
|
||||
|
||||
if(is_notification && (!(it.sub_val & NIMBLE_DESC_FLAG_NOTIFY))) {
|
||||
if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) {
|
||||
NIMBLE_LOGW(LOG_TAG,
|
||||
"Sending notification to client subscribed to indications, sending indication instead");
|
||||
is_notification = false;
|
||||
}
|
||||
|
||||
if(!is_notification && (!(it.sub_val & NIMBLE_DESC_FLAG_INDICATE))) {
|
||||
if(!is_notification && (!(it.second & NIMBLE_SUB_INDICATE))) {
|
||||
NIMBLE_LOGW(LOG_TAG,
|
||||
"Sending indication to client subscribed to notification, sending notification instead");
|
||||
is_notification = true;
|
||||
|
@ -399,7 +408,7 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
|
||||
rc = ble_gattc_indicate_custom(it.conn_id, m_handle, om);
|
||||
rc = ble_gattc_indicate_custom(it.first, m_handle, om);
|
||||
if(rc != 0){
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT;
|
||||
} else {
|
||||
|
@ -418,7 +427,7 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE;
|
||||
}
|
||||
} else {
|
||||
rc = ble_gattc_notify_custom(it.conn_id, m_handle, om);
|
||||
rc = ble_gattc_notify_custom(it.first, m_handle, om);
|
||||
if(rc == 0) {
|
||||
statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY;
|
||||
} else {
|
||||
|
@ -435,7 +444,8 @@ void NimBLECharacteristic::notify(bool is_notification) {
|
|||
|
||||
/**
|
||||
* @brief Set the callback handlers for this characteristic.
|
||||
* @param [in] pCallbacks An instance of a callbacks structure used to define any callbacks for the characteristic.
|
||||
* @param [in] pCallbacks An instance of a NimBLECharacteristicCallbacks class\n
|
||||
* used to define any callbacks for the characteristic.
|
||||
*/
|
||||
void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
|
@ -473,11 +483,9 @@ void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Set the value of the characteristic from string data.
|
||||
* We set the value of the characteristic from the bytes contained in the
|
||||
* string.
|
||||
* @param [in] Set the value of the characteristic.
|
||||
* @return N/A.
|
||||
* @brief Set the value of the characteristic from string data.\n
|
||||
* We set the value of the characteristic from the bytes contained in the string.
|
||||
* @param [in] value the std::string value of the characteristic.
|
||||
*/
|
||||
void NimBLECharacteristic::setValue(const std::string &value) {
|
||||
setValue((uint8_t*)(value.data()), value.length());
|
||||
|
@ -515,6 +523,14 @@ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic
|
|||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
|
||||
} // onRead
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a read request.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
* @param [in] desc The connection description struct that is associated with the peer that performed the read.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default");
|
||||
} // onRead
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a write request.
|
||||
|
@ -524,6 +540,14 @@ void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristi
|
|||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
|
||||
} // onWrite
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a write request.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
* @param [in] desc The connection description struct that is associated with the peer that performed the write.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default");
|
||||
} // onWrite
|
||||
|
||||
/**
|
||||
* @brief Callback function to support a Notify request.
|
||||
|
@ -537,12 +561,31 @@ void NimBLECharacteristicCallbacks::onNotify(NimBLECharacteristic* pCharacterist
|
|||
/**
|
||||
* @brief Callback function to support a Notify/Indicate Status report.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
* @param [in] s Status of the notification/indication
|
||||
* @param [in] code Additional code of underlying errors
|
||||
* @param [in] s Status of the notification/indication.
|
||||
* @param [in] code Additional return code from the NimBLE stack.
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code) {
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
||||
} // onStatus
|
||||
|
||||
|
||||
/**
|
||||
* @brief Callback function called when a client changes subscription status.
|
||||
* @param [in] pCharacteristic The characteristic that is the source of the event.
|
||||
* @param [in] desc The connection description struct that is associated with the client.
|
||||
* @param [in] subValue The subscription status:
|
||||
* * 0 = Un-Subscribed
|
||||
* * 1 = Notifications
|
||||
* * 2 = Indications
|
||||
* * 3 = Notifications and Indications
|
||||
*/
|
||||
void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacteristic,
|
||||
ble_gap_conn_desc* desc,
|
||||
uint16_t subValue)
|
||||
{
|
||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
|
||||
}
|
||||
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -75,6 +75,15 @@ public:
|
|||
NimBLEUUID getUUID();
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
|
||||
/**
|
||||
* @brief A template to convert the characteristic data to <type\>.
|
||||
* @tparam T The type to convert the data to.
|
||||
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
|
||||
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <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>getValue<type>(×tamp, skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
|
||||
std::string value = getValue();
|
||||
|
@ -90,6 +99,10 @@ public:
|
|||
void setValue(const uint8_t* data, size_t size);
|
||||
void setValue(const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the characteristic value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
|
@ -97,6 +110,7 @@ public:
|
|||
|
||||
std::string toString();
|
||||
uint16_t getHandle();
|
||||
size_t getSubscribedCount();
|
||||
|
||||
private:
|
||||
|
||||
|
@ -132,6 +146,8 @@ private:
|
|||
ble_task_data_t *m_pTaskData;
|
||||
portMUX_TYPE m_valMux;
|
||||
time_t m_timestamp;
|
||||
|
||||
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
|
||||
}; // NimBLECharacteristic
|
||||
|
||||
|
||||
|
@ -144,6 +160,12 @@ private:
|
|||
*/
|
||||
class NimBLECharacteristicCallbacks {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief An enum to provide the callback the status of the
|
||||
* notification/indication, implemented for backward compatibility.
|
||||
* @deprecated To be removed in the future as the NimBLE stack return code is also provided.
|
||||
*/
|
||||
typedef enum {
|
||||
SUCCESS_INDICATE,
|
||||
SUCCESS_NOTIFY,
|
||||
|
@ -157,9 +179,12 @@ public:
|
|||
|
||||
virtual ~NimBLECharacteristicCallbacks();
|
||||
virtual void onRead(NimBLECharacteristic* pCharacteristic);
|
||||
virtual void onRead(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
|
||||
virtual void onWrite(NimBLECharacteristic* pCharacteristic);
|
||||
virtual void onWrite(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
|
||||
virtual void onNotify(NimBLECharacteristic* pCharacteristic);
|
||||
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
|
||||
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue);
|
||||
};
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
|
|
|
@ -48,8 +48,12 @@ static NimBLEClientCallbacks defaultCallbacks;
|
|||
*
|
||||
*/
|
||||
|
||||
NimBLEClient::NimBLEClient()
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Constructor, private - only callable by NimBLEDevice::createClient
|
||||
* to ensure proper handling of the list of client objects.
|
||||
*/
|
||||
NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(peerAddress) {
|
||||
m_pClientCallbacks = &defaultCallbacks;
|
||||
m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||
m_isConnected = false;
|
||||
|
@ -86,7 +90,7 @@ NimBLEClient::~NimBLEClient() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Delete any existing services.
|
||||
* @brief Delete all service objects created by this client and clear the vector.
|
||||
*/
|
||||
void NimBLEClient::deleteServices() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> deleteServices");
|
||||
|
@ -123,30 +127,36 @@ size_t NimBLEClient::deleteService(const NimBLEUUID &uuid) {
|
|||
|
||||
|
||||
/**
|
||||
* NOT NEEDED
|
||||
*/
|
||||
/*
|
||||
void NimBLEClient::onHostReset() {
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add overloaded function to ease connect to peer device with not public address
|
||||
*/
|
||||
bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices) {
|
||||
NimBLEAddress address(device->getAddress());
|
||||
uint8_t type = device->getAddressType();
|
||||
return connect(address, type, refreshServices);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect to the partner (BLE Server).
|
||||
* @param [in] address The address of the partner.
|
||||
* @brief Connect to the BLE Server.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) {
|
||||
bool NimBLEClient::connect(bool deleteAttibutes) {
|
||||
return connect(m_peerAddress, deleteAttibutes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect to an advertising device.
|
||||
* @param [in] device The device to connect to.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes) {
|
||||
NimBLEAddress address(device->getAddress());
|
||||
return connect(address, deleteAttibutes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Connect to the BLE Server.
|
||||
* @param [in] address The address of the server.
|
||||
* @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
|
||||
* have created and clears the vectors after successful connection.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
||||
|
||||
if(!NimBLEDevice::m_synced) {
|
||||
|
@ -163,17 +173,23 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
|||
return false;
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
if(address == NimBLEAddress("")) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Invalid peer address;(NULL)");
|
||||
return false;
|
||||
} else if(m_peerAddress != address) {
|
||||
m_peerAddress = address;
|
||||
}
|
||||
|
||||
ble_addr_t peerAddrt;
|
||||
memcpy(&peerAddrt.val, address.getNative(),6);
|
||||
peerAddrt.type = type;
|
||||
memcpy(&peerAddrt.val, m_peerAddress.getNative(),6);
|
||||
peerAddrt.type = m_peerAddress.getType();
|
||||
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
m_pTaskData = &taskData;
|
||||
|
||||
/** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
|
||||
int rc = 0;
|
||||
|
||||
/* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
|
||||
* timeout (default value of m_connectTimeout).
|
||||
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
|
||||
*/
|
||||
|
@ -186,10 +202,9 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
|||
}while(rc == BLE_HS_EBUSY);
|
||||
|
||||
if (rc != 0 && rc != BLE_HS_EDONE) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; addr_type=%d "
|
||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; "
|
||||
"addr=%s, rc=%d; %s",
|
||||
type,
|
||||
m_peerAddress.toString().c_str(),
|
||||
std::string(m_peerAddress).c_str(),
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
m_pTaskData = nullptr;
|
||||
m_waitingToConnect = false;
|
||||
|
@ -205,8 +220,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
|||
return false;
|
||||
}
|
||||
|
||||
if(refreshServices) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Refreshing Services for: (%s)", address.toString().c_str());
|
||||
if(deleteAttibutes) {
|
||||
deleteServices();
|
||||
}
|
||||
|
||||
|
@ -218,12 +232,16 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
|||
|
||||
|
||||
/**
|
||||
* @brief Called when a characteristic or descriptor requires encryption or authentication to access it.
|
||||
* This will pair with the device and bond if enabled.
|
||||
* @brief Initiate a secure connection (pair/bond) with the server.\n
|
||||
* Called automatically when a characteristic or descriptor requires encryption or authentication to access it.
|
||||
* @return True on success.
|
||||
*/
|
||||
bool NimBLEClient::secureConnection() {
|
||||
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||
|
||||
int retryCount = 1;
|
||||
|
||||
do {
|
||||
m_pTaskData = &taskData;
|
||||
|
||||
int rc = NimBLEDevice::startSecurity(m_conn_id);
|
||||
|
@ -233,18 +251,19 @@ bool NimBLEClient::secureConnection() {
|
|||
}
|
||||
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
} while (taskData.rc == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING) && retryCount--);
|
||||
|
||||
if(taskData.rc != 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // secureConnection
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disconnect from the peer.
|
||||
* @return N/A.
|
||||
* @return Error code from NimBLE stack, 0 = success.
|
||||
*/
|
||||
int NimBLEClient::disconnect(uint8_t reason) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> disconnect()");
|
||||
|
@ -264,6 +283,12 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
|||
|
||||
/**
|
||||
* @brief Set the connection paramaters to use when connecting to a server.
|
||||
* @param [in] minInterval minimum connection interval in 0.625ms units.
|
||||
* @param [in] maxInterval maximum connection interval in 0.625ms units.
|
||||
* @param [in] latency number of packets allowed to skip (extends max interval)
|
||||
* @param [in] timeout the timeout time in 10ms units before disconnecting
|
||||
* @param [in] scanInterval the scan interval to use when attempting to connect in 0.625ms units.
|
||||
* @param [in] scanWindow the scan window to use when attempting to connect in 0.625ms units.
|
||||
*/
|
||||
void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout,
|
||||
|
@ -271,12 +296,12 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
|
|||
uint16_t minConnTime, uint16_t maxConnTime)*/
|
||||
{
|
||||
|
||||
m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units
|
||||
m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units
|
||||
m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
|
||||
m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
|
||||
m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval)
|
||||
m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
|
||||
m_pConnParams.scan_itvl = scanInterval;
|
||||
m_pConnParams.scan_window = scanWindow;
|
||||
m_pConnParams.itvl_min = minInterval;
|
||||
m_pConnParams.itvl_max = maxInterval;
|
||||
m_pConnParams.latency = latency;
|
||||
m_pConnParams.supervision_timeout = timeout;
|
||||
|
||||
// These are not used by NimBLE at this time - Must leave at defaults
|
||||
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
|
||||
|
@ -284,11 +309,16 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
|
|||
|
||||
int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
|
||||
assert(rc == 0 && "Invalid Connection parameters");
|
||||
}
|
||||
} // setConnectionParams
|
||||
|
||||
|
||||
/**
|
||||
* Update connection parameters can be called only after connection has been established
|
||||
* @brief Update the connection parameters:
|
||||
* * Can only be used after a connection has been established.
|
||||
* @param [in] minInterval minimum connection interval in 0.625ms units.
|
||||
* @param [in] maxInterval maximum connection interval in 0.625ms units.
|
||||
* @param [in] latency number of packets allowed to skip (extends max interval)
|
||||
* @param [in] timeout the timeout time in 10ms units before disconnecting
|
||||
*/
|
||||
void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout)
|
||||
|
@ -308,16 +338,16 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
|||
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
}
|
||||
}
|
||||
} // updateConnParams
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the timeout to wait for connection attempt to complete
|
||||
* @params[in] Time to wait in seconds.
|
||||
* @brief Set the timeout to wait for connection attempt to complete.
|
||||
* @param [in] time The number of seconds before timeout.
|
||||
*/
|
||||
void NimBLEClient::setConnectTimeout(uint8_t time) {
|
||||
m_connectTimeout = (uint32_t)(time * 1000);
|
||||
}
|
||||
} // setConnectTimeout
|
||||
|
||||
|
||||
/**
|
||||
|
@ -334,7 +364,23 @@ uint16_t NimBLEClient::getConnId() {
|
|||
*/
|
||||
NimBLEAddress NimBLEClient::getPeerAddress() {
|
||||
return m_peerAddress;
|
||||
} // getAddress
|
||||
} // getPeerAddress
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the peer address.
|
||||
* @param [in] address The address of the peer that this client is
|
||||
* connected or should connect to.
|
||||
*/
|
||||
void NimBLEClient::setPeerAddress(const NimBLEAddress &address) {
|
||||
if(isConnected()) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Cannot set peer address while connected");
|
||||
return;
|
||||
}
|
||||
|
||||
m_peerAddress = address;
|
||||
NIMBLE_LOGD(LOG_TAG, "Peer address set: %s", std::string(m_peerAddress).c_str());
|
||||
} // setPeerAddress
|
||||
|
||||
|
||||
/**
|
||||
|
@ -381,7 +427,7 @@ std::vector<NimBLERemoteService*>::iterator NimBLEClient::end() {
|
|||
/**
|
||||
* @brief Get the service BLE Remote Service instance corresponding to the uuid.
|
||||
* @param [in] uuid The UUID of the service being sought.
|
||||
* @return A reference to the Service or nullptr if don't know about it.
|
||||
* @return A pointer to the service or nullptr if not found.
|
||||
*/
|
||||
NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
|
||||
return getService(NimBLEUUID(uuid));
|
||||
|
@ -391,7 +437,7 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
|
|||
/**
|
||||
* @brief Get the service object corresponding to the uuid.
|
||||
* @param [in] uuid The UUID of the service being sought.
|
||||
* @return A reference to the Service or nullptr if don't know about it.
|
||||
* @return A pointer to the service or nullptr if not found.
|
||||
*/
|
||||
NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
|
||||
|
@ -416,12 +462,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
|||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the vector of found services.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all services retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored services,
|
||||
* If true it will retrieve all services from the peripheral and return the vector with all services
|
||||
* @return a pointer to the vector of available services.
|
||||
* @brief Get a pointer to the vector of found services.
|
||||
* @param [in] refresh If true the current services vector will be cleared and\n
|
||||
* all services will be retrieved from the peripheral.\n
|
||||
* If false the vector will be returned with the currently stored services.
|
||||
* @return A pointer to the vector of available services.
|
||||
*/
|
||||
std::vector<NimBLERemoteService*>* NimBLEClient::getServices(bool refresh) {
|
||||
if(refresh) {
|
||||
|
@ -435,11 +480,11 @@ std::vector<NimBLERemoteService*>* NimBLEClient::getServices(bool refresh) {
|
|||
}
|
||||
}
|
||||
return &m_servicesVector;
|
||||
}
|
||||
} // getServices
|
||||
|
||||
|
||||
/**
|
||||
* @ Retrieves the full database of attributes that the peripheral has available.
|
||||
* @brief Retrieves the full database of attributes that the peripheral has available.
|
||||
*/
|
||||
void NimBLEClient::discoverAttributes() {
|
||||
for(auto svc: *getServices(true)) {
|
||||
|
@ -447,14 +492,12 @@ void NimBLEClient::discoverAttributes() {
|
|||
chr->getDescriptors(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // discoverAttributes
|
||||
|
||||
|
||||
/**
|
||||
* @brief Ask the remote %BLE server for its services.
|
||||
* A %BLE Server exposes a set of services for its partners. Here we ask the server for its set of
|
||||
* services and wait until we have received them all.
|
||||
* We then ask for the characteristics for each service found and their desciptors.
|
||||
* @brief Ask the remote %BLE server for its services.\n
|
||||
* Here we ask the server for its set of services and wait until we have received them all.
|
||||
* @return true on success otherwise false if an error occurred
|
||||
*/
|
||||
bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
|
||||
|
@ -502,7 +545,7 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief STATIC Callback for the service discovery API function.
|
||||
* @brief STATIC Callback for the service discovery API function.\n
|
||||
* When a service is found or there is none left or there was an error
|
||||
* the API will call this and report findings.
|
||||
*/
|
||||
|
@ -574,6 +617,7 @@ std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUU
|
|||
* @brief Set the value of a specific characteristic associated with a specific service.
|
||||
* @param [in] serviceUUID The service that owns the characteristic.
|
||||
* @param [in] characteristicUUID The characteristic whose value we wish to write.
|
||||
* @param [in] value The value to write to the characteristic.
|
||||
* @returns true if successful otherwise false
|
||||
*/
|
||||
bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
||||
|
@ -600,17 +644,17 @@ bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &cha
|
|||
|
||||
/**
|
||||
* @brief Get the current mtu of this connection.
|
||||
* @returns The MTU value.
|
||||
*/
|
||||
uint16_t NimBLEClient::getMTU() {
|
||||
return ble_att_mtu(m_conn_id);
|
||||
}
|
||||
} // getMTU
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle a received GAP event.
|
||||
*
|
||||
* @param [in] event
|
||||
* @param [in] arg = pointer to the client instance
|
||||
* @param [in] event The event structure sent by the NimBLE stack.
|
||||
* @param [in] arg A pointer to the client instance that registered for this callback.
|
||||
*/
|
||||
/*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEClient* client = (NimBLEClient*)arg;
|
||||
|
@ -783,12 +827,15 @@ uint16_t NimBLEClient::getMTU() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(event->enc_change.status == 0) {
|
||||
if(event->enc_change.status == 0 || event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) {
|
||||
struct ble_gap_conn_desc desc;
|
||||
rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc);
|
||||
rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
|
||||
if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
if (event->enc_change.status == (BLE_HS_ERR_HCI_BASE + BLE_ERR_PINKEY_MISSING)) {
|
||||
// Key is missing, try deleting.
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
} else if(NimBLEDevice::m_securityCallbacks != nullptr) {
|
||||
NimBLEDevice::m_securityCallbacks->onAuthenticationComplete(&desc);
|
||||
} else {
|
||||
client->m_pClientCallbacks->onAuthenticationComplete(&desc);
|
||||
|
@ -855,7 +902,7 @@ uint16_t NimBLEClient::getMTU() {
|
|||
pkey.passkey = NimBLEDevice::m_securityCallbacks->onPassKeyRequest();
|
||||
/////////////////////////////////////////////
|
||||
} else {
|
||||
client->m_pClientCallbacks->onPassKeyRequest();
|
||||
pkey.passkey = client->m_pClientCallbacks->onPassKeyRequest();
|
||||
}
|
||||
|
||||
rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey);
|
||||
|
@ -893,7 +940,9 @@ bool NimBLEClient::isConnected() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Set the callbacks that will be invoked.
|
||||
* @brief Set the callbacks that will be invoked when events are received.
|
||||
* @param [in] pClientCallbacks A pointer to a class to receive the event callbacks.
|
||||
* @param [in] deleteCallbacks If true this will delete the callback class sent when the client is destructed.
|
||||
*/
|
||||
void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, bool deleteCallbacks) {
|
||||
if (pClientCallbacks != nullptr){
|
||||
|
@ -938,7 +987,7 @@ uint32_t NimBLEClientCallbacks::onPassKeyRequest(){
|
|||
NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyRequest: default: 123456");
|
||||
return 123456;
|
||||
}
|
||||
|
||||
/*
|
||||
void NimBLEClientCallbacks::onPassKeyNotify(uint32_t pass_key){
|
||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyNotify: default: %d", pass_key);
|
||||
}
|
||||
|
@ -946,7 +995,7 @@ void NimBLEClientCallbacks::onPassKeyNotify(uint32_t pass_key){
|
|||
bool NimBLEClientCallbacks::onSecurityRequest(){
|
||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onSecurityRequest: default: true");
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
void NimBLEClientCallbacks::onAuthenticationComplete(ble_gap_conn_desc* desc){
|
||||
NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default");
|
||||
}
|
||||
|
|
|
@ -38,11 +38,12 @@ class NimBLEAdvertisedDevice;
|
|||
*/
|
||||
class NimBLEClient {
|
||||
public:
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||
bool connect(const NimBLEAddress &address, uint8_t type = BLE_ADDR_PUBLIC,
|
||||
bool refreshServices = true);
|
||||
bool connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes = true);
|
||||
bool connect(const NimBLEAddress &address, bool deleteAttibutes = true);
|
||||
bool connect(bool deleteAttibutes = true);
|
||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||
NimBLEAddress getPeerAddress();
|
||||
void setPeerAddress(const NimBLEAddress &address);
|
||||
int getRssi();
|
||||
std::vector<NimBLERemoteService*>* getServices(bool refresh = false);
|
||||
std::vector<NimBLERemoteService*>::iterator begin();
|
||||
|
@ -70,7 +71,7 @@ public:
|
|||
void discoverAttributes();
|
||||
|
||||
private:
|
||||
NimBLEClient();
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
~NimBLEClient();
|
||||
|
||||
friend class NimBLEDevice;
|
||||
|
@ -83,7 +84,7 @@ private:
|
|||
void *arg);
|
||||
bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr);
|
||||
|
||||
NimBLEAddress m_peerAddress = NimBLEAddress("");
|
||||
NimBLEAddress m_peerAddress;
|
||||
uint16_t m_conn_id;
|
||||
bool m_isConnected;
|
||||
bool m_waitingToConnect;
|
||||
|
@ -107,13 +108,48 @@ private:
|
|||
class NimBLEClientCallbacks {
|
||||
public:
|
||||
virtual ~NimBLEClientCallbacks() {};
|
||||
|
||||
/**
|
||||
* @brief Called after client connects.
|
||||
* @param [in] pClient A pointer to the calling client object.
|
||||
*/
|
||||
virtual void onConnect(NimBLEClient* pClient);
|
||||
|
||||
/**
|
||||
* @brief Called when disconnected from the server.
|
||||
* @param [in] pClient A pointer to the calling client object.
|
||||
*/
|
||||
virtual void onDisconnect(NimBLEClient* pClient);
|
||||
|
||||
/**
|
||||
* @brief Called when server requests to update the connection parameters.
|
||||
* @param [in] pClient A pointer to the calling client object.
|
||||
* @param [in] params A pointer to the struct containing the connection parameters requested.
|
||||
* @return True to accept the parmeters.
|
||||
*/
|
||||
virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params);
|
||||
|
||||
/**
|
||||
* @brief Called when server requests a passkey for pairing.
|
||||
* @return The passkey to be sent to the server.
|
||||
*/
|
||||
virtual uint32_t onPassKeyRequest();
|
||||
virtual void onPassKeyNotify(uint32_t pass_key);
|
||||
virtual bool onSecurityRequest();
|
||||
|
||||
/*virtual void onPassKeyNotify(uint32_t pass_key);
|
||||
virtual bool onSecurityRequest();*/
|
||||
|
||||
/**
|
||||
* @brief Called when the pairing procedure is complete.
|
||||
* @param [in] desc A pointer to the struct containing the connection information.\n
|
||||
* This can be used to check the status of the connection encryption/pairing.
|
||||
*/
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Called when using numeric comparision for pairing.
|
||||
* @param [in] pin The pin to compare with the server.
|
||||
* @return True to accept the pin.
|
||||
*/
|
||||
virtual bool onConfirmPIN(uint32_t pin);
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,10 @@ public:
|
|||
void setValue(const std::string &value);
|
||||
std::string toString();
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the descriptor value to <type\>val.
|
||||
* @param [in] s The value to set.
|
||||
*/
|
||||
template<typename T>
|
||||
void setValue(const T &s) {
|
||||
setValue((uint8_t*)&s, sizeof(T));
|
||||
|
@ -101,6 +105,8 @@ public:
|
|||
virtual void onWrite(NimBLEDescriptor* pDescriptor);
|
||||
};
|
||||
|
||||
#include "NimBLE2904.h"
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */
|
||||
|
|
|
@ -90,6 +90,10 @@ NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
|||
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
/**
|
||||
* @brief Get the instance of the advertising object.
|
||||
* @return A pointer to the advertising object.
|
||||
*/
|
||||
NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
||||
if(m_bleAdvertising == nullptr) {
|
||||
m_bleAdvertising = new NimBLEAdvertising();
|
||||
|
@ -98,11 +102,17 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convenience function to begin advertising.
|
||||
*/
|
||||
void NimBLEDevice::startAdvertising() {
|
||||
getAdvertising()->start();
|
||||
} // startAdvertising
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convenience function to stop advertising.
|
||||
*/
|
||||
void NimBLEDevice::stopAdvertising() {
|
||||
getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
|
@ -123,19 +133,22 @@ void NimBLEDevice::stopAdvertising() {
|
|||
} // getScan
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new client object and maintains a list of all client objects
|
||||
* each client can connect to 1 peripheral device.
|
||||
* @param [in] peerAddress An optional peer address that is copied to the new client
|
||||
* object, allows for calling NimBLEClient::connect(bool) without a device or address parameter.
|
||||
* @return A reference to the new client object.
|
||||
*/
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
/* STATIC */ NimBLEClient* NimBLEDevice::createClient() {
|
||||
/* STATIC */ NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) {
|
||||
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
|
||||
NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)",
|
||||
NIMBLE_MAX_CONNECTIONS);
|
||||
}
|
||||
|
||||
NimBLEClient* pClient = new NimBLEClient();
|
||||
NimBLEClient* pClient = new NimBLEClient(peerAddress);
|
||||
m_cList.push_back(pClient);
|
||||
|
||||
return pClient;
|
||||
|
@ -143,9 +156,9 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Delete the client object and remove it from the list.
|
||||
* Check if it is connected or trying to connect and close/stop it first.
|
||||
* @param [in] Pointer to the client object.
|
||||
* @brief Delete the client object and remove it from the list.\n
|
||||
* Checks if it is connected or trying to connect and disconnects/stops it first.
|
||||
* @param [in] pClient A pointer to the client object.
|
||||
*/
|
||||
/* STATIC */ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) {
|
||||
if(pClient == nullptr) {
|
||||
|
@ -183,8 +196,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief get the list of clients.
|
||||
* @return a pointer to the list of clients.
|
||||
* @brief Get the list of created client objects.
|
||||
* @return A pointer to the list of clients.
|
||||
*/
|
||||
/* STATIC */std::list<NimBLEClient*>* NimBLEDevice::getClientList() {
|
||||
return &m_cList;
|
||||
|
@ -192,8 +205,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief get the size of the list of clients.
|
||||
* @return a pointer to the list of clients.
|
||||
* @brief Get the number of created client objects.
|
||||
* @return Number of client objects created.
|
||||
*/
|
||||
/* STATIC */size_t NimBLEDevice::getClientListSize() {
|
||||
return m_cList.size();
|
||||
|
@ -202,8 +215,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Get a reference to a client by connection ID.
|
||||
* @param [in] The client connection ID to search for.
|
||||
* @return A reference pointer to the client with the spcified connection ID.
|
||||
* @param [in] conn_id The client connection ID to search for.
|
||||
* @return A pointer to the client object with the spcified connection ID.
|
||||
*/
|
||||
/* STATIC */NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) {
|
||||
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
||||
|
@ -218,8 +231,8 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Get a reference to a client by peer address.
|
||||
* @param [in] a NimBLEAddress of the peer to search for.
|
||||
* @return A reference pointer to the client with the peer address.
|
||||
* @param [in] peer_addr The address of the peer to search for.
|
||||
* @return A pointer to the client object with the peer address.
|
||||
*/
|
||||
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) {
|
||||
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
||||
|
@ -233,7 +246,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Finds the first disconnected client in the list.
|
||||
* @return A reference pointer to the first client that is not connected to a peer.
|
||||
* @return A pointer to the first client object that is not connected to a peer.
|
||||
*/
|
||||
/* STATIC */NimBLEClient* NimBLEDevice::getDisconnectedClient() {
|
||||
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
||||
|
@ -249,16 +262,28 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Set the transmission power.
|
||||
* The power level can be one of:
|
||||
* * ESP_PWR_LVL_N12 = 0, !< Corresponding to -12dbm
|
||||
* * ESP_PWR_LVL_N9 = 1, !< Corresponding to -9dbm
|
||||
* * ESP_PWR_LVL_N6 = 2, !< Corresponding to -6dbm
|
||||
* * ESP_PWR_LVL_N3 = 3, !< Corresponding to -3dbm
|
||||
* * ESP_PWR_LVL_N0 = 4, !< Corresponding to 0dbm
|
||||
* * ESP_PWR_LVL_P3 = 5, !< Corresponding to +3dbm
|
||||
* * ESP_PWR_LVL_P6 = 6, !< Corresponding to +6dbm
|
||||
* * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm
|
||||
* @param [in] powerLevel.
|
||||
* @param [in] powerLevel The power level to set, can be one of:
|
||||
* * ESP_PWR_LVL_N12 = 0, Corresponding to -12dbm
|
||||
* * ESP_PWR_LVL_N9 = 1, Corresponding to -9dbm
|
||||
* * ESP_PWR_LVL_N6 = 2, Corresponding to -6dbm
|
||||
* * ESP_PWR_LVL_N3 = 3, Corresponding to -3dbm
|
||||
* * ESP_PWR_LVL_N0 = 4, Corresponding to 0dbm
|
||||
* * ESP_PWR_LVL_P3 = 5, Corresponding to +3dbm
|
||||
* * ESP_PWR_LVL_P6 = 6, Corresponding to +6dbm
|
||||
* * ESP_PWR_LVL_P9 = 7, Corresponding to +9dbm
|
||||
* @param [in] powerType The BLE function to set the power level for, can be one of:
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, For connection handle 0
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, For connection handle 2
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, For connection handle 3
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, For connection handle 4
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, For connection handle 5
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, For connection handle 6
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, For connection handle 7
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, For connection handle 8
|
||||
* * ESP_BLE_PWR_TYPE_ADV = 9, For advertising
|
||||
* * ESP_BLE_PWR_TYPE_SCAN = 10, For scan
|
||||
* * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType);
|
||||
|
@ -270,6 +295,24 @@ void NimBLEDevice::stopAdvertising() {
|
|||
} // setPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the transmission power.
|
||||
* @param [in] powerType The power level to set, can be one of:
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, For connection handle 0
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, For connection handle 1
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, For connection handle 2
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, For connection handle 3
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, For connection handle 4
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, For connection handle 5
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, For connection handle 6
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, For connection handle 7
|
||||
* * ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, For connection handle 8
|
||||
* * ESP_BLE_PWR_TYPE_ADV = 9, For advertising
|
||||
* * ESP_BLE_PWR_TYPE_SCAN = 10, For scan
|
||||
* * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value
|
||||
* @return the power level currently used by the type specified.
|
||||
*/
|
||||
|
||||
/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) {
|
||||
|
||||
switch(esp_ble_tx_power_get(powerType)) {
|
||||
|
@ -302,7 +345,6 @@ void NimBLEDevice::stopAdvertising() {
|
|||
*/
|
||||
/* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() {
|
||||
ble_addr_t addr = {BLE_ADDR_PUBLIC, 0};
|
||||
//ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)
|
||||
|
||||
if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Public address not found, checking random");
|
||||
|
@ -324,9 +366,9 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Setup local mtu that will be used to negotiate mtu during request from client peer
|
||||
* @param [in] mtu Value to set local mtu, should be larger than 23 and lower or equal to
|
||||
* BLE_ATT_MTU_MAX = 527
|
||||
* @brief Setup local mtu that will be used to negotiate mtu during request from client peer.
|
||||
* @param [in] mtu Value to set local mtu:
|
||||
* * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527.
|
||||
*/
|
||||
/* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu);
|
||||
|
@ -344,6 +386,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Get local MTU value set.
|
||||
* @return The current preferred MTU setting.
|
||||
*/
|
||||
/* STATIC */uint16_t NimBLEDevice::getMTU() {
|
||||
return ble_att_preferred_mtu();
|
||||
|
@ -352,6 +395,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Host reset, we pass the message so we don't make calls until resynced.
|
||||
* @param [in] reason The reason code for the reset.
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::onReset(int reason)
|
||||
{
|
||||
|
@ -389,7 +433,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Host resynced with controller, all clear to make calls.
|
||||
* @brief Host resynced with controller, all clear to make calls to the stack.
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::onSync(void)
|
||||
{
|
||||
|
@ -439,7 +483,7 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Initialize the %BLE environment.
|
||||
* @param deviceName The device name of the device.
|
||||
* @param [in] deviceName The device name of the device.
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) {
|
||||
if(!initialized){
|
||||
|
@ -497,8 +541,10 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
/**
|
||||
* @brief Shutdown the NimBLE stack/controller.
|
||||
* @param [in] clearAll If true, deletes all server/advertising/scan/client objects after deinitializing.
|
||||
* @note If clearAll is true when called, any references to the created objects become invalid.
|
||||
*/
|
||||
/* STATIC */ void NimBLEDevice::deinit() {
|
||||
/* STATIC */ void NimBLEDevice::deinit(bool clearAll) {
|
||||
int ret = nimble_port_stop();
|
||||
if (ret == 0) {
|
||||
nimble_port_deinit();
|
||||
|
@ -510,12 +556,49 @@ void NimBLEDevice::stopAdvertising() {
|
|||
|
||||
initialized = false;
|
||||
m_synced = false;
|
||||
|
||||
if(clearAll) {
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||
if(NimBLEDevice::m_pServer != nullptr) {
|
||||
delete NimBLEDevice::m_pServer;
|
||||
NimBLEDevice::m_pServer = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
if(NimBLEDevice::m_bleAdvertising != nullptr) {
|
||||
delete NimBLEDevice::m_bleAdvertising;
|
||||
NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
if(NimBLEDevice::m_pScan != nullptr) {
|
||||
delete NimBLEDevice::m_pScan;
|
||||
NimBLEDevice::m_pScan= nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
for(auto &it : m_cList) {
|
||||
deleteClient(it);
|
||||
m_cList.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
m_ignoreList.clear();
|
||||
|
||||
if(m_securityCallbacks != nullptr) {
|
||||
delete m_securityCallbacks;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // deinit
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if the initialization is complete.
|
||||
* @return true if initialized.
|
||||
*/
|
||||
bool NimBLEDevice::getInitialized() {
|
||||
return initialized;
|
||||
|
@ -524,9 +607,9 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief Set the authorization mode for this device.
|
||||
* @param bonding, if true we allow bonding, false no bonding will be performed.
|
||||
* @param mitm, if true we are capable of man in the middle protection, false if not.
|
||||
* @param sc, if true we will perform secure connection pairing, false we will use legacy pairing.
|
||||
* @param bonding If true we allow bonding, false no bonding will be performed.
|
||||
* @param mitm If true we are capable of man in the middle protection, false if not.
|
||||
* @param sc If true we will perform secure connection pairing, false we will use legacy pairing.
|
||||
*/
|
||||
/*STATIC*/ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) {
|
||||
NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc);
|
||||
|
@ -538,13 +621,12 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief Set the authorization mode for this device.
|
||||
* @param A bitmap indicating what modes are supported.
|
||||
* The bits are defined as follows:
|
||||
* @param auth_req A bitmap indicating what modes are supported.\n
|
||||
* The available bits are defined as:
|
||||
* * 0x01 BLE_SM_PAIR_AUTHREQ_BOND
|
||||
* * 0x04 BLE_SM_PAIR_AUTHREQ_MITM
|
||||
* * 0x08 BLE_SM_PAIR_AUTHREQ_SC
|
||||
* * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported.
|
||||
** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED - for reference only.
|
||||
*/
|
||||
/*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) {
|
||||
NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0,
|
||||
|
@ -555,7 +637,7 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief Set the Input/Output capabilities of this device.
|
||||
* @param One of the following:
|
||||
* @param iocap One of the following values:
|
||||
* * 0x00 BLE_HS_IO_DISPLAY_ONLY DisplayOnly IO capability
|
||||
* * 0x01 BLE_HS_IO_DISPLAY_YESNO DisplayYesNo IO capability
|
||||
* * 0x02 BLE_HS_IO_KEYBOARD_ONLY KeyboardOnly IO capability
|
||||
|
@ -569,8 +651,8 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief If we are the initiator of the security procedure this sets the keys we will distribute.
|
||||
* @param A bitmap indicating which keys to distribute during pairing.
|
||||
* The bits are defined as follows:
|
||||
* @param init_key A bitmap indicating which keys to distribute during pairing.\n
|
||||
* The available bits are defined as:
|
||||
* * 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Distribute the encryption key.
|
||||
* * 0x02: BLE_SM_PAIR_KEY_DIST_ID - Distribute the ID key (IRK).
|
||||
* * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
|
||||
|
@ -583,20 +665,21 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief Set the keys we are willing to accept during pairing.
|
||||
* @param A bitmap indicating which keys to accept during pairing.
|
||||
* The bits are defined as follows:
|
||||
* @param resp_key A bitmap indicating which keys to accept during pairing.
|
||||
* The available bits are defined as:
|
||||
* * 0x01: BLE_SM_PAIR_KEY_DIST_ENC - Accept the encryption key.
|
||||
* * 0x02: BLE_SM_PAIR_KEY_DIST_ID - Accept the ID key (IRK).
|
||||
* * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
|
||||
* * 0x08: BLE_SM_PAIR_KEY_DIST_LINK
|
||||
*/
|
||||
/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t init_key) {
|
||||
ble_hs_cfg.sm_their_key_dist = init_key;
|
||||
/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) {
|
||||
ble_hs_cfg.sm_their_key_dist = resp_key;
|
||||
} // setsSecurityRespKey
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the passkey for pairing.
|
||||
* @brief Set the passkey the server will ask for when pairing.
|
||||
* @param [in] pin The passkey to use.
|
||||
*/
|
||||
/*STATIC*/void NimBLEDevice::setSecurityPasskey(uint32_t pin) {
|
||||
m_passkey = pin;
|
||||
|
@ -604,7 +687,8 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Get the passkey for pairing.
|
||||
* @brief Get the current passkey used for pairing.
|
||||
* @return The current passkey.
|
||||
*/
|
||||
/*STATIC*/uint32_t NimBLEDevice::getSecurityPasskey() {
|
||||
return m_passkey;
|
||||
|
@ -613,7 +697,8 @@ bool NimBLEDevice::getInitialized() {
|
|||
|
||||
/**
|
||||
* @brief Set callbacks that will be used to handle encryption negotiation events and authentication events
|
||||
* @param [in] cllbacks Pointer to NimBLESecurityCallbacks class
|
||||
* @param [in] callbacks Pointer to NimBLESecurityCallbacks class
|
||||
* @deprecated For backward compatibility, New code should use client/server callback methods.
|
||||
*/
|
||||
void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
||||
NimBLEDevice::m_securityCallbacks = callbacks;
|
||||
|
@ -622,8 +707,8 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
|
||||
/**
|
||||
* @brief Start the connection securing and authorization for this connection.
|
||||
* @param Connection id of the client.
|
||||
* @returns host return code 0 if success.
|
||||
* @param conn_id The connection id of the peer device.
|
||||
* @returns NimBLE stack return code, 0 = success.
|
||||
*/
|
||||
/* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) {
|
||||
/* if(m_securityCallbacks != nullptr) {
|
||||
|
@ -641,6 +726,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
|
||||
/**
|
||||
* @brief Check if the device address is on our ignore list.
|
||||
* @param [in] address The address to look for.
|
||||
* @return True if ignoring.
|
||||
*/
|
||||
/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) {
|
||||
|
@ -656,7 +742,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
|
||||
/**
|
||||
* @brief Add a device to the ignore list.
|
||||
* @param Address of the device we want to ignore.
|
||||
* @param [in] address The address of the device we want to ignore.
|
||||
*/
|
||||
/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) {
|
||||
m_ignoreList.push_back(address);
|
||||
|
@ -665,7 +751,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
|
||||
/**
|
||||
* @brief Remove a device from the ignore list.
|
||||
* @param Address of the device we want to remove from the list.
|
||||
* @param [in] address The address of the device we want to remove from the list.
|
||||
*/
|
||||
/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) {
|
||||
for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) {
|
||||
|
@ -679,6 +765,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
|||
|
||||
/**
|
||||
* @brief Set a custom callback for gap events.
|
||||
* @param [in] handler The function to call when gap events occur.
|
||||
*/
|
||||
void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
|
||||
m_customGapHandler = handler;
|
||||
|
|
|
@ -81,17 +81,17 @@
|
|||
#define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief BLE functions.
|
||||
*/
|
||||
typedef int (*gap_event_handler)(ble_gap_event *event, void *arg);
|
||||
|
||||
extern "C" void ble_store_config_init(void);
|
||||
|
||||
/**
|
||||
* @brief A model of a %BLE Device from which all the BLE roles are created.
|
||||
*/
|
||||
class NimBLEDevice {
|
||||
public:
|
||||
static void init(const std::string &deviceName);
|
||||
static void deinit();
|
||||
static void deinit(bool clearAll = false);
|
||||
static bool getInitialized();
|
||||
static NimBLEAddress getAddress();
|
||||
static std::string toString();
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
#endif
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
static NimBLEClient* createClient();
|
||||
static NimBLEClient* createClient(NimBLEAddress peerAddress = NimBLEAddress(""));
|
||||
static bool deleteClient(NimBLEClient* pClient);
|
||||
static NimBLEClient* getClientByID(uint16_t conn_id);
|
||||
static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr);
|
||||
|
@ -181,8 +181,6 @@ private:
|
|||
static NimBLESecurityCallbacks* m_securityCallbacks;
|
||||
static uint32_t m_passkey;
|
||||
static ble_gap_event_listener m_listener;
|
||||
|
||||
public:
|
||||
static gap_event_handler m_customGapHandler;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
|
||||
static const char LOG_TAG[] = "NimBLEEddystoneTLM";
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a default EddystoneTLM beacon object.
|
||||
*/
|
||||
NimBLEEddystoneTLM::NimBLEEddystoneTLM() {
|
||||
beaconUUID = 0xFEAA;
|
||||
m_eddystoneData.frameType = EDDYSTONE_TLM_FRAME_TYPE;
|
||||
|
@ -35,34 +37,73 @@ NimBLEEddystoneTLM::NimBLEEddystoneTLM() {
|
|||
m_eddystoneData.tmil = 0;
|
||||
} // NimBLEEddystoneTLM
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the data that is being advertised.
|
||||
* @return The advertised data.
|
||||
*/
|
||||
std::string NimBLEEddystoneTLM::getData() {
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
} // getData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID being advertised.
|
||||
* @return The UUID advertised.
|
||||
*/
|
||||
NimBLEUUID NimBLEEddystoneTLM::getUUID() {
|
||||
return NimBLEUUID(beaconUUID);
|
||||
} // getUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the version being advertised.
|
||||
* @return The version number.
|
||||
*/
|
||||
uint8_t NimBLEEddystoneTLM::getVersion() {
|
||||
return m_eddystoneData.version;
|
||||
} // getVersion
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the battery voltage.
|
||||
* @return The battery voltage.
|
||||
*/
|
||||
uint16_t NimBLEEddystoneTLM::getVolt() {
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.volt);
|
||||
} // getVolt
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the temperature being advertised.
|
||||
* @return The temperature value.
|
||||
*/
|
||||
float NimBLEEddystoneTLM::getTemp() {
|
||||
return ENDIAN_CHANGE_U16(m_eddystoneData.temp) / 256.0f;
|
||||
} // getTemp
|
||||
|
||||
/**
|
||||
* @brief Get the count of advertisments sent.
|
||||
* @return The number of advertisments.
|
||||
*/
|
||||
uint32_t NimBLEEddystoneTLM::getCount() {
|
||||
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
|
||||
} // getCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the advertisment time.
|
||||
* @return The advertisment time.
|
||||
*/
|
||||
uint32_t NimBLEEddystoneTLM::getTime() {
|
||||
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
|
||||
} // getTime
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a string representation of the beacon.
|
||||
* @return The string representation.
|
||||
*/
|
||||
std::string NimBLEEddystoneTLM::toString() {
|
||||
std::string out = "";
|
||||
uint32_t rawsec = ENDIAN_CHANGE_U32(m_eddystoneData.tmil);
|
||||
|
@ -113,8 +154,10 @@ std::string NimBLEEddystoneTLM::toString() {
|
|||
return out;
|
||||
} // toString
|
||||
|
||||
|
||||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
* @brief Set the raw data for the beacon advertisment.
|
||||
* @param [in] data The raw data to advertise.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setData(const std::string &data) {
|
||||
if (data.length() != sizeof(m_eddystoneData)) {
|
||||
|
@ -125,26 +168,56 @@ void NimBLEEddystoneTLM::setData(const std::string &data) {
|
|||
memcpy(&m_eddystoneData, data.data(), data.length());
|
||||
} // setData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the UUID to advertise.
|
||||
* @param [in] l_uuid The UUID.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
} // setUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the version to advertise.
|
||||
* @param [in] version The version number.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setVersion(uint8_t version) {
|
||||
m_eddystoneData.version = version;
|
||||
} // setVersion
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the battery voltage to advertise.
|
||||
* @param [in] volt The voltage in millivolts.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setVolt(uint16_t volt) {
|
||||
m_eddystoneData.volt = volt;
|
||||
} // setVolt
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the temperature to advertise.
|
||||
* @param [in] temp The temperature value.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setTemp(float temp) {
|
||||
m_eddystoneData.temp = (uint16_t)temp;
|
||||
} // setTemp
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisment count.
|
||||
* @param [in] advCount The advertisment number.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
|
||||
m_eddystoneData.advCount = advCount;
|
||||
} // setCount
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the advertisment time.
|
||||
* @param [in] tmil The advertisment time in milliseconds.
|
||||
*/
|
||||
void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
|
||||
m_eddystoneData.tmil = tmil;
|
||||
} // setTime
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
static const char LOG_TAG[] = "NimBLEEddystoneURL";
|
||||
|
||||
|
||||
/**
|
||||
* @brief Construct a default EddystoneURL beacon object.
|
||||
*/
|
||||
NimBLEEddystoneURL::NimBLEEddystoneURL() {
|
||||
beaconUUID = 0xFEAA;
|
||||
lengthURL = 0;
|
||||
|
@ -29,22 +33,47 @@ NimBLEEddystoneURL::NimBLEEddystoneURL() {
|
|||
memset(m_eddystoneData.url, 0, sizeof(m_eddystoneData.url));
|
||||
} // BLEEddystoneURL
|
||||
|
||||
|
||||
/**
|
||||
* @brief Retrieve the data that is being advertised.
|
||||
* @return The advertised data.
|
||||
*/
|
||||
std::string NimBLEEddystoneURL::getData() {
|
||||
return std::string((char*) &m_eddystoneData, sizeof(m_eddystoneData));
|
||||
} // getData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the UUID being advertised.
|
||||
* @return The UUID advertised.
|
||||
*/
|
||||
NimBLEUUID NimBLEEddystoneURL::getUUID() {
|
||||
return NimBLEUUID(beaconUUID);
|
||||
} // getUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the transmit power being advertised.
|
||||
* @return The transmit power.
|
||||
*/
|
||||
int8_t NimBLEEddystoneURL::getPower() {
|
||||
return m_eddystoneData.advertisedTxPower;
|
||||
} // getPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the raw URL being advertised.
|
||||
* @return The raw URL.
|
||||
*/
|
||||
std::string NimBLEEddystoneURL::getURL() {
|
||||
return std::string((char*) &m_eddystoneData.url, sizeof(m_eddystoneData.url));
|
||||
} // getURL
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the full URL being advertised.
|
||||
* @return The full URL.
|
||||
*/
|
||||
std::string NimBLEEddystoneURL::getDecodedURL() {
|
||||
std::string decodedURL = "";
|
||||
|
||||
|
@ -123,7 +152,8 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
|
|||
|
||||
|
||||
/**
|
||||
* Set the raw data for the beacon record.
|
||||
* @brief Set the raw data for the beacon advertisment.
|
||||
* @param [in] data The raw data to advertise.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setData(const std::string &data) {
|
||||
if (data.length() > sizeof(m_eddystoneData)) {
|
||||
|
@ -136,14 +166,29 @@ void NimBLEEddystoneURL::setData(const std::string &data) {
|
|||
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
|
||||
} // setData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the UUID to advertise.
|
||||
* @param [in] l_uuid The UUID.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) {
|
||||
beaconUUID = l_uuid.getNative()->u16.value;
|
||||
} // setUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the transmit power to advertise.
|
||||
* @param [in] advertisedTxPower The transmit power level.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) {
|
||||
m_eddystoneData.advertisedTxPower = advertisedTxPower;
|
||||
} // setPower
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the URL to advertise.
|
||||
* @param [in] url The URL.
|
||||
*/
|
||||
void NimBLEEddystoneURL::setURL(const std::string &url) {
|
||||
if (url.length() > sizeof(m_eddystoneData.url)) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
|
||||
|
|
|
@ -260,13 +260,12 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
|
|||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the vector of found descriptors.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all descriptors for this characteristic retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored descriptors,
|
||||
* if the vector is empty it will retrieve all descriptors for this characteristic
|
||||
* from the peripheral.
|
||||
* @return a pointer to the vector of descriptors for this characteristic.
|
||||
* @brief Get a pointer to the vector of found descriptors.
|
||||
* @param [in] refresh If true the current descriptor vector will be cleared and\n
|
||||
* all descriptors for this characteristic retrieved from the peripheral.\n
|
||||
* If false the vector will be returned with the currently stored descriptors
|
||||
* of this characteristic.
|
||||
* @return A pointer to the vector of descriptors for this characteristic.
|
||||
*/
|
||||
std::vector<NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors(bool refresh) {
|
||||
if(refresh) {
|
||||
|
@ -338,6 +337,7 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() {
|
|||
|
||||
/**
|
||||
* @brief Get the value of the remote characteristic.
|
||||
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
|
||||
* @return The value of the remote characteristic.
|
||||
*/
|
||||
std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
|
||||
|
@ -355,6 +355,7 @@ std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
|
|||
/**
|
||||
* @brief Read an unsigned 16 bit value
|
||||
* @return The unsigned 16 bit value.
|
||||
* @deprecated Use readValue<uint16_t>().
|
||||
*/
|
||||
uint16_t NimBLERemoteCharacteristic::readUInt16() {
|
||||
return readValue<uint16_t>();
|
||||
|
@ -364,6 +365,7 @@ uint16_t NimBLERemoteCharacteristic::readUInt16() {
|
|||
/**
|
||||
* @brief Read an unsigned 32 bit value.
|
||||
* @return the unsigned 32 bit value.
|
||||
* @deprecated Use readValue<uint32_t>().
|
||||
*/
|
||||
uint32_t NimBLERemoteCharacteristic::readUInt32() {
|
||||
return readValue<uint32_t>();
|
||||
|
@ -373,6 +375,7 @@ uint32_t NimBLERemoteCharacteristic::readUInt32() {
|
|||
/**
|
||||
* @brief Read a byte value
|
||||
* @return The value as a byte
|
||||
* @deprecated Use readValue<uint8_t>().
|
||||
*/
|
||||
uint8_t NimBLERemoteCharacteristic::readUInt8() {
|
||||
return readValue<uint8_t>();
|
||||
|
@ -390,6 +393,7 @@ float NimBLERemoteCharacteristic::readFloat() {
|
|||
|
||||
/**
|
||||
* @brief Read the value of the remote characteristic.
|
||||
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
|
||||
* @return The value of the remote characteristic.
|
||||
*/
|
||||
std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
|
||||
|
@ -458,7 +462,7 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
|
|||
|
||||
/**
|
||||
* @brief Callback for characteristic read operation.
|
||||
* @return 0 or error code.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
|
@ -498,12 +502,13 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
|
|||
|
||||
/**
|
||||
* @brief Subscribe or unsubscribe for notifications or indications.
|
||||
* @param [in] uint16_t val 0x00 to unsubscribe, 0x01 for notifications, 0x02 for indications.
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then no callback
|
||||
* is performed for notifications.
|
||||
* @param [in] val 0x00 to unsubscribe, 0x01 for notifications, 0x02 for indications.
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification.
|
||||
* @param [in] response If write response required set this to true.
|
||||
* If NULL is provided then no callback is performed.
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::setNotify(uint16_t val, bool response, notify_callback notifyCallback) {
|
||||
bool NimBLERemoteCharacteristic::setNotify(uint16_t val, notify_callback notifyCallback, bool response) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> setNotify(): %s, %02x", toString().c_str(), val);
|
||||
|
||||
NimBLERemoteDescriptor* desc = getDescriptor(NimBLEUUID((uint16_t)0x2902));
|
||||
|
@ -522,43 +527,44 @@ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, bool response, notify_c
|
|||
|
||||
/**
|
||||
* @brief Subscribe for notifications or indications.
|
||||
* @param [in] bool if true, subscribe for notifications, false subscribe for indications.
|
||||
* @param [in] bool if true, require a write response from the descriptor write operation.
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then no callback
|
||||
* is performed for notifications.
|
||||
* @param [in] notifications If true, subscribe for notifications, false subscribe for indications.
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification.
|
||||
* @param [in] response If true, require a write response from the descriptor write operation.
|
||||
* If NULL is provided then no callback is performed.
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::subscribe(bool notifications, bool response, notify_callback notifyCallback) {
|
||||
bool NimBLERemoteCharacteristic::subscribe(bool notifications, notify_callback notifyCallback, bool response) {
|
||||
if(notifications) {
|
||||
return setNotify(0x01, response, notifyCallback);
|
||||
return setNotify(0x01, notifyCallback, response);
|
||||
} else {
|
||||
return setNotify(0x02, response, notifyCallback);
|
||||
return setNotify(0x02, notifyCallback, response);
|
||||
}
|
||||
} // subscribe
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unsubscribe for notifications or indications.
|
||||
* @param [in] bool if true, require a write response from the descriptor write operation.
|
||||
* @param [in] response bool if true, require a write response from the descriptor write operation.
|
||||
* @return true if successful.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::unsubscribe(bool response) {
|
||||
return setNotify(0x00, response);
|
||||
return setNotify(0x00, nullptr, response);
|
||||
} // unsubscribe
|
||||
|
||||
|
||||
/**
|
||||
* @brief backward-compatibility method for subscribe/unsubscribe notifications/indications
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then we are
|
||||
* unregistering for notifications.
|
||||
* @param [in] bool if true, register for notifications, false register for indications.
|
||||
* @param [in] bool if true, require a write response from the descriptor write operation.
|
||||
* @param [in] notifyCallback A callback to be invoked for a notification. If NULL is provided then we
|
||||
* will unregister for notifications.
|
||||
* @param [in] notifications If true, register for notifications, false register for indications.
|
||||
* @param [in] response If true, require a write response from the descriptor write operation.
|
||||
* @return true if successful.
|
||||
* @deprecated Use subscribe() / unsubscribe() instead.
|
||||
*/
|
||||
bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback, bool notifications, bool response) {
|
||||
bool success;
|
||||
if(notifyCallback != nullptr) {
|
||||
success = subscribe(notifications, response, notifyCallback);
|
||||
success = subscribe(notifications, notifyCallback, response);
|
||||
} else {
|
||||
success = unsubscribe(response);
|
||||
}
|
||||
|
@ -568,10 +574,9 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
|
|||
|
||||
/**
|
||||
* @brief Delete the descriptors in the descriptor vector.
|
||||
* We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors
|
||||
* @details We maintain a vector called m_descriptorVector that contains pointers to NimBLERemoteDescriptors
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleting
|
||||
* them. This method does just that.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLERemoteCharacteristic::deleteDescriptors() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptors");
|
||||
|
@ -587,7 +592,7 @@ void NimBLERemoteCharacteristic::deleteDescriptors() {
|
|||
/**
|
||||
* @brief Delete descriptor by UUID
|
||||
* @param [in] uuid The UUID of the descriptor to be deleted.
|
||||
* @return Number of services left.
|
||||
* @return Number of descriptors left in the vector.
|
||||
*/
|
||||
size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptor");
|
||||
|
@ -607,7 +612,7 @@ size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Convert a BLERemoteCharacteristic to a string representation;
|
||||
* @brief Convert a NimBLERemoteCharacteristic to a string representation;
|
||||
* @return a String representation.
|
||||
*/
|
||||
std::string NimBLERemoteCharacteristic::toString() {
|
||||
|
@ -725,7 +730,7 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
|
|||
|
||||
/**
|
||||
* @brief Callback for characteristic write operation.
|
||||
* @return 0 or error code.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
|
|
|
@ -24,13 +24,14 @@
|
|||
#include "NimBLERemoteDescriptor.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class NimBLERemoteService;
|
||||
class NimBLERemoteDescriptor;
|
||||
|
||||
|
||||
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||
uint8_t* pData, size_t length, bool isNotify);
|
||||
typedef std::function<void (NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||
uint8_t* pData, size_t length, bool isNotify)> notify_callback;
|
||||
|
||||
typedef struct {
|
||||
const NimBLEUUID *uuid;
|
||||
|
@ -63,6 +64,15 @@ public:
|
|||
NimBLEUUID getUUID();
|
||||
std::string readValue(time_t *timestamp = nullptr);
|
||||
|
||||
/**
|
||||
* @brief A template to convert the remote characteristic data to <type\>.
|
||||
* @tparam T The type to convert the data to.
|
||||
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
|
||||
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <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>readValue<type>(×tamp, skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T readValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
|
||||
std::string value = readValue(timestamp);
|
||||
|
@ -77,6 +87,15 @@ public:
|
|||
float readFloat() __attribute__ ((deprecated("Use template readValue<float>()")));
|
||||
std::string getValue(time_t *timestamp = nullptr);
|
||||
|
||||
/**
|
||||
* @brief A template to convert the remote characteristic data to <type\>.
|
||||
* @tparam T The type to convert the data to.
|
||||
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
|
||||
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <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>getValue<type>(×tamp, skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
|
||||
std::string value = getValue(timestamp);
|
||||
|
@ -86,9 +105,9 @@ public:
|
|||
}
|
||||
|
||||
bool subscribe(bool notifications = true,
|
||||
bool response = true,
|
||||
notify_callback notifyCallback = nullptr);
|
||||
bool unsubscribe(bool response = true);
|
||||
notify_callback notifyCallback = nullptr,
|
||||
bool response = false);
|
||||
bool unsubscribe(bool response = false);
|
||||
bool registerForNotify(notify_callback notifyCallback,
|
||||
bool notifications = true,
|
||||
bool response = true)
|
||||
|
@ -98,6 +117,11 @@ public:
|
|||
bool response = false);
|
||||
bool writeValue(const std::string &newValue,
|
||||
bool response = false);
|
||||
/**
|
||||
* @brief Convenience template to set the remote characteristic value to <type\>val.
|
||||
* @param [in] s The value to write.
|
||||
* @param [in] response True == request write response.
|
||||
*/
|
||||
template<typename T>
|
||||
bool writeValue(const T &s, bool response = false) {
|
||||
return writeValue((uint8_t*)&s, sizeof(T), response);
|
||||
|
@ -115,7 +139,7 @@ private:
|
|||
friend class NimBLERemoteDescriptor;
|
||||
|
||||
// Private member functions
|
||||
bool setNotify(uint16_t val, bool response = true, notify_callback notifyCallback = nullptr);
|
||||
bool setNotify(uint16_t val, notify_callback notifyCallback = nullptr, bool response = true);
|
||||
bool retrieveDescriptors(const NimBLEUUID *uuid_filter = nullptr);
|
||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr, void *arg);
|
||||
|
|
|
@ -25,8 +25,8 @@ static const char* LOG_TAG = "NimBLERemoteDescriptor";
|
|||
|
||||
/**
|
||||
* @brief Remote descriptor constructor.
|
||||
* @param [in] Reference to the Characteristic that this belongs to.
|
||||
* @param [in] Reference to the struct that contains the descriptor information.
|
||||
* @param [in] pRemoteCharacteristic A pointer to the Characteristic that this belongs to.
|
||||
* @param [in] dsc A pointer to the struct that contains the descriptor information.
|
||||
*/
|
||||
NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic,
|
||||
const struct ble_gatt_dsc *dsc)
|
||||
|
@ -78,6 +78,11 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() {
|
|||
} // getUUID
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a byte value
|
||||
* @return The value as a byte
|
||||
* @deprecated Use readValue<uint8_t>().
|
||||
*/
|
||||
uint8_t NimBLERemoteDescriptor::readUInt8() {
|
||||
std::string value = readValue();
|
||||
if (value.length() >= 1) {
|
||||
|
@ -87,6 +92,11 @@ uint8_t NimBLERemoteDescriptor::readUInt8() {
|
|||
} // readUInt8
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read an unsigned 16 bit value
|
||||
* @return The unsigned 16 bit value.
|
||||
* @deprecated Use readValue<uint16_t>().
|
||||
*/
|
||||
uint16_t NimBLERemoteDescriptor::readUInt16() {
|
||||
std::string value = readValue();
|
||||
if (value.length() >= 2) {
|
||||
|
@ -96,6 +106,11 @@ uint16_t NimBLERemoteDescriptor::readUInt16() {
|
|||
} // readUInt16
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read an unsigned 32 bit value.
|
||||
* @return the unsigned 32 bit value.
|
||||
* @deprecated Use readValue<uint32_t>().
|
||||
*/
|
||||
uint32_t NimBLERemoteDescriptor::readUInt32() {
|
||||
std::string value = readValue();
|
||||
if (value.length() >= 4) {
|
||||
|
@ -105,6 +120,10 @@ uint32_t NimBLERemoteDescriptor::readUInt32() {
|
|||
} // readUInt32
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the value of the remote descriptor.
|
||||
* @return The value of the remote descriptor.
|
||||
*/
|
||||
std::string NimBLERemoteDescriptor::readValue() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
||||
|
||||
|
@ -161,7 +180,7 @@ std::string NimBLERemoteDescriptor::readValue() {
|
|||
|
||||
/**
|
||||
* @brief Callback for Descriptor read operation.
|
||||
* @return 0 or error code.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
|
@ -200,8 +219,8 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
|||
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of this BLE Remote Descriptor.
|
||||
* @retun A string representation of this BLE Remote Descriptor.
|
||||
* @brief Return a string representation of this Remote Descriptor.
|
||||
* @return A string representation of this Remote Descriptor.
|
||||
*/
|
||||
std::string NimBLERemoteDescriptor::toString() {
|
||||
std::string res = "Descriptor: uuid: " + getUUID().toString();
|
||||
|
@ -216,7 +235,7 @@ std::string NimBLERemoteDescriptor::toString() {
|
|||
|
||||
/**
|
||||
* @brief Callback for descriptor write operation.
|
||||
* @return 0 or error code.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
|
@ -242,7 +261,8 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
|||
* @brief Write data to the BLE Remote Descriptor.
|
||||
* @param [in] data The data to send to the remote descriptor.
|
||||
* @param [in] length The length of the data to send.
|
||||
* @param [in] response True if we expect a response.
|
||||
* @param [in] response True if we expect a write response.
|
||||
* @return True if successful
|
||||
*/
|
||||
bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) {
|
||||
|
||||
|
@ -322,11 +342,11 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
|
|||
* @brief Write data represented as a string to the BLE Remote Descriptor.
|
||||
* @param [in] newValue The data to send to the remote descriptor.
|
||||
* @param [in] response True if we expect a response.
|
||||
* @return True if successful
|
||||
*/
|
||||
bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) {
|
||||
return writeValue((uint8_t*) newValue.data(), newValue.length(), response);
|
||||
} // writeValue
|
||||
|
||||
|
||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
|
|
@ -33,6 +33,14 @@ public:
|
|||
NimBLEUUID getUUID();
|
||||
std::string readValue();
|
||||
|
||||
/**
|
||||
* @brief A template to convert the remote descriptor 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>readValue<type>(skipSizeCheck);</tt>
|
||||
*/
|
||||
template<typename T>
|
||||
T readValue(bool skipSizeCheck = false) {
|
||||
std::string value = readValue();
|
||||
|
@ -41,12 +49,18 @@ public:
|
|||
return *((T *)pData);
|
||||
}
|
||||
|
||||
uint8_t readUInt8() __attribute__ ((deprecated));
|
||||
uint16_t readUInt16() __attribute__ ((deprecated));
|
||||
uint32_t readUInt32() __attribute__ ((deprecated));
|
||||
uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue<uint8_t>()")));
|
||||
uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue<uint16_t>()")));
|
||||
uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue<uint32_t>()")));
|
||||
std::string toString(void);
|
||||
bool writeValue(const uint8_t* data, size_t length, bool response = false);
|
||||
bool writeValue(const std::string &newValue, bool response = false);
|
||||
|
||||
/**
|
||||
* @brief Convenience template to set the remote descriptor value to <type\>val.
|
||||
* @param [in] s The value to write.
|
||||
* @param [in] response True == request write response.
|
||||
*/
|
||||
template<typename T>
|
||||
bool writeValue(const T &s, bool response = false) {
|
||||
return writeValue((uint8_t*)&s, sizeof(T), response);
|
||||
|
|
|
@ -26,8 +26,8 @@ static const char* LOG_TAG = "NimBLERemoteService";
|
|||
|
||||
/**
|
||||
* @brief Remote Service constructor.
|
||||
* @param [in] Reference to the client this belongs to.
|
||||
* @param [in] Refernce to the structure with the services' information.
|
||||
* @param [in] pClient A pointer to the client this belongs to.
|
||||
* @param [in] service A pointer to the structure with the service information.
|
||||
*/
|
||||
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) {
|
||||
|
||||
|
@ -55,7 +55,6 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble
|
|||
|
||||
/**
|
||||
* @brief When deleting the service make sure we delete all characteristics and descriptors.
|
||||
* Also release any semaphores they may be holding.
|
||||
*/
|
||||
NimBLERemoteService::~NimBLERemoteService() {
|
||||
deleteCharacteristics();
|
||||
|
@ -83,7 +82,7 @@ std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::end() {
|
|||
/**
|
||||
* @brief Get the remote characteristic object for the characteristic UUID.
|
||||
* @param [in] uuid Remote characteristic uuid.
|
||||
* @return Reference to the remote characteristic object.
|
||||
* @return A pointer to the remote characteristic object.
|
||||
*/
|
||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) {
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
|
@ -93,7 +92,7 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
|
|||
/**
|
||||
* @brief Get the characteristic object for the UUID.
|
||||
* @param [in] uuid Characteristic uuid.
|
||||
* @return Reference to the characteristic object, or nullptr if not found.
|
||||
* @return A pointer to the characteristic object, or nullptr if not found.
|
||||
*/
|
||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
for(auto &it: m_characteristicVector) {
|
||||
|
@ -114,15 +113,12 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
|
|||
|
||||
|
||||
/**
|
||||
* @Get a pointer to the vector of found characteristics.
|
||||
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||
* subsequently all characteristics for this service retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored characteristics,
|
||||
* If true it will retrieve all characteristics of this service from the peripheral
|
||||
* and return the vector with all characteristics for this service.
|
||||
* @return a pointer to the vector of descriptors for this characteristic.
|
||||
* @brief Get a pointer to the vector of found characteristics.
|
||||
* @param [in] refresh If true the current characteristics vector will cleared and
|
||||
* all characteristics for this service retrieved from the peripheral.
|
||||
* If false the vector will be returned with the currently stored characteristics of this service.
|
||||
* @return A pointer to the vector of descriptors for this characteristic.
|
||||
*/
|
||||
|
||||
std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics(bool refresh) {
|
||||
if(refresh) {
|
||||
deleteCharacteristics();
|
||||
|
@ -140,6 +136,7 @@ std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristic
|
|||
|
||||
/**
|
||||
* @brief Callback for Characterisic discovery.
|
||||
* @return success == 0 or error code.
|
||||
*/
|
||||
int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
|
@ -182,7 +179,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
|||
/**
|
||||
* @brief Retrieve all the characteristics for this service.
|
||||
* This function will not return until we have all the characteristics.
|
||||
* @return N/A
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter) {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
|
||||
|
@ -299,10 +296,9 @@ bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const s
|
|||
|
||||
/**
|
||||
* @brief Delete the characteristics in the characteristics vector.
|
||||
* We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic
|
||||
* @details We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic
|
||||
* object references. Since we allocated these in this class, we are also responsible for deleting
|
||||
* them. This method does just that.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLERemoteService::deleteCharacteristics() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> deleteCharacteristics");
|
||||
|
@ -316,7 +312,7 @@ void NimBLERemoteService::deleteCharacteristics() {
|
|||
|
||||
/**
|
||||
* @brief Delete characteristic by UUID
|
||||
* @param [in] uuid The UUID of the characteristic to be cleared.
|
||||
* @param [in] uuid The UUID of the characteristic to be removed from the local database.
|
||||
* @return Number of characteristics left.
|
||||
*/
|
||||
size_t NimBLERemoteService::deleteCharacteristic(const NimBLEUUID &uuid) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
void deleteCharacteristics();
|
||||
size_t deleteCharacteristic(const NimBLEUUID &uuid);
|
||||
NimBLEClient* getClient(void);
|
||||
uint16_t getHandle();
|
||||
//uint16_t getHandle();
|
||||
NimBLEUUID getUUID(void);
|
||||
std::string getValue(const NimBLEUUID &characteristicUuid);
|
||||
bool setValue(const NimBLEUUID &characteristicUuid,
|
||||
|
|
|
@ -44,6 +44,13 @@ NimBLEScan::NimBLEScan() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Scan destructor, release any allocated resources.
|
||||
*/
|
||||
NimBLEScan::~NimBLEScan() {
|
||||
clearResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle GAP events related to scans.
|
||||
* @param [in] event The event type for this event.
|
||||
|
@ -52,8 +59,6 @@ NimBLEScan::NimBLEScan() {
|
|||
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
|
||||
NimBLEScan* pScan = (NimBLEScan*)arg;
|
||||
struct ble_hs_adv_fields fields;
|
||||
int rc = 0;
|
||||
|
||||
switch(event->type) {
|
||||
|
||||
|
@ -63,13 +68,6 @@ NimBLEScan::NimBLEScan() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
rc = ble_hs_adv_parse_fields(&fields, event->disc.data,
|
||||
event->disc.length_data);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "Gap Event Parse ERROR.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLEAddress advertisedAddress(event->disc.addr);
|
||||
|
||||
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
||||
|
@ -92,7 +90,6 @@ NimBLEScan::NimBLEScan() {
|
|||
// Otherwise just update the relevant parameters of the already known device.
|
||||
if(advertisedDevice == nullptr){
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
advertisedDevice->setAddressType(event->disc.addr.type);
|
||||
advertisedDevice->setAddress(advertisedAddress);
|
||||
advertisedDevice->setAdvType(event->disc.event_type);
|
||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||
|
@ -102,9 +99,9 @@ NimBLEScan::NimBLEScan() {
|
|||
NIMBLE_LOGI(LOG_TAG, "UPDATING PREVIOUSLY FOUND DEVICE: %s", advertisedAddress.toString().c_str());
|
||||
}
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->parseAdvertisement(&fields);
|
||||
advertisedDevice->setScan(pScan);
|
||||
advertisedDevice->setAdvertisementResult(event->disc.data, event->disc.length_data);
|
||||
if(event->disc.length_data > 0) {
|
||||
advertisedDevice->parseAdvertisement(event->disc.data, event->disc.length_data);
|
||||
}
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
|
@ -151,7 +148,6 @@ NimBLEScan::NimBLEScan() {
|
|||
* @brief Should we perform an active or passive scan?
|
||||
* The default is a passive scan. An active scan means that we will wish a scan response.
|
||||
* @param [in] active If true, we perform an active scan otherwise a passive scan.
|
||||
* @return N/A.
|
||||
*/
|
||||
void NimBLEScan::setActiveScan(bool active) {
|
||||
if (active) {
|
||||
|
@ -165,40 +161,40 @@ void NimBLEScan::setActiveScan(bool active) {
|
|||
/**
|
||||
* @brief Set whether or not the BLE controller should only report results
|
||||
* from devices it has not already seen.
|
||||
* @param [in] active If true, scanned devices will only be reported once.
|
||||
* @param [in] enabled If true, scanned devices will only be reported once.
|
||||
* @details The controller has a limited buffer and will start reporting
|
||||
* dupicate devices once the limit is reached.
|
||||
*/
|
||||
void NimBLEScan::setDuplicateFilter(bool active) {
|
||||
m_scan_params.filter_duplicates = active;
|
||||
void NimBLEScan::setDuplicateFilter(bool enabled) {
|
||||
m_scan_params.filter_duplicates = enabled;
|
||||
} // setDuplicateFilter
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set whether or not the BLE controller only report scan results
|
||||
* from devices advertising in limited discovery mode, i.e. directed advertising.
|
||||
* @param [in] active If true, only limited discovery devices will be in scan results.
|
||||
* @param [in] enabled If true, only limited discovery devices will be in scan results.
|
||||
*/
|
||||
void NimBLEScan::setLimitedOnly(bool active) {
|
||||
m_scan_params.limited = active;
|
||||
void NimBLEScan::setLimitedOnly(bool enabled) {
|
||||
m_scan_params.limited = enabled;
|
||||
} // setLimited
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the scan filter policy.
|
||||
* @param [in] filter Can be one of:
|
||||
* BLE_HCI_SCAN_FILT_NO_WL (0)
|
||||
* Scanner processes all advertising packets (white list not used) except
|
||||
* * BLE_HCI_SCAN_FILT_NO_WL (0)
|
||||
* Scanner processes all advertising packets (white list not used) except\n
|
||||
* directed, connectable advertising packets not sent to the scanner.
|
||||
* BLE_HCI_SCAN_FILT_USE_WL (1)
|
||||
* Scanner processes advertisements from white list only. A connectable,
|
||||
* * BLE_HCI_SCAN_FILT_USE_WL (1)
|
||||
* Scanner processes advertisements from white list only. A connectable,\n
|
||||
* directed advertisment is ignored unless it contains scanners address.
|
||||
* BLE_HCI_SCAN_FILT_NO_WL_INITA (2)
|
||||
* Scanner process all advertising packets (white list not used). A
|
||||
* * BLE_HCI_SCAN_FILT_NO_WL_INITA (2)
|
||||
* Scanner process all advertising packets (white list not used). A\n
|
||||
* connectable, directed advertisement shall not be ignored if the InitA
|
||||
* is a resolvable private address.
|
||||
* BLE_HCI_SCAN_FILT_USE_WL_INITA (3)
|
||||
* Scanner process advertisements from white list only. A connectable,
|
||||
* * BLE_HCI_SCAN_FILT_USE_WL_INITA (3)
|
||||
* Scanner process advertisements from white list only. A connectable,\n
|
||||
* directed advertisement shall not be ignored if the InitA is a
|
||||
* resolvable private address.
|
||||
*/
|
||||
|
@ -221,7 +217,7 @@ void NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* p
|
|||
|
||||
/**
|
||||
* @brief Set the interval to scan.
|
||||
* @param [in] The interval in msecs.
|
||||
* @param [in] intervalMSecs The scan interval (how often) in milliseconds.
|
||||
*/
|
||||
void NimBLEScan::setInterval(uint16_t intervalMSecs) {
|
||||
m_scan_params.itvl = intervalMSecs / 0.625;
|
||||
|
@ -237,11 +233,20 @@ void NimBLEScan::setWindow(uint16_t windowMSecs) {
|
|||
} // setWindow
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the status of the scanner.
|
||||
* @return true if scanning or scan starting.
|
||||
*/
|
||||
bool NimBLEScan::isScanning() {
|
||||
return !m_stopped;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start scanning.
|
||||
* @param [in] duration The duration in seconds for which to scan.
|
||||
* @param [in] scanCompleteCB A function to be called when scanning has completed.
|
||||
* @param [in] are we continue scan (true) or we want to clear stored devices (false)
|
||||
* @param [in] is_continue Set to true to save previous scan results, false to clear them.
|
||||
* @return True if scan started or false if there was an error.
|
||||
*/
|
||||
bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) {
|
||||
|
@ -309,7 +314,8 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
|||
/**
|
||||
* @brief Start scanning and block until scanning has been completed.
|
||||
* @param [in] duration The duration in seconds for which to scan.
|
||||
* @return The BLEScanResults.
|
||||
* @param [in] is_continue Set to true to save previous scan results, false to clear them.
|
||||
* @return The NimBLEScanResults.
|
||||
*/
|
||||
NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
|
||||
if(duration == 0) {
|
||||
|
@ -330,7 +336,7 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
|
|||
|
||||
/**
|
||||
* @brief Stop an in progress scan.
|
||||
* @return N/A.
|
||||
* @return True if successful.
|
||||
*/
|
||||
bool NimBLEScan::stop() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop()");
|
||||
|
@ -343,7 +349,7 @@ bool NimBLEScan::stop() {
|
|||
|
||||
m_stopped = true;
|
||||
|
||||
if (m_scanCompleteCB != nullptr) {
|
||||
if (rc != BLE_HS_EALREADY && m_scanCompleteCB != nullptr) {
|
||||
m_scanCompleteCB(m_scanResults);
|
||||
}
|
||||
|
||||
|
@ -356,7 +362,11 @@ bool NimBLEScan::stop() {
|
|||
} // stop
|
||||
|
||||
|
||||
// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address
|
||||
/**
|
||||
* @brief Delete peer device from the scan results vector.
|
||||
* @param [in] address The address of the device to delete from the results.
|
||||
* @details After disconnecting, it may be required in the case we were connected to a device without a public address.
|
||||
*/
|
||||
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||
|
||||
|
@ -371,8 +381,7 @@ void NimBLEScan::erase(const NimBLEAddress &address) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief If the host reset the scan will have stopped so we should flag it and release the semaphore.
|
||||
* @return N/A.
|
||||
* @brief If the host reset the scan will have stopped so we should set the flag as stopped.
|
||||
*/
|
||||
void NimBLEScan::onHostReset() {
|
||||
m_stopped = true;
|
||||
|
@ -411,7 +420,7 @@ void NimBLEScanResults::dump() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Return the count of devices found in the last scan.
|
||||
* @brief Get the count of devices found in the last scan.
|
||||
* @return The number of devices found in the last scan.
|
||||
*/
|
||||
int NimBLEScanResults::getCount() {
|
||||
|
@ -449,7 +458,7 @@ std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::end() {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to the specified device at the given address.
|
||||
* @brief Get a pointer to the specified device at the given address.
|
||||
* If the address is not found a nullptr is returned.
|
||||
* @param [in] address The address of the device.
|
||||
* @return A pointer to the device at the specified address.
|
||||
|
|
|
@ -33,9 +33,9 @@ class NimBLEAdvertisedDeviceCallbacks;
|
|||
class NimBLEAddress;
|
||||
|
||||
/**
|
||||
* @brief The result of having performed a scan.
|
||||
* When a scan completes, we have a set of found devices. Each device is described
|
||||
* by a BLEAdvertisedDevice object. The number of items in the set is given by
|
||||
* @brief A class that contains and operates on the results of a BLE scan.
|
||||
* @details When a scan completes, we have a set of found devices. Each device is described
|
||||
* by a NimBLEAdvertisedDevice object. The number of items in the set is given by
|
||||
* getCount(). We can retrieve a device by calling getDevice() passing in the
|
||||
* index (starting at 0) of the desired device.
|
||||
*/
|
||||
|
@ -62,12 +62,13 @@ class NimBLEScan {
|
|||
public:
|
||||
bool start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue = false);
|
||||
NimBLEScanResults start(uint32_t duration, bool is_continue = false);
|
||||
bool isScanning();
|
||||
void setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates = false);
|
||||
void setActiveScan(bool active);
|
||||
void setInterval(uint16_t intervalMSecs);
|
||||
void setWindow(uint16_t windowMSecs);
|
||||
void setDuplicateFilter(bool active);
|
||||
void setLimitedOnly(bool active);
|
||||
void setDuplicateFilter(bool enabled);
|
||||
void setLimitedOnly(bool enabled);
|
||||
void setFilterPolicy(uint8_t filter);
|
||||
bool stop();
|
||||
void clearResults();
|
||||
|
@ -76,8 +77,10 @@ public:
|
|||
|
||||
|
||||
private:
|
||||
NimBLEScan();
|
||||
friend class NimBLEDevice;
|
||||
|
||||
NimBLEScan();
|
||||
~NimBLEScan();
|
||||
static int handleGapEvent(ble_gap_event* event, void* arg);
|
||||
void onHostReset();
|
||||
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEDevice.h"
|
||||
|
||||
/**
|
||||
* @brief This class is for backward compatibility with the bluedroid based library.
|
||||
* Use the new security functions in NimBLEDevice instead.
|
||||
* New callback functions in NimBLEServer and NimBLEClient.
|
||||
*/
|
||||
|
||||
NimBLESecurity::NimBLESecurity() {
|
||||
}
|
||||
|
||||
|
@ -33,6 +27,15 @@ NimBLESecurity::~NimBLESecurity() {
|
|||
|
||||
/**
|
||||
* @brief Set requested authentication mode
|
||||
* @param [in] auth_req A bitmask containing one or more of:
|
||||
* * ESP_LE_AUTH_NO_BOND 0x00
|
||||
* * ESP_LE_AUTH_BOND 0x01
|
||||
* * ESP_LE_AUTH_REQ_MITM (1 << 2)
|
||||
* * ESP_LE_AUTH_REQ_BOND_MITM (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM)
|
||||
* * ESP_LE_AUTH_REQ_SC_ONLY (1 << 3)
|
||||
* * ESP_LE_AUTH_REQ_SC_BOND (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY)
|
||||
* * ESP_LE_AUTH_REQ_SC_MITM (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY)
|
||||
* * ESP_LE_AUTH_REQ_SC_MITM_BOND (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY | ESP_LE_AUTH_BOND)
|
||||
*/
|
||||
void NimBLESecurity::setAuthenticationMode(esp_ble_auth_req_t auth_req) {
|
||||
NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0,
|
||||
|
@ -43,7 +46,14 @@ void NimBLESecurity::setAuthenticationMode(esp_ble_auth_req_t auth_req) {
|
|||
|
||||
/**
|
||||
* @brief Set our device IO capability to let end user perform authorization
|
||||
* either by displaying or entering generated 6-digits pin code
|
||||
* either by displaying or entering generated 6-digit pin code or use \"just works\".
|
||||
* @param [in] iocap The IO capabilites our device has.\n
|
||||
* Can be set to one of:
|
||||
* * ESP_IO_CAP_OUT 0
|
||||
* * ESP_IO_CAP_IO 1
|
||||
* * ESP_IO_CAP_IN 2
|
||||
* * ESP_IO_CAP_NONE 3
|
||||
* * ESP_IO_CAP_KBDISP 4
|
||||
*/
|
||||
void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) {
|
||||
NimBLEDevice::setSecurityIOCap(iocap);
|
||||
|
@ -51,8 +61,13 @@ void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Init encryption key by server
|
||||
* @param key_size is value between 7 and 16
|
||||
* @brief Sets the keys we will distibute during encryption.
|
||||
* @param [in] init_key A bitmask of the keys we will distibute.\n
|
||||
* Can be one or more of:
|
||||
* * ESP_BLE_ENC_KEY_MASK (1 << 0)
|
||||
* * ESP_BLE_ID_KEY_MASK (1 << 1)
|
||||
* * ESP_BLE_CSR_KEY_MASK (1 << 2)
|
||||
* * ESP_BLE_LINK_KEY_MASK (1 << 3)
|
||||
*/
|
||||
void NimBLESecurity::setInitEncryptionKey(uint8_t init_key) {
|
||||
NimBLEDevice::setSecurityInitKey(init_key);
|
||||
|
@ -60,8 +75,13 @@ void NimBLESecurity::setInitEncryptionKey(uint8_t init_key) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Init encryption key by client
|
||||
* @param key_size is value between 7 and 16
|
||||
* @brief Sets the keys we will accept during encryption.
|
||||
* @param [in] resp_key A bitmask of the keys we will accept.\n
|
||||
* Can be one or more of:
|
||||
* * ESP_BLE_ENC_KEY_MASK (1 << 0)
|
||||
* * ESP_BLE_ID_KEY_MASK (1 << 1)
|
||||
* * ESP_BLE_CSR_KEY_MASK (1 << 2)
|
||||
* * ESP_BLE_LINK_KEY_MASK (1 << 3)
|
||||
*/
|
||||
void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) {
|
||||
NimBLEDevice::setSecurityRespKey(resp_key);
|
||||
|
@ -70,7 +90,6 @@ void NimBLESecurity::setRespEncryptionKey(uint8_t resp_key) {
|
|||
|
||||
/**
|
||||
*@todo Requires implementation
|
||||
*
|
||||
*/
|
||||
void NimBLESecurity::setKeySize(uint8_t key_size) {
|
||||
|
||||
|
@ -80,7 +99,8 @@ void NimBLESecurity::setKeySize(uint8_t key_size) {
|
|||
|
||||
|
||||
/**
|
||||
* Setup for static PIN connection.
|
||||
* @brief Sets a static PIN used to authenticate/encrypt the connection.
|
||||
* @param [in] pin The 6 digit pin code to accept.
|
||||
*/
|
||||
void NimBLESecurity::setStaticPIN(uint32_t pin){
|
||||
//uint32_t passkey = pin;
|
||||
|
|
|
@ -12,10 +12,6 @@
|
|||
* Author: chegewara
|
||||
*/
|
||||
|
||||
/** This class exists for backward compatibility - Should not be used in new code
|
||||
* See the security functions in NimBLEDevice and callbacks in NimBLEServer / NimBLEClient
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_NIMBLESECURITY_H_
|
||||
#define COMPONENTS_NIMBLESECURITY_H_
|
||||
#include "sdkconfig.h"
|
||||
|
@ -56,6 +52,12 @@
|
|||
typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit pattern */
|
||||
typedef uint8_t esp_ble_io_cap_t; /*!< combination of the io capability */
|
||||
|
||||
|
||||
/**
|
||||
* @brief A class to handle BLE security operations.
|
||||
* <b>Deprecated - provided for backward compatibility only.</b>
|
||||
* @deprecated Use the security methods provided in NimBLEDevice instead.
|
||||
*/
|
||||
class NimBLESecurity {
|
||||
public:
|
||||
NimBLESecurity();
|
||||
|
@ -78,8 +80,10 @@ private:
|
|||
}; // BLESecurity
|
||||
|
||||
|
||||
/*
|
||||
* @brief Callbacks to handle GAP events related to authorization
|
||||
/**
|
||||
* @brief Callbacks to handle GAP events related to authorization.
|
||||
* <b>Deprecated - provided for backward compatibility only.</b>
|
||||
* @deprecated Use the callbacks provided in NimBLEClientCallbacks and NimBLEServerCallbacks instead.
|
||||
*/
|
||||
class NimBLESecurityCallbacks {
|
||||
public:
|
||||
|
@ -95,21 +99,25 @@ public:
|
|||
/**
|
||||
* @brief Provide us 6-digits code to perform authentication.
|
||||
* It requires that our device is capable to display this code to end user
|
||||
* @param
|
||||
* @param [in] pass_key The PIN provided by the peer.
|
||||
*/
|
||||
virtual void onPassKeyNotify(uint32_t pass_key) = 0;
|
||||
|
||||
/**
|
||||
* @brief Here we can make decision if we want to let negotiate authorization with peer device or not
|
||||
* return Return true if we accept this peer device request
|
||||
* @return Return true if we accept this peer device request
|
||||
*/
|
||||
|
||||
virtual bool onSecurityRequest() = 0 ;
|
||||
/**
|
||||
* Provide us information when authentication process is completed
|
||||
* @brief Provides us information when authentication process is completed
|
||||
*/
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc*) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called when using numeric comparison for authentication.
|
||||
* @param [in] pin The PIN to compare.
|
||||
* @return True to accept and pair.
|
||||
*/
|
||||
virtual bool onConfirmPIN(uint32_t pin) = 0;
|
||||
}; // BLESecurityCallbacks
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include "NimBLEDevice.h"
|
||||
#include "NimBLELog.h"
|
||||
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
|
||||
|
||||
static const char* LOG_TAG = "NimBLEServer";
|
||||
static NimBLEServerCallbacks defaultCallbacks;
|
||||
|
||||
|
@ -37,9 +41,25 @@ NimBLEServer::NimBLEServer() {
|
|||
m_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
m_advertiseOnDisconnect = true;
|
||||
m_svcChanged = false;
|
||||
m_deleteCallbacks = true;
|
||||
} // NimBLEServer
|
||||
|
||||
|
||||
/**
|
||||
* @brief Destructor: frees all resources / attributes created.
|
||||
*/
|
||||
NimBLEServer::~NimBLEServer() {
|
||||
for(auto &it : m_svcVec) {
|
||||
delete it;
|
||||
}
|
||||
|
||||
if(m_deleteCallbacks && m_pServerCallbacks != &defaultCallbacks) {
|
||||
delete m_pServerCallbacks;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a %BLE Service.
|
||||
* @param [in] uuid The UUID of the new service.
|
||||
|
@ -71,6 +91,12 @@ NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numH
|
|||
NimBLEService* pService = new NimBLEService(uuid, numHandles, this);
|
||||
m_svcVec.push_back(pService); // Save a reference to this service being on this server.
|
||||
|
||||
if(m_gattsStarted) {
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
m_svcChanged = true;
|
||||
resetGATT();
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< createService");
|
||||
return pService;
|
||||
} // createService
|
||||
|
@ -146,17 +172,21 @@ void NimBLEServer::start() {
|
|||
|
||||
NIMBLE_LOGI(LOG_TAG, "Service changed characterisic handle: %d", m_svcChgChrHdl);
|
||||
*/
|
||||
// Build a vector of characteristics with Notify / Indicate capabilities for event handling
|
||||
// Get the assigned service handles and build a vector of characteristics
|
||||
// with Notify / Indicate capabilities for event handling
|
||||
for(auto &svc : m_svcVec) {
|
||||
if(svc->m_removed == 0) {
|
||||
rc = ble_gatts_find_svc(&svc->getUUID().getNative()->u, &svc->m_handle);
|
||||
if(rc != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &chr : svc->m_chrVec) {
|
||||
// if Notify / Indicate is enabled but we didn't create the descriptor
|
||||
// we do it now.
|
||||
if((chr->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||
(chr->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
||||
|
||||
if(nullptr == chr->getDescriptorByUUID(uint16_t(0x2902))) {
|
||||
chr->createDescriptor(uint16_t(0x2902));
|
||||
}
|
||||
m_notifyChrVec.push_back(chr);
|
||||
}
|
||||
}
|
||||
|
@ -168,8 +198,8 @@ void NimBLEServer::start() {
|
|||
|
||||
/**
|
||||
* @brief Disconnect the specified client with optional reason.
|
||||
* @param [in] Connection Id of the client to disconnect.
|
||||
* @param [in] Reason code for disconnecting.
|
||||
* @param [in] connId Connection Id of the client to disconnect.
|
||||
* @param [in] reason code for disconnecting.
|
||||
* @return NimBLE host return code.
|
||||
*/
|
||||
int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
||||
|
@ -188,7 +218,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||
|
||||
/**
|
||||
* @brief Set the server to automatically start advertising when a client disconnects.
|
||||
* @param [in] bool true == advertise, false == don't advertise.
|
||||
* @param [in] aod true == advertise, false == don't advertise.
|
||||
*/
|
||||
void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
||||
m_advertiseOnDisconnect = aod;
|
||||
|
@ -260,6 +290,11 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
server->m_connectedPeersVec.end(),
|
||||
event->disconnect.conn.conn_handle),
|
||||
server->m_connectedPeersVec.end());
|
||||
|
||||
if(server->m_svcChanged) {
|
||||
server->resetGATT();
|
||||
}
|
||||
|
||||
server->m_pServerCallbacks->onDisconnect(server);
|
||||
|
||||
if(server->m_advertiseOnDisconnect) {
|
||||
|
@ -269,9 +304,9 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
} // BLE_GAP_EVENT_DISCONNECT
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE: {
|
||||
NIMBLE_LOGI(LOG_TAG, "subscribe event; cur_notify=%d\n value handle; "
|
||||
"val_handle=%d\n",
|
||||
event->subscribe.cur_notify, event->subscribe.attr_handle);
|
||||
NIMBLE_LOGI(LOG_TAG, "subscribe event; attr_handle=%d, subscribed: %s",
|
||||
event->subscribe.attr_handle,
|
||||
(event->subscribe.cur_notify ? "true":"false"));
|
||||
|
||||
for(auto &it : server->m_notifyChrVec) {
|
||||
if(it->getHandle() == event->subscribe.attr_handle) {
|
||||
|
@ -318,6 +353,12 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "Advertising Complete");
|
||||
NimBLEDevice::getAdvertising()->advCompleteCB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
|
||||
return 0;
|
||||
|
@ -435,16 +476,121 @@ size_t NimBLEServer::getConnectedCount() {
|
|||
* events are detected.
|
||||
*
|
||||
* @param [in] pCallbacks The callbacks to be invoked.
|
||||
* @param [in] deleteCallbacks if true callback class will be deleted when server is destructed.
|
||||
*/
|
||||
void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks) {
|
||||
void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCallbacks) {
|
||||
if (pCallbacks != nullptr){
|
||||
m_pServerCallbacks = pCallbacks;
|
||||
m_deleteCallbacks = deleteCallbacks;
|
||||
} else {
|
||||
m_pServerCallbacks = &defaultCallbacks;
|
||||
}
|
||||
} // setCallbacks
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove a service from the server.
|
||||
*
|
||||
* @details Immediately removes access to the service by clients, sends a service changed indication,
|
||||
* and removes the service (if applicable) from the advertisments.
|
||||
* The service is not deleted unless the deleteSvc parameter is true, otherwise the service remains
|
||||
* available and can be re-added in the future. If desired a removed but not deleted service can
|
||||
* be deleted later by calling this method with deleteSvc set to true.
|
||||
*
|
||||
* @note The service will not be removed from the database until all open connections are closed
|
||||
* as it requires resetting the GATT server. In the interim the service will have it's visibility disabled.
|
||||
*
|
||||
* @note Advertising will need to be restarted by the user after calling this as we must stop
|
||||
* advertising in order to remove the service.
|
||||
*
|
||||
* @param [in] service The service object to remove.
|
||||
* @param [in] deleteSvc true if the service should be deleted.
|
||||
*/
|
||||
void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
||||
// Check if the service was already removed and if so check if this
|
||||
// is being called to delete the object and do so if requested.
|
||||
// Otherwise, ignore the call and return.
|
||||
if(service->m_removed > 0) {
|
||||
if(deleteSvc) {
|
||||
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ++it) {
|
||||
if ((*it)->getUUID() == service->getUUID()) {
|
||||
delete *it;
|
||||
m_svcVec.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int rc = ble_gatts_svc_set_visibility(service->getHandle(), 0);
|
||||
if(rc !=0) {
|
||||
return;
|
||||
}
|
||||
|
||||
service->m_removed = deleteSvc ? 2 : 1;
|
||||
m_svcChanged = true;
|
||||
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Adds a service which was already created, but removed from availability.
|
||||
* @param [in] service The service object to add.
|
||||
* @note If it is desired to advertise the service it must be added by
|
||||
* calling NimBLEAdvertising::addServiceUUID.
|
||||
*/
|
||||
void NimBLEServer::addService(NimBLEService* service) {
|
||||
// If adding a service that was not removed just return.
|
||||
if(service->m_removed == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
service->m_removed = 0;
|
||||
m_svcChanged = true;
|
||||
|
||||
ble_svc_gatt_changed(0x0001, 0xffff);
|
||||
resetGATT();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Resets the GATT server, used when services are added/removed after initialization.
|
||||
*/
|
||||
void NimBLEServer::resetGATT() {
|
||||
if(getConnectedCount() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLEDevice::stopAdvertising();
|
||||
ble_gatts_reset();
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
|
||||
for(auto it = m_svcVec.begin(); it != m_svcVec.end(); ) {
|
||||
if ((*it)->m_removed > 0) {
|
||||
if ((*it)->m_removed == 2) {
|
||||
delete *it;
|
||||
it = m_svcVec.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
(*it)->start();
|
||||
++it;
|
||||
}
|
||||
|
||||
m_svcChanged = false;
|
||||
m_gattsStarted = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
*
|
||||
|
@ -516,7 +662,7 @@ uint32_t NimBLEServerCallbacks::onPassKeyRequest(){
|
|||
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyRequest: default: 123456");
|
||||
return 123456;
|
||||
}
|
||||
|
||||
/*
|
||||
void NimBLEServerCallbacks::onPassKeyNotify(uint32_t pass_key){
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onPassKeyNotify: default: %d", pass_key);
|
||||
}
|
||||
|
@ -525,6 +671,7 @@ bool NimBLEServerCallbacks::onSecurityRequest(){
|
|||
NIMBLE_LOGD("NimBLEServerCallbacks", "onSecurityRequest: default: true");
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
void NimBLEServerCallbacks::onAuthenticationComplete(ble_gap_conn_desc*){
|
||||
NIMBLE_LOGD("NimBLEServerCallbacks", "onAuthenticationComplete: default");
|
||||
}
|
||||
|
|
|
@ -41,8 +41,11 @@ public:
|
|||
NimBLEService* createService(const char* uuid);
|
||||
NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15,
|
||||
uint8_t inst_id=0);
|
||||
void removeService(NimBLEService* service, bool deleteSvc = false);
|
||||
void addService(NimBLEService* service);
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks);
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
||||
bool deleteCallbacks = true);
|
||||
void startAdvertising();
|
||||
void stopAdvertising();
|
||||
void start();
|
||||
|
@ -54,18 +57,21 @@ public:
|
|||
uint16_t minInterval, uint16_t maxInterval,
|
||||
uint16_t latency, uint16_t timeout);
|
||||
uint16_t getPeerMTU(uint16_t conn_id);
|
||||
std::vector<uint16_t> getPeerDevices();
|
||||
// std::vector<uint16_t> getPeerDevices();
|
||||
void advertiseOnDisconnect(bool);
|
||||
|
||||
private:
|
||||
NimBLEServer();
|
||||
~NimBLEServer();
|
||||
friend class NimBLECharacteristic;
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEAdvertising;
|
||||
|
||||
bool m_gattsStarted;
|
||||
bool m_advertiseOnDisconnect;
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
bool m_deleteCallbacks;
|
||||
std::vector<uint16_t> m_connectedPeersVec;
|
||||
|
||||
// uint16_t m_svcChgChrHdl; // Future use
|
||||
|
@ -74,6 +80,7 @@ private:
|
|||
std::vector<NimBLECharacteristic*> m_notifyChrVec;
|
||||
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
void resetGATT();
|
||||
}; // NimBLEServer
|
||||
|
||||
|
||||
|
@ -83,29 +90,52 @@ private:
|
|||
class NimBLEServerCallbacks {
|
||||
public:
|
||||
virtual ~NimBLEServerCallbacks() {};
|
||||
|
||||
/**
|
||||
* @brief Handle a new client connection.
|
||||
*
|
||||
* When a new client connects, we are invoked.
|
||||
*
|
||||
* @param [in] pServer A reference to the %BLE server that received the client connection.
|
||||
* @brief Handle a client connection.
|
||||
* This is called when a client connects.
|
||||
* @param [in] pServer A pointer to the %BLE server that received the client connection.
|
||||
*/
|
||||
virtual void onConnect(NimBLEServer* pServer);
|
||||
virtual void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Handle an existing client disconnection.
|
||||
*
|
||||
* When an existing client disconnects, we are invoked.
|
||||
*
|
||||
* @brief Handle a client connection.
|
||||
* This is called when a client connects.
|
||||
* @param [in] pServer A pointer to the %BLE server that received the client connection.
|
||||
* @param [in] desc A pointer to the connection description structure containig information
|
||||
* about the connection parameters.
|
||||
*/
|
||||
virtual void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Handle a client disconnection.
|
||||
* This is called when a client disconnects.
|
||||
* @param [in] pServer A reference to the %BLE server that received the existing client disconnection.
|
||||
*/
|
||||
virtual void onDisconnect(NimBLEServer* pServer);
|
||||
|
||||
virtual uint32_t onPassKeyRequest(); //{return 0;}
|
||||
virtual void onPassKeyNotify(uint32_t pass_key); //{}
|
||||
virtual bool onSecurityRequest(); //{return true;}
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);//{};
|
||||
virtual bool onConfirmPIN(uint32_t pin);//{return true;}
|
||||
/**
|
||||
* @brief Called when a client requests a passkey for pairing.
|
||||
* @return The passkey to be sent to the client.
|
||||
*/
|
||||
virtual uint32_t onPassKeyRequest();
|
||||
|
||||
//virtual void onPassKeyNotify(uint32_t pass_key);
|
||||
//virtual bool onSecurityRequest();
|
||||
|
||||
/**
|
||||
* @brief Called when the pairing procedure is complete.
|
||||
* @param [in] desc A pointer to the struct containing the connection information.\n
|
||||
* This can be used to check the status of the connection encryption/pairing.
|
||||
*/
|
||||
virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);
|
||||
|
||||
/**
|
||||
* @brief Called when using numeric comparision for pairing.
|
||||
* @param [in] pin The pin to compare with the client.
|
||||
* @return True to accept the pin.
|
||||
*/
|
||||
virtual bool onConfirmPIN(uint32_t pin);
|
||||
}; // NimBLEServerCallbacks
|
||||
|
||||
|
||||
|
|
|
@ -53,9 +53,31 @@ NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLE
|
|||
m_handle = NULL_HANDLE;
|
||||
m_pServer = pServer;
|
||||
m_numHandles = numHandles;
|
||||
m_pSvcDef = nullptr;
|
||||
m_removed = 0;
|
||||
|
||||
} // NimBLEService
|
||||
|
||||
|
||||
NimBLEService::~NimBLEService() {
|
||||
if(m_pSvcDef != nullptr) {
|
||||
if(m_pSvcDef->characteristics != nullptr) {
|
||||
for(int i=0; m_pSvcDef->characteristics[i].uuid != NULL; ++i) {
|
||||
if(m_pSvcDef->characteristics[i].descriptors) {
|
||||
delete(m_pSvcDef->characteristics[i].descriptors);
|
||||
}
|
||||
}
|
||||
delete(m_pSvcDef->characteristics);
|
||||
}
|
||||
|
||||
delete(m_pSvcDef);
|
||||
}
|
||||
|
||||
for(auto &it : m_chrVec) {
|
||||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dump details of this BLE GATT service.
|
||||
* @return N/A.
|
||||
|
@ -94,10 +116,11 @@ NimBLEUUID NimBLEService::getUUID() {
|
|||
* and registers it with the NimBLE stack.
|
||||
* @return bool success/failure .
|
||||
*/
|
||||
|
||||
bool NimBLEService::start() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> start(): Starting service: %s", toString().c_str());
|
||||
int rc = 0;
|
||||
|
||||
if(m_pSvcDef == nullptr) {
|
||||
// Nimble requires an array of services to be sent to the api
|
||||
// Since we are adding 1 at a time we create an array of 2 and set the type
|
||||
// of the second service to 0 to indicate the end of the array.
|
||||
|
@ -124,31 +147,14 @@ bool NimBLEService::start() {
|
|||
|
||||
for(uint8_t i=0; i < numChrs;) {
|
||||
uint8_t numDscs = pCharacteristic->m_dscVec.size();
|
||||
if(numDscs) {
|
||||
// skip 2902 as it's automatically created by NimBLE
|
||||
// if Indicate or Notify flags are set
|
||||
if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) &&
|
||||
pCharacteristic->getDescriptorByUUID("2902") != nullptr)
|
||||
{
|
||||
numDscs--;
|
||||
}
|
||||
}
|
||||
|
||||
if(!numDscs){
|
||||
pChr_a[i].descriptors = NULL;
|
||||
} else {
|
||||
// Must have last descriptor uuid = 0 so we have to create 1 extra
|
||||
//NIMBLE_LOGD(LOG_TAG, "Adding %d descriptors", numDscs);
|
||||
pDsc_a = new ble_gatt_dsc_def[numDscs+1];
|
||||
NimBLEDescriptor* pDescriptor = *pCharacteristic->m_dscVec.begin();
|
||||
for(uint8_t d=0; d < numDscs;) {
|
||||
// skip 2902
|
||||
if(pDescriptor->m_uuid == NimBLEUUID(uint16_t(0x2902))) {
|
||||
//NIMBLE_LOGD(LOG_TAG, "Skipped 0x2902");
|
||||
pDescriptor = *(pCharacteristic->m_dscVec.begin()+d+1);
|
||||
continue;
|
||||
}
|
||||
pDsc_a[d].uuid = &pDescriptor->m_uuid.getNative()->u;
|
||||
pDsc_a[d].att_flags = pDescriptor->m_properties;
|
||||
pDsc_a[d].min_key_size = 0;
|
||||
|
@ -178,14 +184,16 @@ bool NimBLEService::start() {
|
|||
|
||||
// end of services must indicate to api with type = 0
|
||||
svc[1].type = 0;
|
||||
m_pSvcDef = svc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)svc);
|
||||
rc = ble_gatts_count_cfg((const ble_gatt_svc_def*)m_pSvcDef);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gatts_count_cfg failed, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs((const ble_gatt_svc_def*)svc);
|
||||
rc = ble_gatts_add_svcs((const ble_gatt_svc_def*)m_pSvcDef);
|
||||
if (rc != 0) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gatts_add_svcs, rc= %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return false;
|
||||
|
@ -238,11 +246,21 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid
|
|||
} // createCharacteristic
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
||||
return getCharacteristic(NimBLEUUID(uuid));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the characteristic object with the specified UUID.
|
||||
* @param [in] uuid The UUID of the characteristic.
|
||||
* @return A pointer to the characteristic object or nullptr if not found.
|
||||
*/
|
||||
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||
for (auto &it : m_chrVec) {
|
||||
if (it->getUUID() == uuid) {
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
private:
|
||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||
~NimBLEService();
|
||||
|
||||
friend class NimBLEServer;
|
||||
friend class NimBLEDevice;
|
||||
|
@ -65,7 +66,8 @@ private:
|
|||
NimBLEServer* m_pServer;
|
||||
NimBLEUUID m_uuid;
|
||||
uint16_t m_numHandles;
|
||||
|
||||
ble_gatt_svc_def* m_pSvcDef;
|
||||
uint8_t m_removed;
|
||||
std::vector<NimBLECharacteristic*> m_chrVec;
|
||||
|
||||
}; // NimBLEService
|
||||
|
|
|
@ -73,15 +73,11 @@ static const char* LOG_TAG = "NimBLEUUID";
|
|||
|
||||
/**
|
||||
* @brief Create a UUID from 16 bytes of memory.
|
||||
*
|
||||
* @param [in] pData The pointer to the start of the UUID.
|
||||
* @param [in] size The size of the data.
|
||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||
/*** TODO: change this to use the Nimble function for various lenght UUIDs:
|
||||
int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len);
|
||||
***/
|
||||
if (size != 16) {
|
||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID length not 16 bytes");
|
||||
return;
|
||||
|
@ -99,7 +95,6 @@ NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
|||
|
||||
/**
|
||||
* @brief Create a UUID from the 16bit value.
|
||||
*
|
||||
* @param [in] uuid The 16bit short form UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint16_t uuid) {
|
||||
|
@ -111,7 +106,6 @@ NimBLEUUID::NimBLEUUID(uint16_t uuid) {
|
|||
|
||||
/**
|
||||
* @brief Create a UUID from the 32bit value.
|
||||
*
|
||||
* @param [in] uuid The 32bit short form UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(uint32_t uuid) {
|
||||
|
@ -123,7 +117,6 @@ NimBLEUUID::NimBLEUUID(uint32_t uuid) {
|
|||
|
||||
/**
|
||||
* @brief Create a UUID from the native UUID.
|
||||
*
|
||||
* @param [in] uuid The native UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
||||
|
@ -135,8 +128,8 @@ NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
|||
|
||||
/**
|
||||
* @brief Create a UUID from the 128bit value using hex parts instead of string,
|
||||
* instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes
|
||||
* BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6)
|
||||
* instead of NimBLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes
|
||||
* NimBLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6)
|
||||
*
|
||||
* @param [in] first The first 32bit of the UUID.
|
||||
* @param [in] second The next 16bit of the UUID.
|
||||
|
@ -153,6 +146,9 @@ NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates an empty UUID.
|
||||
*/
|
||||
NimBLEUUID::NimBLEUUID() {
|
||||
m_valueSet = false;
|
||||
} // NimBLEUUID
|
||||
|
@ -180,29 +176,31 @@ bool NimBLEUUID::equals(const NimBLEUUID &uuid) const {
|
|||
|
||||
|
||||
/**
|
||||
* Create a BLEUUID from a string of the form:
|
||||
* Create a NimBLEUUID from a string of the form:
|
||||
* 0xNNNN
|
||||
* 0xNNNNNNNN
|
||||
* 0x<UUID>
|
||||
* 0x<UUID\>
|
||||
* NNNN
|
||||
* NNNNNNNN
|
||||
* <UUID>
|
||||
* <UUID\>
|
||||
*
|
||||
* @param [in] uuid The string to create the UUID from.
|
||||
*/
|
||||
NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) {
|
||||
NimBLEUUID NimBLEUUID::fromString(const std::string &uuid) {
|
||||
uint8_t start = 0;
|
||||
if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
||||
if (strstr(uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
||||
start = 2;
|
||||
}
|
||||
uint8_t len = _uuid.length() - start; // Calculate the length of the string we are going to use.
|
||||
uint8_t len = uuid.length() - start; // Calculate the length of the string we are going to use.
|
||||
|
||||
if(len == 4) {
|
||||
uint16_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16);
|
||||
uint16_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16);
|
||||
return NimBLEUUID(x);
|
||||
} else if (len == 8) {
|
||||
uint32_t x = strtoul(_uuid.substr(start, len).c_str(), NULL, 16);
|
||||
uint32_t x = strtoul(uuid.substr(start, len).c_str(), NULL, 16);
|
||||
return NimBLEUUID(x);
|
||||
} else if (len == 36) {
|
||||
return NimBLEUUID(_uuid);
|
||||
return NimBLEUUID(uuid);
|
||||
}
|
||||
return NimBLEUUID();
|
||||
} // fromString
|
||||
|
@ -210,8 +208,7 @@ NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) {
|
|||
|
||||
/**
|
||||
* @brief Get the native UUID value.
|
||||
*
|
||||
* @return The native UUID value or NULL if not set.
|
||||
* @return The native UUID value or nullptr if not set.
|
||||
*/
|
||||
const ble_uuid_any_t* NimBLEUUID::getNative() const {
|
||||
if (m_valueSet == false) {
|
||||
|
@ -224,9 +221,9 @@ const ble_uuid_any_t* NimBLEUUID::getNative() const {
|
|||
|
||||
/**
|
||||
* @brief Convert a UUID to its 128 bit representation.
|
||||
*
|
||||
* A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method
|
||||
* @details A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method
|
||||
* will convert 16 or 32 bit representations to the full 128bit.
|
||||
* @return The NimBLEUUID converted to 128bit.
|
||||
*/
|
||||
const NimBLEUUID &NimBLEUUID::to128() {
|
||||
// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
|
||||
|
@ -248,19 +245,23 @@ const NimBLEUUID &NimBLEUUID::to128() {
|
|||
|
||||
/**
|
||||
* @brief Get a string representation of the UUID.
|
||||
*
|
||||
* @details
|
||||
* The format of a string is:
|
||||
* 01234567 8901 2345 6789 012345678901
|
||||
* 0000180d-0000-1000-8000-00805f9b34fb
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
*
|
||||
* @return A string representation of the UUID.
|
||||
* @deprecated Use std::string() operator instead.
|
||||
*/
|
||||
std::string NimBLEUUID::toString() const {
|
||||
return std::string(*this);
|
||||
} // toString
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this UUID is equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||
if(m_valueSet && rhs.m_valueSet) {
|
||||
return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0;
|
||||
|
@ -270,11 +271,19 @@ bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to check if this UUID is not equal to another.
|
||||
*/
|
||||
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||
return !this->operator==(rhs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convienience operator to convert this UUID to string representation.
|
||||
* @details This allows passing NimBLEUUID to functions
|
||||
* that accept std::string and/or or it's methods as a parameter.
|
||||
*/
|
||||
NimBLEUUID::operator std::string() const {
|
||||
if (!m_valueSet) return std::string(); // If we have no value, nothing to format.
|
||||
|
||||
|
|
|
@ -37,20 +37,21 @@ public:
|
|||
NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst);
|
||||
NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth);
|
||||
NimBLEUUID();
|
||||
uint8_t bitSize() const; // Get the number of bits in this uuid.
|
||||
|
||||
uint8_t bitSize() const;
|
||||
bool equals(const NimBLEUUID &uuid) const;
|
||||
const ble_uuid_any_t* getNative() const;
|
||||
const NimBLEUUID & to128();
|
||||
std::string toString() const;
|
||||
static NimBLEUUID fromString(const std::string &uuid); // Create a NimBLEUUID from a string
|
||||
static NimBLEUUID fromString(const std::string &uuid);
|
||||
|
||||
bool operator ==(const NimBLEUUID & rhs) const;
|
||||
bool operator !=(const NimBLEUUID & rhs) const;
|
||||
operator std::string() const;
|
||||
|
||||
private:
|
||||
ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps.
|
||||
bool m_valueSet = false; // Is there a value set for this instance.
|
||||
ble_uuid_any_t m_uuid;
|
||||
bool m_valueSet = false;
|
||||
}; // NimBLEUUID
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_NIMBLEUUID_H_ */
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
static const char* LOG_TAG = "NimBLEUtils";
|
||||
|
||||
|
||||
/**
|
||||
* @brief A function for checking validity of connection parameters.
|
||||
* @param [in] params A pointer to the structure containing the parameters to check.
|
||||
* @return valid == 0 or error code.
|
||||
*/
|
||||
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
||||
/* Check connection interval min */
|
||||
if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
|
||||
|
@ -49,6 +54,11 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Converts a return code from the NimBLE stack to a text string.
|
||||
* @param [in] rc The return code to convert.
|
||||
* @return A string representation of the return code.
|
||||
*/
|
||||
const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||
switch(rc) {
|
||||
|
@ -338,9 +348,9 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
|
|||
|
||||
|
||||
/**
|
||||
* @brief Convert the BLE Advertising Data flags to a string.
|
||||
* @param adFlags The flags to convert
|
||||
* @return std::string A string representation of the advertising flags.
|
||||
* @brief Convert the advertising type flag to a string.
|
||||
* @param advType The type to convert.
|
||||
* @return A string representation of the advertising flags.
|
||||
*/
|
||||
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||
|
@ -400,6 +410,11 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t
|
|||
} // buildHexData
|
||||
|
||||
|
||||
/**
|
||||
* @brief Utility function to log the gap event info.
|
||||
* @param [in] event A pointer to the gap event structure.
|
||||
* @param [in] arg Unused.
|
||||
*/
|
||||
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
||||
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
|
||||
|
@ -408,7 +423,7 @@ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
|||
|
||||
|
||||
/**
|
||||
* @brief Convert a BT GAP event type to a string representation.
|
||||
* @brief Convert a GAP event type to a string representation.
|
||||
* @param [in] eventType The type of event.
|
||||
* @return A string representation of the event type.
|
||||
*/
|
||||
|
@ -493,198 +508,4 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
|||
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||
} // gapEventToString
|
||||
|
||||
|
||||
/**
|
||||
* Utility function to log an array of bytes.
|
||||
*/
|
||||
void print_bytes(const uint8_t *bytes, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
MODLOG_DFLT(ERROR, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
|
||||
if(i % 30 == 0){
|
||||
MODLOG_DFLT(ERROR, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
MODLOG_DFLT(ERROR, "\n");
|
||||
}
|
||||
|
||||
void print_mbuf(const struct os_mbuf *om)
|
||||
{
|
||||
int colon;
|
||||
|
||||
colon = 0;
|
||||
while (om != NULL) {
|
||||
if (colon) {
|
||||
MODLOG_DFLT(DEBUG, ":");
|
||||
} else {
|
||||
colon = 1;
|
||||
}
|
||||
print_bytes(om->om_data, om->om_len);
|
||||
om = SLIST_NEXT(om, om_next);
|
||||
}
|
||||
}
|
||||
|
||||
char *addr_str(const void *addr)
|
||||
{
|
||||
static char buf[6 * 2 + 5 + 1];
|
||||
const uint8_t *u8p;
|
||||
|
||||
u8p = (const uint8_t*)addr;
|
||||
sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void print_uuid(const ble_uuid_t *uuid)
|
||||
{
|
||||
char buf[BLE_UUID_STR_LEN];
|
||||
|
||||
MODLOG_DFLT(DEBUG, "%s", ble_uuid_to_str(uuid, buf));
|
||||
}
|
||||
|
||||
void print_adv_fields(const struct ble_hs_adv_fields *fields)
|
||||
{
|
||||
char s[BLE_HS_ADV_MAX_SZ];
|
||||
const uint8_t *u8p;
|
||||
int i;
|
||||
|
||||
if (fields->flags != 0) {
|
||||
MODLOG_DFLT(DEBUG, " flags=0x%02x\n", fields->flags);
|
||||
}
|
||||
|
||||
if (fields->uuids16 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " uuids16(%scomplete)=",
|
||||
fields->uuids16_is_complete ? "" : "in");
|
||||
for (i = 0; i < fields->num_uuids16; i++) {
|
||||
print_uuid(&fields->uuids16[i].u);
|
||||
MODLOG_DFLT(DEBUG, " ");
|
||||
}
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->uuids32 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " uuids32(%scomplete)=",
|
||||
fields->uuids32_is_complete ? "" : "in");
|
||||
for (i = 0; i < fields->num_uuids32; i++) {
|
||||
print_uuid(&fields->uuids32[i].u);
|
||||
MODLOG_DFLT(DEBUG, " ");
|
||||
}
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->uuids128 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " uuids128(%scomplete)=",
|
||||
fields->uuids128_is_complete ? "" : "in");
|
||||
for (i = 0; i < fields->num_uuids128; i++) {
|
||||
print_uuid(&fields->uuids128[i].u);
|
||||
MODLOG_DFLT(DEBUG, " ");
|
||||
}
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->name != NULL) {
|
||||
assert(fields->name_len < sizeof s - 1);
|
||||
memcpy(s, fields->name, fields->name_len);
|
||||
s[fields->name_len] = '\0';
|
||||
MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n",
|
||||
fields->name_is_complete ? "" : "in", s);
|
||||
}
|
||||
|
||||
if (fields->tx_pwr_lvl_is_present) {
|
||||
MODLOG_DFLT(DEBUG, " tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
|
||||
}
|
||||
|
||||
if (fields->slave_itvl_range != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " slave_itvl_range=");
|
||||
print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid16 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " svc_data_uuid16=");
|
||||
print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->public_tgt_addr != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " public_tgt_addr=");
|
||||
u8p = fields->public_tgt_addr;
|
||||
for (i = 0; i < fields->num_public_tgt_addrs; i++) {
|
||||
MODLOG_DFLT(DEBUG, "public_tgt_addr=%s ", addr_str(u8p));
|
||||
u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||
}
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->appearance_is_present) {
|
||||
MODLOG_DFLT(DEBUG, " appearance=0x%04x\n", fields->appearance);
|
||||
}
|
||||
|
||||
if (fields->adv_itvl_is_present) {
|
||||
MODLOG_DFLT(DEBUG, " adv_itvl=0x%04x\n", fields->adv_itvl);
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid32 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " svc_data_uuid32=");
|
||||
print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->svc_data_uuid128 != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " svc_data_uuid128=");
|
||||
print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->uri != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " uri=");
|
||||
print_bytes(fields->uri, fields->uri_len);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
|
||||
if (fields->mfg_data != NULL) {
|
||||
MODLOG_DFLT(DEBUG, " mfg_data=");
|
||||
print_bytes(fields->mfg_data, fields->mfg_data_len);
|
||||
MODLOG_DFLT(DEBUG, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs information about a connection to the console.
|
||||
*/
|
||||
void print_conn_desc(const struct ble_gap_conn_desc *desc)
|
||||
{
|
||||
MODLOG_DFLT(DEBUG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ",
|
||||
desc->conn_handle, desc->our_ota_addr.type,
|
||||
addr_str(desc->our_ota_addr.val));
|
||||
MODLOG_DFLT(DEBUG, "our_id_addr_type=%d our_id_addr=%s ",
|
||||
desc->our_id_addr.type, addr_str(desc->our_id_addr.val));
|
||||
MODLOG_DFLT(DEBUG, "peer_ota_addr_type=%d peer_ota_addr=%s ",
|
||||
desc->peer_ota_addr.type, addr_str(desc->peer_ota_addr.val));
|
||||
MODLOG_DFLT(DEBUG, "peer_id_addr_type=%d peer_id_addr=%s ",
|
||||
desc->peer_id_addr.type, addr_str(desc->peer_id_addr.val));
|
||||
MODLOG_DFLT(DEBUG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d "
|
||||
"encrypted=%d authenticated=%d bonded=%d",
|
||||
desc->conn_itvl, desc->conn_latency,
|
||||
desc->supervision_timeout,
|
||||
desc->sec_state.encrypted,
|
||||
desc->sec_state.authenticated,
|
||||
desc->sec_state.bonded);
|
||||
}
|
||||
|
||||
|
||||
void print_addr(const void *addr)
|
||||
{
|
||||
const uint8_t *u8p;
|
||||
|
||||
u8p = (uint8_t*)addr;
|
||||
MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
|
||||
}
|
||||
|
||||
#endif //CONFIG_BT_ENABLED
|
||||
|
|
|
@ -27,14 +27,10 @@ typedef struct {
|
|||
std::string *buf;
|
||||
} ble_task_data_t;
|
||||
|
||||
extern "C"{
|
||||
char *addr_str(const void *addr);
|
||||
void print_conn_desc(const struct ble_gap_conn_desc *desc);
|
||||
void print_adv_fields(const struct ble_hs_adv_fields *fields);
|
||||
void print_addr(const void *addr);
|
||||
void print_bytes(const uint8_t *bytes, int len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A BLE Utility class with methods for debugging and general purpose use.
|
||||
*/
|
||||
class NimBLEUtils {
|
||||
public:
|
||||
static void dumpGapEvent(ble_gap_event *event, void *arg);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "esp_bt.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_compiler.h"
|
||||
#include "esp_ipc.h"
|
||||
|
||||
#define NIMBLE_VHCI_TIMEOUT_MS 2000
|
||||
|
||||
|
@ -78,21 +79,29 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
|
|||
ble_hci_rx_acl_hs_arg = acl_arg;
|
||||
}
|
||||
|
||||
void ble_hci_trans_hs_cmd_tx_on_core_0(void *arg)
|
||||
{
|
||||
uint8_t *cmd = arg;
|
||||
uint16_t len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1;
|
||||
esp_vhci_host_send_packet(cmd, len);
|
||||
}
|
||||
|
||||
int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t rc = 0;
|
||||
|
||||
assert(cmd != NULL);
|
||||
*cmd = BLE_HCI_UART_H4_CMD;
|
||||
len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1;
|
||||
if (!esp_vhci_host_check_send_available()) {
|
||||
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
esp_vhci_host_send_packet(cmd, len);
|
||||
if (xPortGetCoreID() != 0) {
|
||||
esp_ipc_call_blocking(0, ble_hci_trans_hs_cmd_tx_on_core_0, cmd);
|
||||
} else {
|
||||
ble_hci_trans_hs_cmd_tx_on_core_0(cmd);
|
||||
}
|
||||
} else {
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
|
@ -111,27 +120,37 @@ int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void ble_hci_trans_hs_acl_tx_on_core_0(void *arg)
|
||||
{
|
||||
uint8_t data[MYNEWT_VAL(BLE_ACL_BUF_SIZE) + 1];
|
||||
struct os_mbuf *om = arg;
|
||||
uint16_t len = 1 + OS_MBUF_PKTLEN(om);
|
||||
|
||||
data[0] = BLE_HCI_UART_H4_ACL;
|
||||
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
|
||||
|
||||
esp_vhci_host_send_packet(data, len);
|
||||
}
|
||||
|
||||
int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
uint8_t data[MYNEWT_VAL(BLE_ACL_BUF_SIZE) + 1], rc = 0;
|
||||
uint8_t rc = 0;
|
||||
/* If this packet is zero length, just free it */
|
||||
if (OS_MBUF_PKTLEN(om) == 0) {
|
||||
os_mbuf_free_chain(om);
|
||||
return 0;
|
||||
}
|
||||
data[0] = BLE_HCI_UART_H4_ACL;
|
||||
len++;
|
||||
|
||||
if (!esp_vhci_host_check_send_available()) {
|
||||
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
||||
}
|
||||
|
||||
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
|
||||
len += OS_MBUF_PKTLEN(om);
|
||||
|
||||
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
esp_vhci_host_send_packet(data, len);
|
||||
if (xPortGetCoreID() != 0) {
|
||||
esp_ipc_call_blocking(0, ble_hci_trans_hs_acl_tx_on_core_0, om);
|
||||
} else {
|
||||
ble_hci_trans_hs_acl_tx_on_core_0(om);
|
||||
}
|
||||
} else {
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
|
@ -451,6 +470,7 @@ esp_err_t esp_nimble_hci_and_controller_init(void)
|
|||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
bt_cfg.ble_max_conn = CONFIG_BT_NIMBLE_MAX_CONNECTIONS;
|
||||
|
||||
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
return ret;
|
||||
|
|
|
@ -53,6 +53,7 @@ struct ble_hs_peer_sec {
|
|||
*/
|
||||
struct ble_hs_dev_records {
|
||||
bool rec_used;
|
||||
uint8_t rand_addr_type;
|
||||
uint8_t pseudo_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rand_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t identity_addr[BLE_DEV_ADDR_LEN];
|
||||
|
|
|
@ -181,6 +181,44 @@ is_rpa_resolvable_by_peer_rec(struct ble_hs_dev_records *p_dev_rec, uint8_t *pee
|
|||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_rpa_replace_id_with_rand_addr(uint8_t *addr_type, uint8_t *peer_addr)
|
||||
{
|
||||
struct ble_hs_dev_records *p_dev_rec;
|
||||
ble_addr_t p_addr = {0};
|
||||
struct ble_hs_conn *conn = NULL;
|
||||
|
||||
p_dev_rec = ble_rpa_find_peer_dev_rec(peer_addr);
|
||||
|
||||
if (p_dev_rec != NULL) {
|
||||
if (memcmp(p_dev_rec->rand_addr, p_dev_rec->identity_addr, BLE_DEV_ADDR_LEN)) {
|
||||
/* OTA address (before resolving) gets saved in RAND_ADDR when the peer
|
||||
* record is fetched from resolving list. Replace peer address
|
||||
* with rand_addr to maintain status quo for new pairing/encryption request. */
|
||||
p_addr.type = *addr_type;
|
||||
memcpy(&p_addr.val[0], peer_addr, BLE_DEV_ADDR_LEN);
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
conn = ble_hs_conn_find_by_addr(&p_addr);
|
||||
/* Rewrite the peer address history in ble_hs_conn. Need to take
|
||||
* this step to avoid taking wrong address during re-pairing
|
||||
* process */
|
||||
if (conn != NULL) {
|
||||
conn->bhc_peer_rpa_addr.type = p_dev_rec->rand_addr_type;
|
||||
memcpy(&conn->bhc_peer_rpa_addr.val[0], p_dev_rec->rand_addr, BLE_DEV_ADDR_LEN);
|
||||
conn->bhc_peer_addr.type = p_dev_rec->rand_addr_type;
|
||||
memcpy(&conn->bhc_peer_addr.val[0], p_dev_rec->rand_addr, BLE_DEV_ADDR_LEN);
|
||||
BLE_HS_LOG(DEBUG, "\n Replace Identity addr with random addr received at"
|
||||
" start of the connection\n");
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add peer to peer device records.
|
||||
*
|
||||
* @return 0 if added successfully,
|
||||
|
@ -227,6 +265,7 @@ ble_rpa_find_rl_from_peer_records(uint8_t *peer_addr, uint8_t *peer_addr_type)
|
|||
|
||||
if (is_rpa_resolvable_by_peer_rec(p_dev_rec, peer_addr)) {
|
||||
memcpy(p_dev_rec->rand_addr, peer_addr, BLE_DEV_ADDR_LEN);
|
||||
p_dev_rec->rand_addr_type = *peer_addr_type;
|
||||
rl = ble_hs_resolv_list_find(p_dev_rec->identity_addr);
|
||||
if (rl) {
|
||||
memcpy(peer_addr, p_dev_rec->identity_addr, BLE_DEV_ADDR_LEN);
|
||||
|
@ -277,14 +316,11 @@ ble_rpa_replace_peer_params_with_rl(uint8_t *peer_addr, uint8_t *addr_type,
|
|||
|
||||
if (is_rpa) {
|
||||
ble_hs_log_flat_buf(peer_addr, BLE_DEV_ADDR_LEN);
|
||||
rl_tmp = ble_hs_resolv_list_find(peer_addr);
|
||||
BLE_HS_LOG(DEBUG, "\n");
|
||||
|
||||
/* Try to find from your peer_device records, if RL doesn't
|
||||
* exist */
|
||||
if (rl_tmp == NULL) {
|
||||
/* Try to find RL from your peer_device records */
|
||||
rl_tmp = ble_rpa_find_rl_from_peer_records(peer_addr, addr_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (rl != NULL) {
|
||||
*rl = rl_tmp;
|
||||
|
@ -571,7 +607,7 @@ ble_hs_resolv_list_add(uint8_t *cmdbuf)
|
|||
int
|
||||
ble_hs_resolv_list_rmv(uint8_t addr_type, uint8_t *ident_addr)
|
||||
{
|
||||
int position;
|
||||
int position, rc = BLE_HS_ENOENT;
|
||||
|
||||
/* Remove from IRK records */
|
||||
position = ble_hs_is_on_resolv_list(ident_addr, addr_type);
|
||||
|
@ -583,10 +619,15 @@ ble_hs_resolv_list_rmv(uint8_t addr_type, uint8_t *ident_addr)
|
|||
ble_hs_resolv_entry));
|
||||
--g_ble_hs_resolv_data.rl_cnt;
|
||||
|
||||
return 0;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return BLE_HS_ENOENT;
|
||||
/* As we are removing the RL record, it is needed to change
|
||||
* peer_address to its latest received OTA address, this helps when existing bond at
|
||||
* peer side is removed */
|
||||
ble_rpa_replace_id_with_rand_addr(&addr_type, ident_addr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,6 +53,7 @@ struct ble_hs_peer_sec {
|
|||
*/
|
||||
struct ble_hs_dev_records {
|
||||
bool rec_used;
|
||||
uint8_t rand_addr_type;
|
||||
uint8_t pseudo_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rand_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t identity_addr[BLE_DEV_ADDR_LEN];
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
/** @file
|
||||
*
|
||||
* IGNORE THIS FILE IF USING ESP-IDF, USE MENUCONFIG TO SET NIMBLE OPTIONS.
|
||||
*
|
||||
* The config options here are for Arduino use only.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
/** For ESP-IDF compatibility
|
||||
*
|
||||
|
||||
/*
|
||||
* For ESP-IDF compatibility
|
||||
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||
*/
|
||||
|
||||
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig) */
|
||||
#if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
|
@ -36,99 +45,171 @@
|
|||
#else // Using Arduino
|
||||
|
||||
/***********************************************
|
||||
* Arduino config options
|
||||
* Arduino config options start here
|
||||
**********************************************/
|
||||
|
||||
/** Comment out if not using NimBLE Client functions
|
||||
/** @brief Comment out if not using NimBLE Client functions \n
|
||||
* Reduces flash size by approx. 7kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||
|
||||
/** Comment out if not using NimBLE Scan functions
|
||||
/** @brief Comment out if not using NimBLE Scan functions \n
|
||||
* Reduces flash size by approx. 26kB.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
|
||||
/** Comment out if not using NimBLE Server functions
|
||||
/** @brief Comment out if not using NimBLE Server functions \n
|
||||
* Reduces flash size by approx. 16kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||
|
||||
/** Comment out if not using NimBLE Advertising functions
|
||||
/** @brief Comment out if not using NimBLE Advertising functions \n
|
||||
* Reduces flash size by approx. 5kB.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
|
||||
/** Uncomment to see debug log messages from the NimBLE host
|
||||
/* Uncomment to see debug log messages from the NimBLE host
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/** Uncomment to see NimBLE host return codes as text debug log messages.
|
||||
/* Uncomment to see NimBLE host return codes as text debug log messages.
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/** Uncomment to see GAP event codes as text in debug log messages.
|
||||
/* Uncomment to see GAP event codes as text in debug log messages.
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/** Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||
/* Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
|
||||
/** Sets the core NimBLE host runs on */
|
||||
/** @brief Sets the core NimBLE host runs on */
|
||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||
|
||||
/** Sets the stack size for the NimBLE host task */
|
||||
/** @brief Sets the stack size for the NimBLE host task */
|
||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||
|
||||
/** Sets the number of simultaneous connections (esp controller max is 9) */
|
||||
/**
|
||||
* @brief Sets the memory pool where NimBLE will be loaded
|
||||
* @details By default NimBLE is loaded in internal ram.\n
|
||||
* To use external PSRAM you must change this to `#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL 1`
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
||||
|
||||
/** @brief Sets the number of simultaneous connections (esp controller max is 9) */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||
|
||||
/** Sets the number of devices allowed to store/bond with */
|
||||
/** @brief Sets the number of devices allowed to store/bond with */
|
||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
||||
|
||||
/** Sets the number of CCCD's to store per bonded device */
|
||||
/** @brief Sets the maximum number of CCCD subscriptions to store */
|
||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
||||
|
||||
/** @brief Set if CCCD's and bond data should be stored in NVS */
|
||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 0
|
||||
|
||||
/** @brief Allow legacy paring */
|
||||
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
|
||||
|
||||
/** @brief Allow BLE secure connections */
|
||||
#define CONFIG_BT_NIMBLE_SM_SC 1
|
||||
|
||||
/** @brief Default device name */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||
|
||||
/** @brief Max device name length (bytes) */
|
||||
#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31
|
||||
|
||||
/** @brief Default MTU size */
|
||||
#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 256
|
||||
|
||||
/** @brief Default GAP appearance */
|
||||
#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
|
||||
|
||||
/** @brief ACL Buffer count */
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12
|
||||
|
||||
/** @brief ACL Buffer size */
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
|
||||
|
||||
/** @brief HCI Event Buffer size */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
|
||||
|
||||
/** @brief Number of high priority HCI event buffers */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
|
||||
|
||||
/** @brief Number of low priority HCI event buffers */
|
||||
#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8
|
||||
|
||||
/**
|
||||
* @brief Sets the number of MSYS buffers available.
|
||||
* @details MSYS is a system level mbuf registry. For prepare write & prepare \n
|
||||
* responses MBUFs are allocated out of msys_1 pool. This may need to be increased if\n
|
||||
* you are sending large blocks of data with a low MTU. E.g: 512 bytes with 23 MTU will fail.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12
|
||||
|
||||
|
||||
/** @brief Random address refresh time in seconds */
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
|
||||
/** @brief Maximum number of connection oriented channels */
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
|
||||
/* These should not be altered */
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL 1
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
|
||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||
|
||||
/** Do not comment out */
|
||||
#ifndef CONFIG_BT_ENABLED
|
||||
#define CONFIG_BT_ENABLED
|
||||
#endif
|
||||
|
||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
|
||||
|
||||
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||
|
||||
/** Cannot use client without scan */
|
||||
/**********************************
|
||||
End Arduino config
|
||||
**********************************/
|
||||
|
||||
|
||||
/* Cannot use client without scan */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||
#endif
|
||||
|
||||
/** Cannot use server without advertise */
|
||||
/* Cannot use server without advertise */
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef _DOXYGEN_
|
||||
/** @brief Uncomment to see debug log messages from the NimBLE host \n
|
||||
* Uses approx. 32kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_BT_NIMBLE_DEBUG
|
||||
|
||||
/** @brief Uncomment to see NimBLE host return codes as text debug log messages. \n
|
||||
* Uses approx. 7kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see GAP event codes as text in debug log messages. \n
|
||||
* Uses approx. 1kB of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||
|
||||
/** @brief Uncomment to see advertisment types as text while scanning in debug log messages. \n
|
||||
* Uses approx. 250 bytes of flash memory.
|
||||
*/
|
||||
#define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||
#endif // _DOXYGEN_
|
||||
|
|
|
@ -346,7 +346,8 @@ os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
|
|||
omi->omi_num_blocks = cur->mp_num_blocks;
|
||||
omi->omi_num_free = cur->mp_num_free;
|
||||
omi->omi_min_free = cur->mp_min_free;
|
||||
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name));
|
||||
strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name) - 1);
|
||||
omi->omi_name[sizeof(omi->omi_name) - 1] = '\0';
|
||||
|
||||
return (cur);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue