adafruit / Adafruit_nRF52_Arduino

Adafruit code for the Nordic nRF52 BLE SoC on Arduino
Other
598 stars 488 forks source link

Bluefruit.Security.setIOCaps(false, true, false); I would like to inquire regarding this. #815

Open gujakoo opened 3 months ago

gujakoo commented 3 months ago

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

gujakoo commented 3 months ago

I understand that you're facing an issue with pairing a physical button in your code setup. Despite the button appearing in the application and registering immediately upon registration, you want to pair it using the physical button during connection attempts. Pairing works fine when using display mode or keyboard mode, but the button part doesn't seem to work. You're asking whether this is a bug or if there's something wrong with your approach. You're also seeking advice regarding the Bluefruit.Security.setIOCaps(false, true, false) function.

To troubleshoot this, let's break down the situation:

Physical Button Pairing Issue: It seems like the problem lies in the pairing process using the physical button. This could be due to various reasons such as incorrect wiring, hardware compatibility issues, or code configuration.

Code Configuration: The function Bluefruit.Security.setIOCaps(false, true, false) is likely related to the input/output capabilities of your device. Setting it to (false, true, false) suggests that you're enabling keyboard-only mode. This might be causing the issue with the physical button pairing.

Troubleshooting Steps:

Double-check your wiring and ensure that the physical button is connected properly. Review the documentation of Bluefruit_LE_Connect_Android_V2-master to ensure that you're following the correct procedure for pairing physical buttons. Experiment with different configurations of Bluefruit.Security.setIOCaps() function to see if it resolves the issue. You might need to enable other capabilities besides just keyboard mode. Bug vs. Configuration Issue: It's hard to determine whether this is a bug or a configuration issue without more detailed information. Try reaching out to the developer community or the support resources provided by the manufacturer for assistance. They might have encountered similar issues and can offer specific guidance.

In summary, thoroughly review your hardware setup, code configuration, and documentation provided by Bluefruit_LE_Connect_Android_V2-master. Experiment with different configurations, and consider seeking assistance from the developer community or manufacturer support for further troubleshooting.