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
*/
2022-08-27 03:32:01 +02:00
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 ) ; }
2022-10-24 03:16:33 +02:00
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 ;
2024-11-18 17:37:46 +01:00
static const BLEAdvertisedDevice * myDevice ;
2020-08-22 17:56:19 +02:00
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. **
2022-08-27 03:32:01 +02:00
* * Remove as you see fit for your needs */
2020-08-22 17:56:19 +02:00
class MyClientCallback : public BLEClientCallbacks {
void onConnect ( BLEClient * pclient ) {
}
2022-08-27 03:51:19 +02:00
/** 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 * * * * * * * */
2024-07-26 22:47:36 +02:00
void onPassKeyEntry ( NimBLEConnInfo & connInfo ) {
2024-06-07 03:36:14 +02:00
printf ( " Server Passkey Entry \n " ) ;
/** This should prompt the user to enter the passkey displayed
* on the peer device .
*/
NimBLEDevice : : injectPassKey ( connInfo , 123456 ) ;
} ;
2024-11-03 02:00:07 +01:00
void onConfirmPasskey ( NimBLEConnInfo & connInfo , uint32_t pass_key ) {
2024-06-07 03:36:14 +02:00
printf ( " The passkey YES/NO number: % " PRIu32 " \n " , pass_key ) ;
/** Inject false if passkeys don't match. */
2024-09-29 23:59:42 +02:00
NimBLEDevice : : injectConfirmPasskey ( connInfo , true ) ;
2024-06-07 03:36:14 +02:00
} ;
2020-08-22 17:56:19 +02:00
2024-06-07 03:36:14 +02:00
/** Pairing process complete, we can check the results in connInfo */
2024-07-26 22:47:36 +02:00
void onAuthenticationComplete ( NimBLEConnInfo & connInfo ) {
2024-06-07 03:36:14 +02:00
if ( ! connInfo . isEncrypted ( ) ) {
printf ( " Encrypt connection failed - disconnecting \n " ) ;
/** Find the client with the connection handle provided in desc */
2024-09-29 23:59:42 +02:00
NimBLEDevice : : getClientByHandle ( connInfo . getConnHandle ( ) ) - > disconnect ( ) ;
2024-06-07 03:36:14 +02:00
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 ( ) ) ;
2022-10-24 03:16:33 +02:00
}
/** 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 .
*/
2022-08-27 03:32:01 +02:00
2020-08-22 17:56:19 +02:00
/*** Only a reference to the advertised device is passed now
2022-08-27 03:32:01 +02:00
void onResult ( BLEAdvertisedDevice advertisedDevice ) { * */
2024-11-18 17:37:46 +01:00
void onResult ( const BLEAdvertisedDevice * advertisedDevice ) {
2020-08-22 17:56:19 +02:00
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
2022-10-24 03:16:33 +02:00
// 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 ) ;
2022-10-24 03:16:33 +02:00
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 ) {
2022-08-27 03:32:01 +02:00
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
}
2022-10-24 03:16:33 +02:00
2020-08-22 17:56:19 +02:00
vTaskDelay ( 1000 / portTICK_PERIOD_MS ) ; // Delay a second between loops.
}
2022-10-24 03:16:33 +02:00
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 ( ) ;
2022-08-27 21:13:27 +02:00
pBLEScan - > setScanCallbacks ( new MyAdvertisedDeviceCallbacks ( ) ) ;
2020-08-22 17:56:19 +02:00
pBLEScan - > setInterval ( 1349 ) ;
pBLEScan - > setWindow ( 449 ) ;
pBLEScan - > setActiveScan ( true ) ;
2022-10-24 03:16:33 +02:00
2020-08-22 17:56:19 +02:00
xTaskCreate ( connectTask , " connectTask " , 5000 , NULL , 1 , NULL ) ;
2022-08-27 03:32:01 +02:00
pBLEScan - > start ( 5 * 1000 , false ) ;
2020-08-22 17:56:19 +02:00
} // End of setup.