esp-nimble-cpp/examples/basic/BLE_client/main/main.cpp

215 lines
8.2 KiB
C++
Raw Permalink Normal View History

2020-08-22 17:56:19 +02:00
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
* updated for NimBLE by H2zero
*/
2020-08-22 17:56:19 +02:00
/** NimBLE differences highlighted in comment blocks **/
/*******original********
#include "BLEDevice.h"
***********************/
#include "NimBLEDevice.h"
extern "C"{void app_main(void);}
2020-08-22 17:56:19 +02:00
// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static bool doConnect = false;
static bool connected = false;
static bool doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
printf("Notify callback for characteristic %s of data length %d data: %s\n",
pBLERemoteCharacteristic->getUUID().toString().c_str(),
length,
(char*)pData);
}
/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
2020-08-22 17:56:19 +02:00
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
/** onDisconnect now takes a reason parameter to indicate the reason for disconnection
void onDisconnect(BLEClient* pclient) { */
void onDisconnect(BLEClient* pclient, int reason) {
2020-08-22 17:56:19 +02:00
connected = false;
printf("onDisconnect");
}
/***************** New - Security handled here ********************
****** Note: these are the same return values as defaults ********/
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 22:47:36 +02:00
void onPassKeyEntry(NimBLEConnInfo& connInfo){
printf("Server Passkey Entry\n");
/** This should prompt the user to enter the passkey displayed
* on the peer device.
*/
NimBLEDevice::injectPassKey(connInfo, 123456);
};
void onConfirmPasskey(NimBLEConnInfo& connInfo, uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
/** Inject false if passkeys don't match. */
NimBLEDevice::injectConfirmPasskey(connInfo, true);
};
2020-08-22 17:56:19 +02:00
/** Pairing process complete, we can check the results in connInfo */
[BREAKING] Refactor attributes Refactor attributes to reduce code duplication and improve maintainability. * Add attribute base classes to provide common code. * Add const where possible to functions and parameters. * `NimBLECharacteristic::notify` no longer takes a `bool is_notification` parameter, instead `indicate()` should be called to send indications. * `NimBLECharacteristic::indicate` now takes the same parameters as `notify`. * `NimBLECharacteristicCallbacks` and `NimBLEDescriptorCallbacks` methods now take `const NimBLEConnInfo&` instead of non-const. * `NimBLECharacteristic::onNotify` callback removed as unnecessary, the library does not call notify without app input. * `NimBLERemoteCharacteristic::getRemoteService` now returns a `const NimBLERemoteService*` instead of non-const. * Add NimBLEUUID constructor that takes a reference to `ble_uuid_any_t`. * `NimBLERemoteService::getCharacteristics` now returns a `const std::vector<NimBLERemoteCharacteristic*>&` instead of non-const `std::vector<NimBLERemoteCharacteristic*>*` * `NimBLERemoteService::getValue` now returns `NimBLEAttValue` instead of `std::string` * `NimBLEService::getCharacteristics` now returns a `const std::vector<NimBLECharacteristic*>&` instead of a copy of std::vector<NimBLECharacteristic *>. * Remove const requirement for NimBLEConnInfo parameter in callbacks. Const is unnecessary as the data can't be changed by application code. * Change NimBLERemoteCharacteristic::getRemoteService to return const pointer.
2024-07-26 22:47:36 +02:00
void onAuthenticationComplete(NimBLEConnInfo& connInfo){
if(!connInfo.isEncrypted()) {
printf("Encrypt connection failed - disconnecting\n");
/** Find the client with the connection handle provided in desc */
NimBLEDevice::getClientByHandle(connInfo.getConnHandle())->disconnect();
return;
}
2020-08-22 17:56:19 +02:00
}
/*******************************************************************/
};
bool connectToServer() {
printf("Forming a connection to %s\n", myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
printf(" - Created client\n");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
printf(" - Connected to server\n");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
printf("Failed to find our service UUID: %s\n", serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
printf(" - Found our service\n");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
printf("Failed to find our characteristic UUID: %s\n", charUUID.toString().c_str());
pClient->disconnect();
return false;
}
printf(" - Found our characteristic\n");
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
printf("The characteristic value was: %s\n", value.c_str());
}
/** registerForNotify() has been removed and replaced with subscribe() / unsubscribe().
* Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=true.
* Unsubscribe parameter defaults are: response=true.
2020-08-22 17:56:19 +02:00
*/
if(pRemoteCharacteristic->canNotify()) {
//pRemoteCharacteristic->registerForNotify(notifyCallback);
pRemoteCharacteristic->subscribe(true, notifyCallback);
}
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
2020-08-22 17:56:19 +02:00
/*** Only a reference to the advertised device is passed now
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
2020-08-22 17:56:19 +02:00
void onResult(BLEAdvertisedDevice* advertisedDevice) {
printf("BLE Advertised Device found: %s\n", advertisedDevice->toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
/********************************************************************************
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
********************************************************************************/
if (advertisedDevice->haveServiceUUID() && advertisedDevice->isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
/*******************************************************************
myDevice = new BLEAdvertisedDevice(advertisedDevice);
*******************************************************************/
myDevice = advertisedDevice; /** Just save the reference now, no need to copy the object */
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
// This is the Arduino main loop function.
void connectTask (void * parameter){
for(;;) {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
2020-08-22 17:56:19 +02:00
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
printf("We are now connected to the BLE Server.\n");
} else {
printf("We have failed to connect to the server; there is nothin more we will do.\n");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
char buf[256];
snprintf(buf, 256, "Time since boot: %lu", (unsigned long)(esp_timer_get_time() / 1000000ULL));
printf("Setting new characteristic value to %s\n", buf);
2020-08-22 17:56:19 +02:00
// Set the characteristic's value to be the array of bytes that is actually a string.
/*** Note: write value now returns true if successful, false otherwise - try again or disconnect ***/
pRemoteCharacteristic->writeValue((uint8_t*)buf, strlen(buf), false);
}else if(doScan){
BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it
2020-08-22 17:56:19 +02:00
}
2020-08-22 17:56:19 +02:00
vTaskDelay(1000/portTICK_PERIOD_MS); // Delay a second between loops.
}
2020-08-22 17:56:19 +02:00
vTaskDelete(NULL);
} // End of loop
void app_main(void) {
printf("Starting BLE Client application...\n");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setScanCallbacks(new MyAdvertisedDeviceCallbacks());
2020-08-22 17:56:19 +02:00
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
2020-08-22 17:56:19 +02:00
xTaskCreate(connectTask, "connectTask", 5000, NULL, 1, NULL);
pBLEScan->start(5 * 1000, false);
2020-08-22 17:56:19 +02:00
} // End of setup.