diff --git a/README.md b/README.md index aa68fc8..ac8d946 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Call `NimBLEDevice::init("");` in `app_main`. # Using This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes. -See: [Breaking API Changes vs Original](docs/BREAKING_API_CHANGES.md) for details. +See: [The migration guide](docs/Migration_guide.md) for details. Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes. diff --git a/docs/BREAKING_API_CHANGES.md b/docs/BREAKING_API_CHANGES.md index cfbe929..cf99a7a 100644 --- a/docs/BREAKING_API_CHANGES.md +++ b/docs/BREAKING_API_CHANGES.md @@ -44,7 +44,7 @@ NimBLE automatically creates the 0x2902 descriptor if a characteristic has a not **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 desctiptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` methods (except 0x2904, see below). +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, diff --git a/docs/Improvements_and_updates.md b/docs/Improvements_and_updates.md index 702a30f..1709e10 100644 --- a/docs/Improvements_and_updates.md +++ b/docs/Improvements_and_updates.md @@ -83,8 +83,14 @@ get the last updated value any time. In addition NimBLERemoteCharacteristic::readValue and NimBLERemoteCharacteristic::getValue take an optional timestamp parameter which will update it's value with the time the last value was recieved. -NimBLEClient::getService will now retrieve only the service specified and not the full database, this preserves resources -otherwise wasted retrieving and allocating attributes the user application is not interested in. +> 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.
NimBLEClient::connect() can now be called without an address or advertised device parameter. This will connect to the diff --git a/docs/Migration_guide.md b/docs/Migration_guide.md new file mode 100644 index 0000000..4221f38 --- /dev/null +++ b/docs/Migration_guide.md @@ -0,0 +1,303 @@ +# 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 some of the many that have been made, this is only a small overview 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) +
+ +# 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. +These macros are used the same way as the `ESP_LOGx` macros. +
+ +### Class Names +Class names remain the same as the original with the addition of "Nim" added to the beginning of the name. +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. +
+ +### 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. +
+ +# 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. +
+ +### 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 +`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 +
+ +#### 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 +
+ +**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 + ); +``` +
+ +`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe` which 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. +
+ +### 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. +
+ +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"); +``` +
+ +### Server Security +Security is set on the characteristic or descriptor properties by applying one of the following: +> NIMBLE_PROPERTY::READ_ENC +> NIMBLE_PROPERTY::READ_AUTHEN +> NIMBLE_PROPERTY::READ_AUTHOR +> NIMBLE_PROPERTY::WRITE_ENC +> NIMBLE_PROPERTY::WRITE_AUTHEN +> NIMBLE_PROPERTY::WRITE_AUTHOR + +When a peer wants to read or write a characteristic or descriptor with any of these properties applied +it will trigger the pairing process. By default the "just-works" pairing will be performed automatically. +This can be changed to use passkey authentication or numeric comparison. See [Security Differences](#security-differences) for details. +
+ +# Client API + +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. +
+ +> `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`. +
+ +**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. +
+ +### Remote Services +`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of: +> BLERemoteService::getCharacteristicsByHandle +This method has been removed. +
+ +> `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`. +
+ +### 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. +
+ +> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`) + +Is now **deprecated**. +> NimBLERemoteCharacteristic::subscribe +> NimBLERemoteCharacteristic::unsubscribe + +Are the new methods added to replace it. +
+ +> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`) +> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`) +> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`) +> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`) + +Are **deprecated** a template: NimBLERemoteCharacteristic::readValue(time_t\*, bool) has been added to replace them. +
+ +> BLERemoteCharacteristic::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(); +``` +
+ +> `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`. +
+ +### 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 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. + +The callback methods are: + +> bool onConfirmPIN(uint32_t pin); + +Receives the pin when using numeric comparison authentication, `return true;` to accept. +
+ +> uint32_t onPassKeyRequest(); + +For server callback; return the passkey expected from the client. +For client callback; return the passkey to send to the server. +
+ +> void onAuthenticationComplete(ble_gap_conn_desc\* desc); + +Authentication complete, success or failed information is in `desc`. +
+ +Security settings and IO capabilities are now set by the following methods of NimBLEDevice. +> NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) +> NimBLEDevice::setSecurityAuth(uint8_t auth_req) + +Sets the authorization mode for this device. +
+ +> NimBLEDevice::setSecurityIOCap(uint8_t iocap) + +Sets the Input/Output capabilities of this device. +
+ +> NimBLEDevice::setSecurityInitKey(uint8_t init_key) + +If we are the initiator of the security procedure this sets the keys we will distribute. +
+ +> NimBLEDevice::setSecurityRespKey(uint8_t resp_key) + +Sets the keys we are willing to accept from the peer during pairing. +
+ diff --git a/docs/index.md b/docs/index.md index dcb4383..0cf96fa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -44,7 +44,7 @@ Call `NimBLEDevice::init("");` in `app_main`. # Using This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes. -See: [Breaking API Changes vs Original](docs/BREAKING_API_CHANGES.md) for details. +See: [The migration guide](docs/Migration_guide.md) for details. Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes.