mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-22 13:10: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
|
# Using
|
||||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
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.
|
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
|
# Todo
|
||||||
1. Implement random addresses.
|
1. Implement random addresses.
|
||||||
2. Implement NimBLEServer::removeService
|
2. Add BLE Mesh code.
|
||||||
3. Implement extra fields in NimBLEAdvertisedDevice.
|
|
||||||
4. Document nimconfig.
|
|
||||||
5. Add BLE Mesh code.
|
|
||||||
<br/>
|
<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
|
# Server
|
||||||
|
|
||||||
NimBLECharacteristic::setValue(const T &s)
|
`NimBLECharacteristic::setValue(const T &s)`
|
||||||
NimBLEDescriptor::setValue(const T &s)
|
`NimBLEDescriptor::setValue(const T &s)`
|
||||||
|
|
||||||
Now use a template to accomodate standard and custom types/values.
|
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.
|
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
|
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.
|
as a type specified by the user.
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ using `NimBLEServer::addService`.
|
||||||
|
|
||||||
# Client
|
# Client
|
||||||
|
|
||||||
NimBLERemoteCharacteristic::readValue(time_t\*, bool)
|
`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
|
||||||
NimBLERemoteDescriptor::readValue(bool)
|
`NimBLERemoteDescriptor::readValue(bool)`
|
||||||
|
|
||||||
Have been added as templates to allow reading the values as any specified type.
|
Have been added as templates to allow reading the values as any specified type.
|
||||||
|
|
||||||
|
@ -73,14 +73,14 @@ struct my_struct{
|
||||||
```
|
```
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
NimBLERemoteCharacteristic::registerForNotify
|
`NimBLERemoteCharacteristic::registerForNotify`
|
||||||
Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is recieved.
|
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.
|
`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
|
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.
|
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.
|
the time the last value was recieved.
|
||||||
|
|
||||||
> NimBLEClient::getService
|
> 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.
|
These changes allow more control for the user to manage the resources used for the attributes.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
NimBLEClient::connect() can now be called without an address or advertised device parameter. This will connect to the
|
`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().
|
device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
|
||||||
|
|
||||||
# General
|
# General
|
||||||
To reduce resource use all instances of std::map have been replaced with std::vector.
|
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.
|
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`.
|
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.
|
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/>
|
<br/>
|
||||||
|
|
||||||
# General Information
|
# General Information {#general-information}
|
||||||
|
|
||||||
### Header Files
|
### Header Files
|
||||||
All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
|
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.
|
These macros are used the same way as the `ESP_LOGx` macros.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
@ -25,7 +35,7 @@ this means **no class names need to be changed in existing code** and makes migr
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### BLE Addresses
|
### 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.
|
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).
|
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.
|
As this paramameter is optional no changes to existing code are needed, it is mentioned here for information.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# Server API
|
## Server API {#server-api}
|
||||||
Creating a `BLEServer` instance is the same as original, no changes required.
|
Creating a `BLEServer` instance is the same as original, no changes required.
|
||||||
For example `BLEDevice::createServer()` will work just as it did before.
|
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.
|
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### Services
|
### Services {#services}
|
||||||
Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
|
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.
|
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.
|
`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`.
|
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.
|
**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### Descriptors
|
### Descriptors {descriptors}
|
||||||
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
The previous method `BLECharacteristic::addDescriptor()` has been removed.
|
||||||
|
|
||||||
Descriptors are now created using the `NimBLECharacteristic::createDescriptor` method.
|
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
|
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.
|
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/>
|
<br/>
|
||||||
|
|
||||||
# Client API
|
## Client API {#client-api}
|
||||||
|
|
||||||
Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
|
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.
|
to replace the the removed automatic functionality.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### Remote Services
|
### Remote Services {#remote-services}
|
||||||
`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
|
`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
|
||||||
|
|
||||||
> BLERemoteService::getCharacteristicsByHandle
|
> BLERemoteService::getCharacteristicsByHandle
|
||||||
|
|
||||||
This method has been removed.
|
This method has been removed.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
|
> `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
|
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).
|
the currently known database returned (false : default).
|
||||||
Also now returns a pointer to `std::vector` instead of `std::map`.
|
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### Remote Characteristics
|
### Remote Characteristics{#remote-characteristics}
|
||||||
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
|
`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
|
||||||
|
|
||||||
> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
|
> `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();
|
uint8_t *val = (uint8_t*)pChr->readValue().data();
|
||||||
```
|
```
|
||||||
|
Alternatively use the `readValue` template:
|
||||||
|
```
|
||||||
|
my_struct_t myStruct = pChr->readValue<my_struct_t>();
|
||||||
|
```
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
|
> `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`.
|
Also now returns a pointer to `std::vector` instead of `std::map`.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
### Client Security
|
### Client Security {#client-security}
|
||||||
The client will automatically initiate security when the peripheral responds that it's required.
|
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.
|
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
# Security API
|
## Security API {#security-api}
|
||||||
Security operations have been moved to `BLEDevice` (`NimBLEDevice`).
|
Security operations have been moved to `BLEDevice` (`NimBLEDevice`).
|
||||||
|
|
||||||
Also security callback methods are now incorporated in the NimBLEServerCallbacks / NimBLEClientCallbacks classes.
|
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:
|
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
|
# Using
|
||||||
This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
|
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:
|
### Arduino specific:
|
||||||
See the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
See the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
|
||||||
|
|
Loading…
Reference in a new issue