mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-22 05:00:55 +01:00
Update documentation.
This commit is contained in:
parent
88562bb310
commit
3b81d93d31
6 changed files with 396 additions and 281 deletions
|
@ -42,7 +42,9 @@ Call `NimBLEDevice::init("");` in `app_main`.
|
|||
# Using
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
|
||||
See: [The migration guide](docs/Migration_guide.md) for details.
|
||||
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.
|
||||
|
||||
|
@ -57,8 +59,5 @@ Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for inform
|
|||
|
||||
# Todo
|
||||
1. Implement random addresses.
|
||||
2. Implement NimBLEServer::removeService
|
||||
3. Implement extra fields in NimBLEAdvertisedDevice.
|
||||
4. Document nimconfig.
|
||||
5. Add BLE Mesh code.
|
||||
2. Add BLE Mesh code.
|
||||
<br/>
|
||||
|
|
|
@ -1,238 +0,0 @@
|
|||
# Breaking API Changes vs Original
|
||||
<br/>
|
||||
|
||||
# Server API differnces
|
||||
|
||||
### Characteristics
|
||||
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
|
||||
|
||||
#### Originally
|
||||
> BLECharacteristic::PROPERTY_READ |
|
||||
> BLECharacteristic::PROPERTY_WRITE
|
||||
|
||||
#### Is Now
|
||||
> NIMBLE_PROPERTY::READ |
|
||||
> NIMBLE_PROPERTY::WRITE
|
||||
<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/>
|
||||
|
||||
### Descriptors
|
||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor()` method.
|
||||
|
||||
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||
|
||||
0x2902 Descriptor class: formerly known as BLE2902 or NimBLE2902 has been removed.
|
||||
It was no longer useful as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
|
||||
to handle callback functionality and the client subscription status is handled internally.
|
||||
|
||||
NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
|
||||
|
||||
**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` methods (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/>
|
||||
|
||||
### Server Security
|
||||
Security is set on the characteristic or descriptor properties by applying one of the following:
|
||||
> NIMBLE_PROPERTY::READ_ENC
|
||||
> NIMBLE_PROPERTY::READ_AUTHEN
|
||||
> NIMBLE_PROPERTY::READ_AUTHOR
|
||||
> NIMBLE_PROPERTY::WRITE_ENC
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHEN
|
||||
> NIMBLE_PROPERTY::WRITE_AUTHOR
|
||||
|
||||
When a peer wants to read or write a characteristic or descriptor with any of these properties applied
|
||||
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
||||
This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details.
|
||||
<br/>
|
||||
|
||||
# Client API Differences
|
||||
The `NimBLEAdvertisedDeviceCallbacks::onResult()` method now receives a pointer to the
|
||||
`NimBLEAdvertisedDevice` object instead of a copy.
|
||||
|
||||
`NimBLEClient::connect()` Has had it's parameters altered.
|
||||
Defined as:
|
||||
> NimBLEClient::connect(bool refreshServices = true);
|
||||
> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool refreshServices = true);
|
||||
> NimBLEClient::connect(NimBLEAddress address, bool refreshServices = true);
|
||||
<br/>
|
||||
|
||||
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/>
|
||||
|
||||
> NimBLERemoteCharacteristic::writeValue();
|
||||
> NimBLERemoteCharacteristic::registerForNotify();
|
||||
|
||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||
<br/>
|
||||
|
||||
> NimBLERemoteCharacteristic::registerForNotify();
|
||||
|
||||
Is now **deprecated**.
|
||||
> NimBLERemoteCharacteristic::subscribe()
|
||||
> NimBLERemoteCharacteristic::unsubscribe()
|
||||
|
||||
Are the new methods added to replace it.
|
||||
<br/>
|
||||
|
||||
> NimBLERemoteCharacteristic::readUInt8()
|
||||
> NimBLERemoteCharacteristic::readUInt16()
|
||||
> NimBLERemoteCharacteristic::readUInt32()
|
||||
> NimBLERemoteCharacteristic::readFloat()
|
||||
|
||||
Are **deprecated** and NimBLERemoteCharacteristic::readValue<type\>(time_t\*, bool) template added to replace them.
|
||||
<br/>
|
||||
|
||||
> NimBLERemoteService::getCharacteristicsByHandle()
|
||||
|
||||
Has been removed from the API as it is no longer maintained in the library.
|
||||
<br/>
|
||||
|
||||
> NimBLERemoteCharacteristic::readRawData()
|
||||
|
||||
Has been removed from the API as it stored an unnecessary copy of the data.
|
||||
The user application should use NimBLERemoteCharacteristic::readValue or NimBLERemoteCharacteristic::getValue.
|
||||
Then cast the returned std::string to the type they wish such as:
|
||||
```
|
||||
uint8_t *val = (uint8_t*)pChr->readValue().data();
|
||||
```
|
||||
<br/>
|
||||
|
||||
> NimBLEClient::getServices(bool refresh = false)
|
||||
> NimBLERemoteCharacteristic::getDescriptors(bool refresh = false)
|
||||
> NimBLERemoteService::getCharacteristics(bool refresh = false)
|
||||
|
||||
These methods now take an optional (bool) parameter and return a pointer to `std::vector` instead of `std::map`.
|
||||
If passed true it will clear the respective vector and retrieve **all** the respective attributes from the peripheral.
|
||||
If false(default) it will return the respective vector with the currently stored attributes.
|
||||
<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 functionality.
|
||||
<br/>
|
||||
|
||||
> 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/>
|
||||
|
||||
### 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/>
|
||||
|
||||
# General Differences
|
||||
`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.
|
||||
|
||||
Defined as:
|
||||
> NimBLEAddress(ble_addr_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);
|
||||
<br/>
|
||||
|
||||
# Security Differences
|
||||
Security callback functions are now incorporated in the NimBLEServerCallbacks / NimBLEClientCallbacks classes.
|
||||
However backward compatibility with the original `BLESecurity` class is retained to minimize app code changes.
|
||||
|
||||
The callback methods are:
|
||||
|
||||
> bool onConfirmPIN(uint32_t pin);
|
||||
|
||||
Receives the pin when using numeric comparison authentication, `return true;` to accept.
|
||||
<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/>
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Server
|
||||
|
||||
NimBLECharacteristic::setValue(const T &s)
|
||||
NimBLEDescriptor::setValue(const T &s)
|
||||
`NimBLECharacteristic::setValue(const T &s)`
|
||||
`NimBLEDescriptor::setValue(const T &s)`
|
||||
|
||||
Now use a template to accomodate standard and custom types/values.
|
||||
|
||||
|
@ -27,7 +27,7 @@ struct my_struct{
|
|||
```
|
||||
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
|
||||
`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.
|
||||
|
||||
|
@ -53,8 +53,8 @@ using `NimBLEServer::addService`.
|
|||
|
||||
# Client
|
||||
|
||||
NimBLERemoteCharacteristic::readValue(time_t\*, bool)
|
||||
NimBLERemoteDescriptor::readValue(bool)
|
||||
`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
|
||||
`NimBLERemoteDescriptor::readValue(bool)`
|
||||
|
||||
Have been added as templates to allow reading the values as any specified type.
|
||||
|
||||
|
@ -73,14 +73,14 @@ struct my_struct{
|
|||
```
|
||||
<br/>
|
||||
|
||||
NimBLERemoteCharacteristic::registerForNotify
|
||||
`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
|
||||
`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
|
||||
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
|
||||
|
@ -93,19 +93,19 @@ 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().
|
||||
`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()`.
|
||||
|
||||
# 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.
|
||||
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.
|
||||
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).
|
||||
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.
|
||||
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`.
|
||||
|
|
|
@ -2,17 +2,27 @@
|
|||
|
||||
This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
|
||||
|
||||
The changes listed here are only some of the many that have been made, this is a short overview for migrating existing applications.
|
||||
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](docs/Improvements_and_updates.md)
|
||||
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)
|
||||
* [Client](#client-api)
|
||||
* [Remote Services](#remote-services)
|
||||
* [Remote characteristics](#remote-characteristics)
|
||||
* [Security](#security-api)
|
||||
<br/>
|
||||
|
||||
# General Information
|
||||
# General Information {#general-information}
|
||||
|
||||
### Header Files
|
||||
All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
|
||||
|
||||
You may choose to include `NimBLELog.h` in your appplication if you want to use the `NIMBLE_LOGx` macros for debugging.
|
||||
(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/>
|
||||
|
||||
|
@ -25,7 +35,7 @@ this means **no class names need to be changed in existing code** and makes migr
|
|||
<br/>
|
||||
|
||||
### BLE Addresses
|
||||
`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *optional* `uint8_t type` paramameter
|
||||
`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).
|
||||
|
@ -33,7 +43,7 @@ For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address obje
|
|||
As this paramameter is optional no changes to existing code are needed, it is mentioned here for information.
|
||||
<br/>
|
||||
|
||||
# Server API
|
||||
## Server API {#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.
|
||||
|
||||
|
@ -41,11 +51,11 @@ For example `BLEDevice::createServer()` will work just as it did before.
|
|||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
### Services
|
||||
### Services {#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.
|
||||
|
||||
### Characteristics
|
||||
### Characteristics {#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`.
|
||||
|
@ -97,7 +107,7 @@ BLECharacteristic *pCharacteristic = pService->createCharacteristic(
|
|||
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||
<br/>
|
||||
|
||||
### Descriptors
|
||||
### Descriptors {descriptors}
|
||||
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||
|
||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor` method.
|
||||
|
@ -159,10 +169,10 @@ Security is set on the characteristic or descriptor properties by applying one o
|
|||
|
||||
When a peer wants to read or write a characteristic or descriptor with any of these properties applied
|
||||
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
|
||||
This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details.
|
||||
This can be changed to use passkey authentication or numeric comparison. See [Security API](#security-api) for details.
|
||||
<br/>
|
||||
|
||||
# Client API
|
||||
## Client API {#client-api}
|
||||
|
||||
Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
|
||||
|
||||
|
@ -195,19 +205,22 @@ the user may not be interested in.
|
|||
to replace the the removed automatic functionality.
|
||||
<br/>
|
||||
|
||||
### Remote Services
|
||||
### Remote Services {#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/>
|
||||
|
||||
### Remote Characteristics
|
||||
### Remote Characteristics{#remote-characteristics}
|
||||
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
|
||||
|
||||
> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
|
||||
|
@ -241,6 +254,10 @@ Then cast the returned std::string to the type they wish such as:
|
|||
```
|
||||
uint8_t *val = (uint8_t*)pChr->readValue().data();
|
||||
```
|
||||
Alternatively use the `readValue` template:
|
||||
```
|
||||
my_struct_t myStruct = pChr->readValue<my_struct_t>();
|
||||
```
|
||||
<br/>
|
||||
|
||||
> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
|
||||
|
@ -250,16 +267,16 @@ the currently known database returned (false : default).
|
|||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||
<br/>
|
||||
|
||||
### Client Security
|
||||
### Client Security {#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/>
|
||||
|
||||
# Security API
|
||||
## Security API {#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 app code changes.
|
||||
However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
|
||||
|
||||
The callback methods are:
|
||||
|
||||
|
|
337
docs/New_user_guide.md
Normal file
337
docs/New_user_guide.md
Normal file
|
@ -0,0 +1,337 @@
|
|||
# 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/>
|
||||
|
||||
## Creating a Server {#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/>
|
||||
|
||||
## Creating a Client {#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/>
|
||||
|
|
@ -44,9 +44,9 @@ Call `NimBLEDevice::init("");` in `app_main`.
|
|||
# Using
|
||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
||||
|
||||
See: [The migration guide](docs/Migration_guide.md) for details.
|
||||
See: [The migration guide](Migration_guide.md) for details.
|
||||
|
||||
Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes.
|
||||
Also see [Improvements_and_updates](Improvements_and_updates.md) for information about non-breaking changes.
|
||||
|
||||
### Arduino specific:
|
||||
See the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
||||
|
|
Loading…
Reference in a new issue