2020-03-30 01:44:20 +02:00
|
|
|
/*
|
|
|
|
* NimBLEClient.h
|
|
|
|
*
|
|
|
|
* Created: on Jan 26 2020
|
|
|
|
* Author H2zero
|
2020-05-14 06:03:56 +02:00
|
|
|
*
|
2020-03-30 01:44:20 +02:00
|
|
|
* Originally:
|
|
|
|
* BLEClient.h
|
|
|
|
*
|
|
|
|
* Created on: Mar 22, 2017
|
|
|
|
* Author: kolban
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MAIN_NIMBLECLIENT_H_
|
|
|
|
#define MAIN_NIMBLECLIENT_H_
|
|
|
|
|
|
|
|
#include "sdkconfig.h"
|
2020-05-14 06:03:56 +02:00
|
|
|
#if defined(CONFIG_BT_ENABLED)
|
|
|
|
|
|
|
|
#include "nimconfig.h"
|
|
|
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
#include "NimBLEAddress.h"
|
2020-05-30 05:21:56 +02:00
|
|
|
#include "NimBLEUUID.h"
|
2020-06-22 06:07:01 +02:00
|
|
|
#include "NimBLEUtils.h"
|
Add connection info class and access methods to server and client.
This adds the ability to access information about the current connection.
A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information.
Example server use:
```
for(auto i=0; i<pServer->getConnectedCount();i++) {
NimBLEConnInfo connInfo = pServer->getPeerInfo(i);
printf("Connected client %d info:\n", i);
printf("Peer address: %s\n", connInfo.getAddress().toString().c_str());
printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str());
printf("Handle: %u\n", connInfo.getConnHandle());
printf("Interval: %u\n", connInfo.getConnInterval());
printf("Timeout: %u\n", connInfo.getConnTimeout());
printf("Latency: %u\n", connInfo.getConnLatency());
printf("MTU: %u\n", connInfo.getMTU());
printf("Master: %s\n", connInfo.isMaster()? "true":"false");
printf("Slave: %s\n", connInfo.isSlave()? "true":"false");
printf("Bonded: %s\n", connInfo.isBonded()? "true":"false");
printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false");
printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false");
printf("Encryption Key Size: %u\n", connInfo.getSecKeySize());
}
```
Example client use:
```
if (pClient->isConnected()) {
NimBLEConnInfo connInfo = pClient->getConnInfo();
printf("Connection info:\n");
printf("Peer address: %s\n", connInfo.getAddress().toString().c_str());
printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str());
printf("Handle: %u\n", connInfo.getConnHandle());
printf("Interval: %u\n", connInfo.getConnInterval());
printf("Timeout: %u\n", connInfo.getConnTimeout());
printf("Latency: %u\n", connInfo.getConnLatency());
printf("MTU: %u\n", connInfo.getMTU());
printf("Master: %s\n", connInfo.isMaster()? "true":"false");
printf("Slave: %s\n", connInfo.isSlave()? "true":"false");
printf("Bonded: %s\n", connInfo.isBonded()? "true":"false");
printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false");
printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false");
printf("Encryption Key Size: %u\n", connInfo.getSecKeySize());
}
```
2021-05-07 17:02:43 +02:00
|
|
|
#include "NimBLEConnInfo.h"
|
2020-03-30 01:44:20 +02:00
|
|
|
#include "NimBLEAdvertisedDevice.h"
|
|
|
|
#include "NimBLERemoteService.h"
|
|
|
|
|
2020-05-18 04:21:35 +02:00
|
|
|
#include <vector>
|
2020-03-30 01:44:20 +02:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
class NimBLERemoteService;
|
2020-09-16 06:09:30 +02:00
|
|
|
class NimBLERemoteCharacteristic;
|
2020-03-30 01:44:20 +02:00
|
|
|
class NimBLEClientCallbacks;
|
|
|
|
class NimBLEAdvertisedDevice;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A model of a %BLE client.
|
|
|
|
*/
|
|
|
|
class NimBLEClient {
|
|
|
|
public:
|
2020-07-30 18:09:27 +02:00
|
|
|
bool connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes = true);
|
|
|
|
bool connect(const NimBLEAddress &address, bool deleteAttibutes = true);
|
2020-08-18 23:02:57 +02:00
|
|
|
bool connect(bool deleteAttibutes = true);
|
2020-05-23 18:27:32 +02:00
|
|
|
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
|
|
|
NimBLEAddress getPeerAddress();
|
2020-07-30 18:04:34 +02:00
|
|
|
void setPeerAddress(const NimBLEAddress &address);
|
2020-05-23 18:27:32 +02:00
|
|
|
int getRssi();
|
|
|
|
std::vector<NimBLERemoteService*>* getServices(bool refresh = false);
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
std::vector<NimBLERemoteService*>::iterator begin();
|
|
|
|
std::vector<NimBLERemoteService*>::iterator end();
|
2020-05-23 18:27:32 +02:00
|
|
|
NimBLERemoteService* getService(const char* uuid);
|
|
|
|
NimBLERemoteService* getService(const NimBLEUUID &uuid);
|
2020-05-30 05:21:56 +02:00
|
|
|
void deleteServices();
|
|
|
|
size_t deleteService(const NimBLEUUID &uuid);
|
2020-05-23 18:27:32 +02:00
|
|
|
std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID);
|
|
|
|
bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
2020-12-20 17:57:26 +01:00
|
|
|
const std::string &value, bool response = false);
|
2020-09-16 06:09:30 +02:00
|
|
|
NimBLERemoteCharacteristic* getCharacteristic(const uint16_t handle);
|
2020-05-23 18:27:32 +02:00
|
|
|
bool isConnected();
|
|
|
|
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks,
|
|
|
|
bool deleteCallbacks = true);
|
|
|
|
std::string toString();
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
uint16_t getConnId();
|
|
|
|
uint16_t getMTU();
|
|
|
|
bool secureConnection();
|
|
|
|
void setConnectTimeout(uint8_t timeout);
|
|
|
|
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
2020-05-23 18:27:32 +02:00
|
|
|
uint16_t latency, uint16_t timeout,
|
|
|
|
uint16_t scanInterval=16, uint16_t scanWindow=16);
|
Add iterators to client remote attributes.
Add iterators for NimBLEScan: NimBLEadvertisedDevice, NimBLEClient: NimBLERemoteService, NimBLERemoteService: NimBLERemoteCharacteristic and NimBLERemoteCharacteristic: NimBLERemoteDescriptor
This is handy e.g. for showing every address of the advertised devices from a scan. To do so, first get a new scan and next:
```
for(auto pAdvertisedDevice: pBLEScan->getResults()) {
Serial.printf("Address is %s\n", std::string(pAdvertisedDevice->getAddress()).c_str());
}
```
Of course any other property of the advertised device can be shown (or looked up, if that is your use case)
Also this is handy e.g. for showing every UUID in a peripheral. To do so, first connect to a peripheral and next:
```
for(auto pService: *pClient) {
Serial.printf("Service UUID is %s\n", std::string(pService->getUUID()).c_str());
for(auto pCharacteristic: *pService) {
Serial.printf("Characteristic UUID is %s\n", std::string(pCharacteristic->getUUID()).c_str());
for(auto pDescriptor: *pCharacteristic) {
Serial.printf("Descriptor UUID is %s\n", std::string(pDescriptor->getUUID()).c_str());
}
}
}
```
Again of course any other property can be shown, or looked up.
2020-05-23 04:13:52 +02:00
|
|
|
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
2020-05-23 18:27:32 +02:00
|
|
|
uint16_t latency, uint16_t timeout);
|
|
|
|
void discoverAttributes();
|
Add connection info class and access methods to server and client.
This adds the ability to access information about the current connection.
A new class was created to wrap the struct ble_gap_conn_desc with methods to retrieve the connection information.
Example server use:
```
for(auto i=0; i<pServer->getConnectedCount();i++) {
NimBLEConnInfo connInfo = pServer->getPeerInfo(i);
printf("Connected client %d info:\n", i);
printf("Peer address: %s\n", connInfo.getAddress().toString().c_str());
printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str());
printf("Handle: %u\n", connInfo.getConnHandle());
printf("Interval: %u\n", connInfo.getConnInterval());
printf("Timeout: %u\n", connInfo.getConnTimeout());
printf("Latency: %u\n", connInfo.getConnLatency());
printf("MTU: %u\n", connInfo.getMTU());
printf("Master: %s\n", connInfo.isMaster()? "true":"false");
printf("Slave: %s\n", connInfo.isSlave()? "true":"false");
printf("Bonded: %s\n", connInfo.isBonded()? "true":"false");
printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false");
printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false");
printf("Encryption Key Size: %u\n", connInfo.getSecKeySize());
}
```
Example client use:
```
if (pClient->isConnected()) {
NimBLEConnInfo connInfo = pClient->getConnInfo();
printf("Connection info:\n");
printf("Peer address: %s\n", connInfo.getAddress().toString().c_str());
printf("Peer ID address: %s\n", connInfo.getIdAddress().toString().c_str());
printf("Handle: %u\n", connInfo.getConnHandle());
printf("Interval: %u\n", connInfo.getConnInterval());
printf("Timeout: %u\n", connInfo.getConnTimeout());
printf("Latency: %u\n", connInfo.getConnLatency());
printf("MTU: %u\n", connInfo.getMTU());
printf("Master: %s\n", connInfo.isMaster()? "true":"false");
printf("Slave: %s\n", connInfo.isSlave()? "true":"false");
printf("Bonded: %s\n", connInfo.isBonded()? "true":"false");
printf("Authenticated: %s\n", connInfo.isAuthenticated()? "true":"false");
printf("Encrypted: %s\n", connInfo.isEncrypted()? "true":"false");
printf("Encryption Key Size: %u\n", connInfo.getSecKeySize());
}
```
2021-05-07 17:02:43 +02:00
|
|
|
NimBLEConnInfo getConnInfo();
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2020-03-30 01:44:20 +02:00
|
|
|
private:
|
2020-07-30 20:31:17 +02:00
|
|
|
NimBLEClient(const NimBLEAddress &peerAddress);
|
2020-03-30 01:44:20 +02:00
|
|
|
~NimBLEClient();
|
|
|
|
|
2020-05-23 18:27:32 +02:00
|
|
|
friend class NimBLEDevice;
|
|
|
|
friend class NimBLERemoteService;
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-05-23 18:27:32 +02:00
|
|
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
|
|
|
static int serviceDiscoveredCB(uint16_t conn_handle,
|
|
|
|
const struct ble_gatt_error *error,
|
|
|
|
const struct ble_gatt_svc *service,
|
|
|
|
void *arg);
|
2021-01-12 21:50:08 +01:00
|
|
|
static void dcTimerCb(ble_npl_event *event);
|
2020-05-23 18:27:32 +02:00
|
|
|
bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr);
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-07-30 20:31:17 +02:00
|
|
|
NimBLEAddress m_peerAddress;
|
2020-05-23 18:27:32 +02:00
|
|
|
uint16_t m_conn_id;
|
2021-01-12 21:52:28 +01:00
|
|
|
bool m_connEstablished;
|
2020-06-22 06:07:01 +02:00
|
|
|
bool m_deleteCallbacks;
|
2020-05-23 18:27:32 +02:00
|
|
|
int32_t m_connectTimeout;
|
2020-06-22 06:07:01 +02:00
|
|
|
NimBLEClientCallbacks* m_pClientCallbacks;
|
2021-01-12 21:50:08 +01:00
|
|
|
ble_task_data_t* m_pTaskData;
|
|
|
|
ble_npl_callout m_dcTimer;
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-05-18 04:21:35 +02:00
|
|
|
std::vector<NimBLERemoteService*> m_servicesVector;
|
2020-05-14 06:03:56 +02:00
|
|
|
|
2020-04-14 03:13:51 +02:00
|
|
|
private:
|
|
|
|
friend class NimBLEClientCallbacks;
|
|
|
|
ble_gap_conn_params m_pConnParams;
|
2020-03-30 01:44:20 +02:00
|
|
|
|
2020-05-14 06:03:56 +02:00
|
|
|
}; // class NimBLEClient
|
2020-03-30 01:44:20 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callbacks associated with a %BLE client.
|
|
|
|
*/
|
|
|
|
class NimBLEClientCallbacks {
|
|
|
|
public:
|
|
|
|
virtual ~NimBLEClientCallbacks() {};
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called after client connects.
|
|
|
|
* @param [in] pClient A pointer to the calling client object.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual void onConnect(NimBLEClient* pClient);
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called when disconnected from the server.
|
|
|
|
* @param [in] pClient A pointer to the calling client object.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual void onDisconnect(NimBLEClient* pClient);
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called when server requests to update the connection parameters.
|
|
|
|
* @param [in] pClient A pointer to the calling client object.
|
|
|
|
* @param [in] params A pointer to the struct containing the connection parameters requested.
|
|
|
|
* @return True to accept the parmeters.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params);
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called when server requests a passkey for pairing.
|
|
|
|
* @return The passkey to be sent to the server.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual uint32_t onPassKeyRequest();
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/*virtual void onPassKeyNotify(uint32_t pass_key);
|
|
|
|
virtual bool onSecurityRequest();*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called when the pairing procedure is complete.
|
|
|
|
* @param [in] desc A pointer to the struct containing the connection information.\n
|
|
|
|
* This can be used to check the status of the connection encryption/pairing.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);
|
2020-07-09 03:27:26 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Called when using numeric comparision for pairing.
|
|
|
|
* @param [in] pin The pin to compare with the server.
|
|
|
|
* @return True to accept the pin.
|
|
|
|
*/
|
2020-04-14 03:13:51 +02:00
|
|
|
virtual bool onConfirmPIN(uint32_t pin);
|
2020-03-30 01:44:20 +02:00
|
|
|
};
|
|
|
|
|
2020-05-14 06:03:56 +02:00
|
|
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
2020-03-30 01:44:20 +02:00
|
|
|
#endif // CONFIG_BT_ENABLED
|
|
|
|
#endif /* MAIN_NIMBLECLIENT_H_ */
|