Tasmota/libesp32/NimBLE-Arduino/API_DIFFERENCES.md

9.7 KiB

Server API differnces:

Characteristics:

When creating a characteristic the properties are now set with NIMBLE_PROPERTY::XXXX instead of BLECharacteristic::XXXX.

Previous:

BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE

Changed to:

NIMBLE_PROPERTY::READ | 
NIMBLE_PROPERTY::WRITE

The full list of properties:

NIMBLE_PROPERTY::READ
NIMBLE_PROPERTY::READ_ENC
NIMBLE_PROPERTY::READ_AUTHEN
NIMBLE_PROPERTY::READ_AUTHOR
NIMBLE_PROPERTY::WRITE
NIMBLE_PROPERTY::WRITE_NR
NIMBLE_PROPERTY::WRITE_ENC
NIMBLE_PROPERTY::WRITE_AUTHEN
NIMBLE_PROPERTY::WRITE_AUTHOR
NIMBLE_PROPERTY::BROADCAST
NIMBLE_PROPERTY::NOTIFY 
NIMBLE_PROPERTY::INDICATE

Descriptors:

Descriptors are now created using the NimBLEcharacteristic method createDescriptor().

The previous method addDescriptor() is now a private function in the library.

This was done because the NimBLE host automatically creates a 0x2902 descriptor if a characteristic has notify or indicate properties applied.
Due to this fact, this library also creates one automatically for your application.
The only reason to manually create this descriptor now is to assign callback functions.
If you do not require this functionality you can safely exclude the manual creation of that descriptor.

For any other descriptor, (except 0x2904, see below) it should now be created just as characteristics are
by invoking the NimBLECharacteristic::createDescriptor methods.
Which are defined as:

NimBLEDescriptor* createDescriptor(const char* uuid, 
						uint32_t properties = NIMBLE_PROPERTY::READ | 
											  NIMBLE_PROPERTY::WRITE,
                                     uint16_t max_len = 100);
                                     
NimBLEDescriptor* createDescriptor(NimBLEUUID uuid,
						uint32_t properties = NIMBLE_PROPERTY::READ | 
											  NIMBLE_PROPERTY::WRITE,
                                     uint16_t max_len = 100);
