Open
Description
Operating System
Windows 10
IDE version
arduino 2.3.2
Board
adafruit feather nrf52832
BSP version
1.6.0
Sketch
#include <bluefruit.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
using namespace Adafruit_LittleFS_Namespace;
#define KEY_FILE_PATH "/pairing_info.txt"
#define MAX_REMEMBERED_DEVICES 10
struct pairing {
uint8_t connect;
ble_gap_addr_t addr[MAX_REMEMBERED_DEVICES];
uint8_t numDevices;
};
pairing pairingInfo;
File settingsFile(InternalFS);
#include <Adafruit_TinyUSB.h>
// Use built-in buttons if available, else use A0, A1
#define BUTTON_YES 3
#define BUTTON_NO 4
// Circuit Play Bluefruit has button active state = high
uint32_t const button_active_state = LOW;
// BLE Service
BLEUart bleuart; // uart over ble
// Array to store addresses of the last connected smartphones
ble_gap_addr_t lastConnectedAddr[MAX_REMEMBERED_DEVICES];
void setup() {
// Other setup routines remain the same
Serial.begin(115200);
Serial.println("Bluefruit52 Pairing Display Example");
Serial.println("-----------------------------------\n");
// pull high for active low, or pull low for active high
pinMode(BUTTON_YES, INPUT_PULLDOWN);
pinMode(BUTTON_NO, INPUT_PULLDOWN);
// Setup the BLE LED to be enabled on CONNECT
// Note: This is actually the default behavior, but provided
// here in case you want to control this LED manually via PIN 19
Bluefruit.autoConnLed(true);
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.begin();
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
Bluefruit.Security.setIOCaps(false, true, false); // display = true, yes/no = true, keyboard = false
Bluefruit.Security.setPairPasskeyCallback(pairing_passkey_callback);
Bluefruit.Security.setPairCompleteCallback(pairing_complete_callback);
Bluefruit.Security.setSecuredCallback(connection_secured_callback);
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
bleuart.setPermission(SECMODE_ENC_NO_MITM, SECMODE_ENC_NO_MITM);
bleuart.begin();
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
Serial.println("Your phone should pop-up PIN input");
Serial.println("Once connected, enter character(s) that you wish to send");
startAdv();
InternalFS.begin();
if (digitalRead(BUTTON_NO) == HIGH) {
Serial.print("Formating ... ");
delay(1); // for message appear on monitor
// Format
InternalFS.format();
Serial.println("Done");
delay(10);
}
loadPairing();
}
bool loadPairing() {
Serial.println("loadPairing");
settingsFile = InternalFS.open(KEY_FILE_PATH, FILE_O_READ);
if (!settingsFile) {
Serial.println("Settings file not found.");
return false;
}
if (settingsFile.read((uint8_t *)&pairingInfo, sizeof(pairingInfo)) != sizeof(pairingInfo)) {
Serial.println("Error reading settings.");
settingsFile.close();
return false;
}
settingsFile.close();
// 읽은 내용 출력
Serial.println("Loaded pairing information:");
Serial.print("connect: ");
Serial.println(pairingInfo.connect);
Serial.print("Number of devices: ");
Serial.println(pairingInfo.numDevices);
for (int i = 0; i < pairingInfo.numDevices; ++i) {
Serial.print("Device ");
Serial.print(i + 1);
Serial.print(": ");
for (int j = 0; j < sizeof(ble_gap_addr_t); ++j) {
Serial.print(pairingInfo.addr[i].addr[j], HEX);
Serial.print(" ");
}
Serial.println();
}
return true;
}
void savePairing() {
Serial.println("savePairing");
settingsFile = InternalFS.open(KEY_FILE_PATH, FILE_O_WRITE);
if (!settingsFile) {
Serial.println("Failed to open settings file for writing.");
return;
}
if (settingsFile.write((uint8_t *)&pairingInfo, sizeof(pairingInfo)) != sizeof(pairingInfo)) {
Serial.println("Error writing settings.");
settingsFile.close();
return;
}
settingsFile.close();
Serial.println("Settings saved successfully.");
}
// Other callback functions remain the same
void startAdv(void) {
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addService(bleuart);
Bluefruit.ScanResponse.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);
Bluefruit.Advertising.setFastTimeout(30);
Bluefruit.Advertising.start(0);
}
void loop() {
if (Serial.available() > 0) {
delay(2);
uint8_t buf[64];
int count = Serial.readBytes(buf, sizeof(buf));
bleuart.write(buf, count);
}
if (Bluefruit.connected() && bleuart.notifyEnabled() && bleuart.available() > 0) {
uint8_t ch;
ch = (uint8_t)bleuart.read();
Serial.write(ch);
}
}
void connect_callback(uint16_t conn_handle) {
BLEConnection *connection = Bluefruit.Connection(conn_handle);
char central_name[32] = { 0 };
connection->getPeerName(central_name, sizeof(central_name));
Serial.print("Connected to ");
Serial.println(central_name);
Serial.println("Please select the 'Neopixels' tab, click 'Connect' and have fun");
}
bool pairing_passkey_callback(uint16_t conn_handle, uint8_t const passkey[6], bool match_request) {
Serial.println("Pairing Passkey");
Serial.printf(" %.3s %.3s\n", passkey, passkey + 3);
bool accept_pairing = false;
Serial.println("Do you want to pair?");
Serial.printf("Press button <%u> to Accept, button <%u> to Decline\n", BUTTON_YES, BUTTON_NO);
uint32_t start_time = millis();
while (millis() < start_time + 30000) {
if (digitalRead(BUTTON_YES) == HIGH) {
accept_pairing = true;
break;
}
if (digitalRead(BUTTON_NO) == HIGH) {
accept_pairing = false;
break;
}
if (!Bluefruit.connected(conn_handle)) break;
}
if (accept_pairing) {
Serial.println("Accepted");
} else {
Serial.println("Declined");
}
return accept_pairing;
}
void pairing_complete_callback(uint16_t conn_handle, uint8_t auth_status) {
if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
Serial.println("Succeeded");
} else {
Serial.println("Failed");
}
}
void connection_secured_callback(uint16_t conn_handle) {
Serial.println("Secured");
BLEConnection *connection = Bluefruit.Connection(conn_handle);
ble_gap_addr_t peer_addr = connection->getPeerAddr();
// 연결된 스마트폰 주소를 기존에 저장된 주소와 비교하여 페어링 여부를 결정합니다.
bool is_paired = false;
for (int i = 0; i < pairingInfo.numDevices; ++i) {
if (memcmp(&peer_addr, &pairingInfo.addr[i], sizeof(ble_gap_addr_t)) == 0) {
Serial.println("Connected to a previously paired smartphone. Skipping pairing.");
is_paired = true;
break;
}
}
// 페어링 되지 않은 스마트폰과의 연결이라면 페어링을 시작합니다.
if (!is_paired) {
// 페어링을 시작하기 전에 lastConnectedAddr 배열에 주소를 추가하고, 필요한 경우 페어링 정보를 저장합니다.
if (pairingInfo.numDevices < MAX_REMEMBERED_DEVICES) {
memcpy(&pairingInfo.addr[pairingInfo.numDevices], &peer_addr, sizeof(ble_gap_addr_t));
pairingInfo.numDevices++;
savePairing();
}
Serial.println("Connected to a new device. Initiating pairing...");
}
}
void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
(void)conn_handle;
(void)reason;
Serial.println();
Serial.print("Disconnected, reason = 0x");
Serial.println(reason, HEX);
}
What happened ?
Bluefruit.Security.setIOCaps(false, true, false); // display = true, yes/no = true, keyboard = false
In this code setup, the button that pairs with the physical button is known as the button.
However, a button appears in the application and is registered immediately upon registration.
When attempting to connect, I would like to pair and connect using a physical button.
When pairing, both display mode and keyboard mode work well.
It's not just the button part.
It's not just the button part. Is this a bug? Or am I doing something wrong?
Thank you for your great advice.
How to reproduce ?
Just upload the code and connect via Bluetooth using the Bluefruit_LE_Connect_Android_V2-master app.
Debug Log
No response
Screenshots
No response