Skip to content

Commit

Permalink
track BLE devices with RPA
Browse files Browse the repository at this point in the history
  • Loading branch information
Staars committed Oct 15, 2024
1 parent 69f7f15 commit c6f876c
Show file tree
Hide file tree
Showing 47 changed files with 991 additions and 411 deletions.
2 changes: 2 additions & 0 deletions lib/libesp32_div/esp-nimble-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ idf_component_register(
"esp32c2"
"esp32c3"
"esp32c6"
"esp32h2"
INCLUDE_DIRS
"src"
SRCS
Expand Down Expand Up @@ -58,6 +59,7 @@ idf_component_register(
REQUIRES
bt
nvs_flash
driver
PRIV_REQUIRES
${ESP_NIMBLE_PRIV_REQUIRES}
)
Expand Down
13 changes: 10 additions & 3 deletions lib/libesp32_div/esp-nimble-cpp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ config NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
Enabling this option will display return code values as text
messages in the debug log. This will use approximately 8kB
of flash memory.

config NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
bool "Show NimBLE gap events as text in debug log."
default "n"
Expand All @@ -47,7 +47,7 @@ config NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
default "n"
help
Enabling this option will display advertisment types recieved
while scanning as text messages in the debug log.
while scanning as text messages in the debug log.
This will use approximately 250 bytes of flash memory.

config NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
Expand All @@ -68,5 +68,12 @@ config NIMBLE_CPP_ATT_VALUE_INIT_LENGTH
when the constructor is called. This is also the size used when a remote
characteristic or descriptor is constructed before a value is read/notifed.
Increasing this will reduce reallocations but increase memory footprint.


config NIMBLE_CPP_DEBUG_ASSERT_ENABLED
bool "Enable debug asserts."
default "n"
help
Enabling this option will add debug asserts to the NimBLE CPP library.
This will use approximately 1kB of flash memory.

endmenu
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ If false the service is only removed from visibility by clients. The pointers to
# Advertising
`NimBLEAdvertising::start`

Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
Now takes 2 optional parameters, the first is the duration to advertise for (in milliseconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).

This provides an opportunity to update the advertisement data if desired.

Expand Down
19 changes: 12 additions & 7 deletions lib/libesp32_div/esp-nimble-cpp/docs/Migration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data

> BLEAdvertising::start (NimBLEAdvertising::start)
Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
Now takes 2 optional parameters, the first is the duration to advertise for (in milliseconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
This provides an opportunity to update the advertisement data if desired.
<br/>

Expand Down Expand Up @@ -383,18 +383,23 @@ The security callback methods are now incorporated in the `NimBLEServerCallbacks

The callback methods are:

> `bool onConfirmPIN(uint32_t pin)`
> `bool onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pin)`
Receives the pin when using numeric comparison authentication, `return true;` to accept.
Receives the pin when using numeric comparison authentication.
Call `NimBLEDevice::injectConfirmPIN(connInfo, true);` to accept or `NimBLEDevice::injectConfirmPIN(connInfo, false);` to reject.
<br/>

> `uint32_t onPassKeyRequest()`
> `void onPassKeyEntry(const NimBLEConnInfo& connInfo)`
For server callback; return the passkey expected from the client.
For client callback; return the passkey to send to the server.
Client callback; client should respond with the passkey (pin) by calling `NimBLEDevice::injectPassKey(connInfo, 123456);`
<br/>

> `void onAuthenticationComplete(NimBLEConnInfo& connInfo)`
> `uint32_t onPassKeyDisplay()`
Server callback; should return the passkey (pin) expected from the client.
<br/>

> `void onAuthenticationComplete(const NimBLEConnInfo& connInfo)`
Authentication complete, success or failed information is available from the `NimBLEConnInfo` methods.
<br/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ class ClientCallbacks : public NimBLEClientCallbacks {

/********************* Security handled here **********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
printf("Client Passkey Request\n");
/** return the passkey to send to the server */
return 123456;
}
void onPassKeyEntry(const 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);
};

bool onConfirmPIN(uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
/** Return false if passkeys don't match. */
return true;
}
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
/** Inject false if passkeys don't match. */
NimBLEDevice::injectConfirmPIN(connInfo, true);
};

/** Pairing process complete, we can check the results in connInfo */
void onAuthenticationComplete(NimBLEConnInfo& connInfo){
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
if(!connInfo.isEncrypted()) {
printf("Encrypt connection failed - disconnecting\n");
/** Find the client with the connection handle provided in desc */
Expand Down Expand Up @@ -146,8 +148,8 @@ bool connectToServer() {
* Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 12 * 10ms = 120ms timeout
*/
pClient->setConnectionParams(6,6,0,15);
/** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
pClient->setConnectTimeout(5);
/** Set how long we are willing to wait for the connection to complete (milliseconds), default is 30000. */
pClient->setConnectTimeout(5 * 1000);


if (!pClient->connect(advDevice)) {
Expand Down Expand Up @@ -358,7 +360,7 @@ void app_main (void){
* but will use more energy from both devices
*/
pScan->setActiveScan(true);
/** Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
/** Start scanning for advertisers for the scan time specified (in milliseconds) 0 = forever
* Optional callback for when scanning stops.
*/
pScan->start(scanTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ class ServerCallbacks: public NimBLEServerCallbacks {

/********************* Security handled here **********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
printf("Server Passkey Request\n");
uint32_t onPassKeyDisplay(){
printf("Server Passkey Display\n");
/** This should return a random 6 digit number for security
* or make your own static passkey as done here.
*/
return 123456;
};

bool onConfirmPIN(uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
/** Return false if passkeys don't match. */
return true;
void onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
/** Inject false if passkeys don't match. */
NimBLEDevice::injectConfirmPIN(connInfo, true);
};

void onAuthenticationComplete(NimBLEConnInfo& connInfo){
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
/** Check that encryption was successful, if not we disconnect the client */
if(!connInfo.isEncrypted()) {
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void app_main (void) {
*/
pScan->setActiveScan(true);

/* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
/* Start scanning for advertisers for the scan time specified (in milliseconds) 0 = forever
* Optional callback for when scanning stops.
*/
pScan->start(scanTime);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +0,0 @@
/*
* NimBLE Scan active/passive switching demo
*
* Demonstrates the use of the scan callbacks while alternating between passive and active scanning.
*/

#include "NimBLEDevice.h"
int scanTime = 5 * 1000; // In milliseconds, 0 = scan forever
BLEScan* pBLEScan;

bool active = false;

class scanCallbacks: public NimBLEScanCallbacks {

void onDiscovered(NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Discovered Advertised Device: %s \n", advertisedDevice->toString().c_str());
}

void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf("Advertised Device Result: %s \n", advertisedDevice->toString().c_str());
}

void onScanEnd(NimBLEScanResults results){
Serial.println("Scan Ended");
active = !active;
pBLEScan->setActiveScan(active);
Serial.printf("scan start, active = %u\n", active);
pBLEScan->start(scanTime);
}
};



void setup() {
Serial.begin(115200);
Serial.println("Scanning...");

NimBLEDevice::init("");
pBLEScan = NimBLEDevice::getScan();
pBLEScan->setScanCallbacks(new scanCallbacks());
pBLEScan->setActiveScan(active);
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
pBLEScan->start(scanTime);
}

void loop() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(SUPPORTED_TARGETS esp32)
project(NimBLE_server_get_client_name)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS ".")

register_component()
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/** NimBLE_server_get_client_name
*
* Demonstrates 2 ways for the server to read the device name from the connected client.
*
* Created: on June 24 2024
* Author: H2zero
*
*/

#include <NimBLEDevice.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define ENC_CHARACTERISTIC_UUID "9551f35b-8d91-42e4-8f7e-1358dfe272dc"

NimBLEServer* pServer;

class ServerCallbacks : public NimBLEServerCallbacks {
// Same as before but now includes the name parameter
void onConnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, std::string& name) override {
printf("Client address: %s Name: %s\n", connInfo.getAddress().toString().c_str(), name.c_str());
}

// Same as before but now includes the name parameter
void onAuthenticationComplete(const NimBLEConnInfo& connInfo, const std::string& name) override {
if (!connInfo.isEncrypted()) {
NimBLEDevice::getServer()->disconnect(connInfo.getConnHandle());
printf("Encrypt connection failed - disconnecting client\n");
return;
}

printf("Encrypted Client address: %s Name: %s\n", connInfo.getAddress().toString().c_str(), name.c_str());
}
};

extern "C" void app_main(void) {
printf("Starting BLE Server!\n");

NimBLEDevice::init("Connect to me!");
NimBLEDevice::setSecurityAuth(true, false, true); // Enable bonding to see full name on phones.

pServer = NimBLEDevice::createServer();
NimBLEService* pService = pServer->createService(SERVICE_UUID);
NimBLECharacteristic* pCharacteristic =
pService->createCharacteristic(CHARACTERISTIC_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE);
pCharacteristic->setValue("Hello World says NimBLE!");

NimBLECharacteristic* pEncCharacteristic = pService->createCharacteristic(
ENC_CHARACTERISTIC_UUID,
(NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC));
pEncCharacteristic->setValue("Hello World says NimBLE Encrypted");

pService->start();

pServer->setCallbacks(new ServerCallbacks());
pServer->getPeerNameOnConnect(true); // Setting this will enable the onConnect callback that provides the name.

BLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);

pAdvertising->start();
printf("Advertising started, connect with your phone.\n");

while (true) {
auto clientCount = pServer->getConnectedCount();
if (clientCount) {
printf("Connected clients:\n");
for (auto i = 0; i < clientCount; ++i) {
NimBLEConnInfo peerInfo = pServer->getPeerInfo(i);
printf("Client address: %s Name: %s\n", peerInfo.getAddress().toString().c_str(),
// This function blocks until the name is retrieved, so cannot be used in callback functions.
pServer->getPeerName(peerInfo).c_str());

}
}

vTaskDelay(pdMS_TO_TICKS(10000));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,28 @@ class MyClientCallback : public BLEClientCallbacks {
}
/***************** New - Security handled here ********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
printf("Client PassKeyRequest\n");
return 123456;
}
bool onConfirmPIN(uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32"\n", pass_key);
return true;
}

void onAuthenticationComplete(BLEConnInfo& connInfo){
printf("Starting BLE work!\n");
void onPassKeyEntry(const 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 onConfirmPIN(const NimBLEConnInfo& connInfo, uint32_t pass_key){
printf("The passkey YES/NO number: %" PRIu32 "\n", pass_key);
/** Inject false if passkeys don't match. */
NimBLEDevice::injectConfirmPIN(connInfo, true);
};

/** Pairing process complete, we can check the results in connInfo */
void onAuthenticationComplete(const NimBLEConnInfo& connInfo){
if(!connInfo.isEncrypted()) {
printf("Encrypt connection failed - disconnecting\n");
/** Find the client with the connection handle provided in desc */
NimBLEDevice::getClientByID(connInfo.getConnHandle())->disconnect();
return;
}
}
/*******************************************************************/
};
Expand Down
Loading

0 comments on commit c6f876c

Please sign in to comment.