Example:
pDescriptor = pCharacteristic->createDescriptor("ABCD", 
                            NIMBLE_PROPERTY::READ | 
                            NIMBLE_PROPERTY::WRITE |
                            NIMBLE_PROPERTY::WRITE_ENC,
                            25);`

Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.

For the 0x2904 descriptor, there is a special class that is created when you call createDescriptor("2904").

The pointer returned is of the base class NimBLEDescriptor but the call will create the derived class of NimBLE2904 so you must cast the returned pointer to NimBLE2904* to access the specific class methods.

Example:
p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904");

Server Security:

Security is set on the characteristic or descriptor properties by applying one of the following:

NIMBLE_PROPERTY::READ_ENC
NIMBLE_PROPERTY::READ_AUTHEN
NIMBLE_PROPERTY::READ_AUTHOR
NIMBLE_PROPERTY::WRITE_ENC
NIMBLE_PROPERTY::WRITE_AUTHEN
NIMBLE_PROPERTY::WRITE_AUTHOR

When a peer wants to read or write a characteristic or descriptor with any of these properties applied
it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
This can be changed to use passkey authentication or numeric confirmation. See below for details.

Client API Differences:

The BLEAdvertisedDeviceCallbacks class onResult() method now receives a pointer to the
NimBLEAdvertisedDevice object instead of a copy.

NimBLEClient::connect() now takes an extra parameter to indicate if the client should download the services
database from the peripheral, default value is true.

Defined as:

bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true);

If set to false the client will use the services database it retrieved from the peripheral last time it connected.
This allows for faster connections and power saving if the devices just dropped connection and want to reconnect.

NimBLERemoteCharacteristic::writeValue();
NimBLERemoteCharacteristic::registerForNotify();

Now return true or false to indicate success or failure so you can choose to disconnect or try again.

NimBLEClient::getServices()   
NimBLERemoteService::getCharacteristics()

Now return a pointer to a std::vector of the respective object database instead of std::map.

NimBLERemoteService::getCharacteristicsByHandle() Has been removed from the API as it is no longer maintained in the library.

The last two above changes reduce the heap usage significantly with minimal application code adjustments.

UPDATED on June 21, 2020

NimBLEClient::getServices(bool refresh = false)   
NimBLERemoteService::getCharacteristics(bool refresh = false)   
NimBLERemoteCharacteristic::getDecriptors(bool refresh = false)

These methods now take an optional (bool) parameter.
If true it will clear the respective vector and retrieve all the respective attributes from the peripheral.
If false(default) it will return the respective vector empty or otherwise with the currently stored attributes.

Removed: the automatic discovery of all peripheral attributes as they consumed time and resources for data
the user may not be interested in.

Added: NimBLEClient::discoverAtrributes() for the user to discover all the peripheral attributes
to replace the the former functionality.

getService(NimBLEUUID)   
getCharacteristic(NimBLEUUID)   
getDescriptor(NimBLEUUID)

These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
the specified attribute from the peripheral.

These changes allow more control for the user to manage the resources used for the attributes.


Client Security:

The client will automatically initiate security when the peripheral responds that it's required.
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.

Security:

Security callback functions are now incorporated in the client/server Callbacks class.
However backward compatibility with the BLESecurity class is retained to minimize app code changes.

The relevant server callbacks are defined as:

bool    onConfirmPIN(uint32_t pin); // accept or reject the passkey
void    onAuthenticationComplete(ble_gap_conn_desc* desc); // auth complete - details in desc 
bool    onPassKeyNotify(uint32_t pass_key); // receive the passkey sent by the client, accept or reject

The relevant client callbacks are defined as:

bool     onConfirmPIN(uint32_t pin); // accept or reject the passkey
void     onAuthenticationComplete(ble_gap_conn_desc* desc); // auth complete - details in desc 
uint32_t onPassKeyRequest(); // return the passkey to send to the server

Security settings and IO capabilities are now set by the corresponding method of NimBLEDevice::.

static void             setSecurityAuth(bool bonding, bool mitm, bool sc);
static void             setSecurityAuth(uint8_t auth_req);
static void             setSecurityIOCap(uint8_t iocap);
static void             setSecurityInitKey(uint8_t init_key);
static void             setSecurityRespKey(uint8_t init_key);


/**
 * @brief Set the authorization mode for this device.
 * @param bonding, if true we allow bonding, false no bonding will be performed.
 * @param mitm, if true we are capable of man in the middle protection, false if not.
 * @param sc, if true we will perform secure connection pairing, false we will use legacy pairing.
 */   
void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) 



/**
 * @brief Set the authorization mode for this device.
 * @param A bitmap indicating what modes are supported.
 * The bits are defined as follows:
 ** 0x01 BLE_SM_PAIR_AUTHREQ_BOND                
 ** 0x04 BLE_SM_PAIR_AUTHREQ_MITM                
 ** 0x08 BLE_SM_PAIR_AUTHREQ_SC                  
 ** 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS  - not yet supported.         
 ** 0xe2 BLE_SM_PAIR_AUTHREQ_RESERVED  - for reference only.
 */ 
void NimBLEDevice::setSecurityAuth(uint8_t auth_req) 



/**
 * @brief Set the Input/Output capabilities of this device.
 * @param One of the following:
 ** 0x00 BLE_HS_IO_DISPLAY_ONLY         DisplayOnly IO capability
 ** 0x01 BLE_HS_IO_DISPLAY_YESNO        DisplayYesNo IO capability
 ** 0x02 BLE_HS_IO_KEYBOARD_ONLY        KeyboardOnly IO capability 
 ** 0x03 BLE_HS_IO_NO_INPUT_OUTPUT      NoInputNoOutput IO capability 
 ** 0x04 BLE_HS_IO_KEYBOARD_DISPLAY     KeyboardDisplay Only IO capability
 */
void NimBLEDevice::setSecurityIOCap(uint8_t iocap) 



/**
 * @brief If we are the initiator of the security procedure this sets the keys we will distribute.
 * @param A bitmap indicating which keys to distribute during pairing.
 * The bits are defined as follows:           
 ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC  - Distribute the encryption key.
 ** 0x02: BLE_SM_PAIR_KEY_DIST_ID   - Distribute the ID key (IRK).
 ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
 ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK
 */
void NimBLEDevice::setSecurityInitKey(uint8_t init_key) 


/**
 * @brief Set the keys we are willing to accept during pairing.
 * @param A bitmap indicating which keys to accept during pairing.
 * The bits are defined as follows:           
 ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC  -  Accept the encryption key.
 ** 0x02: BLE_SM_PAIR_KEY_DIST_ID   -  Accept the ID key (IRK).
 ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
 ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK
 */
void NimBLEDevice::setSecurityRespKey(uint8_t init_key) 

I'm sure there are more things I have forgotten but this is all the majors.
I will update this document as necessary.