Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLEService does not survive BLE cycles #357

Open
OpenSrcerer opened this issue Mar 28, 2024 · 1 comment
Open

BLEService does not survive BLE cycles #357

OpenSrcerer opened this issue Mar 28, 2024 · 1 comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Comments

@OpenSrcerer
Copy link

OpenSrcerer commented Mar 28, 2024

Background Info

I am using a Nano 33 IoT 33. In this scenario, my Arduino plays a peripheral role.


⚠️ As you may know, this board does not allow the simultaneous usage of BLE and Wifi. Thus, I must toggle each service as I communicate with either.


What I refer to as "BLE cycle" is the process of using BLE.begin()... up until the BLE.end(), with all the setup and config functions in between.

Problem Description

During my first BLE cycle, everything goes as planned and I can communicate perfectly fine. However, upon ending BLE and doing other stuff, then coming back to it in another step, there will usually be one of these errors:

  • Option 1: The BLEService is totally missing. The advertised UUID may be there, but the service does not get exposed.
  • Option 2: The BLEService is there, but with no characteristics. Yes, I've made sure that I add the characteristics - the same code that adds them in the first time is triggered the second time.

Thus this completely interrupts my device setup flow and I have to resort to resetting the device. Thankfully I have a state machine implementation but I don't believe this is a solution.

What I've Tried

  1. Keeping the same characteristics + service throughout BLE cycles, but made sure to reset their values after every relaunch of BLE. In this approach I usually end up with Option 2.
  2. Creating new characteristics + service for each BLE cycle. This sometimes works, but I have not been able to keep it working consistently. See section below for more details.

Solution 2

In this solution, as described above, I opt to create a new characteristic and service for every BLE cycle. I have found that this sometimes works, specifically in these cases:

  • When you do not write to any characteristic.
  • When I write to the service through the LightBlue app by PunchThrough, it doesn't seem to mind multiple writes and restarts correctly.
  • When I write to the service through the app I have developed, which is using this plugin, it almost always breaks - UNLESS I only write to one characteristic. I'm not doing anything special there, but you can view it for context in the case that I've failed to realize any errors.

I'm all out of ideas at the moment. There's clearly something going wrong in the library level. I haven't been able to pinpoint exactly what causes this. Is there a way to enable some form of verbose logging in your library?

Minimal Reproducible Example

#include <ArduinoBLE.h>

char BLE_NAME[]         = "proto_01";

char SERVICE_UUID[]     = "11111111-1111-1111-1111-111111111110";
char SERIAL_UUID[]      = "11111111-1111-1111-1111-11111111111A";
char SSID_UUID[]        = "11111111-1111-1111-1111-11111111111B";
char PASS_UUID[]        = "11111111-1111-1111-1111-11111111111C";
char JWT_UUID[]         = "11111111-1111-1111-1111-11111111111D";

static const int MAX_JWT_CHARACTERISTIC_BUFFER_SIZE = 512;
static const int MAX_CHARACTERISTIC_BUFFER_SIZE = 64;

// ---- Advertisement ----
BLEService* bleService;
BLEStringCharacteristic* bleSerialChar;
BLEStringCharacteristic* bleSsidChar;
BLEStringCharacteristic* blePassChar;
BLEStringCharacteristic* bleJwtChar;

void newCharacteristics()
{
    bleService =        new BLEService(SERVICE_UUID);

    bleSerialChar =     new BLEStringCharacteristic(SERIAL_UUID, BLERead, MAX_CHARACTERISTIC_BUFFER_SIZE);
    bleSsidChar =       new BLEStringCharacteristic(SSID_UUID, BLEWrite, MAX_CHARACTERISTIC_BUFFER_SIZE);
    blePassChar =       new BLEStringCharacteristic(PASS_UUID, BLEWrite, MAX_CHARACTERISTIC_BUFFER_SIZE);
    bleJwtChar =        new BLEStringCharacteristic(JWT_UUID, BLEWrite, MAX_JWT_CHARACTERISTIC_BUFFER_SIZE);
}

void freeCharacteristics()
{
    bleService->clear();

    delete bleSerialChar;
    delete bleSsidChar;
    delete blePassChar;
    delete bleJwtChar;

    delete bleService;
}

void setup() {
  Serial.begin(9600);
  while (!Serial);
}

void loop() {
  setupBle();

  long startClock = millis(); // Sample time
  while (millis() - startClock < 60000)
  {
    BLE.poll();

    // Write to the SSID char (ends in B) to trigger the bug
    if (bleSsidChar->written())
    {
      Serial.println("Wrote SSID");
      break;
    }
  }

  endBle();
}

void setupBle() {
  newCharacteristics();

  // Add characteristics
  bleService->addCharacteristic(*bleSerialChar);
  bleService->addCharacteristic(*bleSsidChar);
  bleService->addCharacteristic(*blePassChar);
  bleService->addCharacteristic(*bleJwtChar);

  // Write the serial to the characteristic to be readable
  bleSerialChar->writeValue(String(4));

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");
    while (1);
  }

  BLE.setAdvertisedService(*bleService);
  BLE.addService(*bleService);

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");
}

void endBle() {
  BLE.central().disconnect();
  BLE.stopAdvertise();
  BLE.end();

  freeCharacteristics();
}
@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Mar 28, 2024
@Goliath86
Copy link

Goliath86 commented Apr 29, 2024

I've a similar problem with an Arduino OPTA. After some writing to a characteristic, in a complex sketch (the loop function does not call only the BLE.poll() but even other functions), I can't write anymore to it; the OPTA disconnect from the Bluetooth device and if I try to reconnect I can't see the characteristics anymore.

If I run the sketch of this open issue, after the first endBle(), the BLE.begin() function fail systematically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

No branches or pull requests

3 participants