esp32-snippets icon indicating copy to clipboard operation
esp32-snippets copied to clipboard

Connect requests ignored after last Disconnect unless Advertise is called again

Open mbratch opened this issue 4 years ago • 6 comments

I'm using an ESP32-DevKitC-32E platform.

My core code is as follows:

class TemperatureCallback: public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic *pCharacteristic) {
    uint16_t value;
    // Code goes here that obtains the new value to set
    pCharacteristic->setValue(value);
  }
};

class ServerCallback: public BLEServerCallbacks {
  void onDisconnect(BLEServer *pServer) {
    BLEDevice::startAdvertising();
  }
};

void setup() {
  BLEDevice::init("ESP32-BLE-1");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new ServerCallback);

  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ
                                       );

  pCharacteristic->setCallbacks(new TemperatureCallback);

  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();
}

Note that I am calling BLEDevice::startAdvertising(); on the disconnect callback. I need this in order for the server to continue responding to connection requests, even though the client already knows the address of the server and is using that from the original advertisement. If I do not re-advertise after disconnect, attempts by the client to connect are simply ignored. In addition, there is no ongoing advertising from the server, so other clients are not aware of the server.

The need to re-advertise doesn't seem like normal behavior. According to the documentation:

Of course a server doesn't need to advertise. If a client should otherwise be informed (or remember) the address of the BLE server, it can request a connection at any time.

mbratch avatar Apr 23 '21 11:04 mbratch

The need to re-advertise doesn't seem like normal behavior.

I think it is normal. It is up to you if you want or not to let other clients to connect, and it is how its achieved. No advertising == do not want to connect

chegewara avatar Apr 23 '21 11:04 chegewara

@chegewara According to the documentation in this repository:

Of course a server doesn't need to advertise. If a client should otherwise be informed (or remember) the address of the BLE server, it can request a connection at any time.

mbratch avatar Apr 23 '21 11:04 mbratch

@mbratch This probably is wrong info, maybe even i did write it when i knew less about ble. I still know too few to say i am expert, but here is answer that may help you: https://devzone.nordicsemi.com/f/nordic-q-a/8294/reconnecting-with-bonded-device-without-the-advertising-process

A central cannot connect to peripheral if it isn't advertising. The central wouldn't know when to send the connection request, and the peripheral wouldn't know when to listen for the connection request. If you want to reconnect because of an unintended disconnection, it shouldn't be necessary to advertise for very long, as long as the central is scanning at the same time. If you are talking about the general case when the peripheral doesn't know when the central will scan, you will need to make a choice between fast connection (shorter advertising interval, draining more current), slow connection (bigger advertising interval, draining less current), or something inbetween.

chegewara avatar Apr 23 '21 12:04 chegewara

@chegewara well, you still know a lot more than I do! :) Thanks for that additional documentation. I'll have a careful look at it. It seems, then, for a reliable connection sequence, the central should check that the peripheral is advertising before attempting the connection even if the central already knows the information for the peripheral. I've been just trying to understand the overall pattern for the use case in which a central wants intermittent (say, once per minute-ish) updates of a piece of data from the peripheral. And there may be a small number of different centrals requesting at different times. I think the pattern is connect, get data, disconnect at each time interval. I was looking at notify() but I assume a connection must be established to receive a notification, and I didn't want to leave the connection open all the time in this case (unless that's the normal thing to do: multiple centrals with open connections to the peripheral).

mbratch avatar Apr 23 '21 12:04 mbratch

I dont know what you are trying to achieve, but recently i had a chance to play with esp32 C3 a bit and BLE5. There is few cool new features, which helps with connectionless data exchange. So, for example, if you have peripheral that has some amount of data you would like to send to central every some time, you could use periodic advertising, which can advertise up to 251 bytes, i think, with period from 6ms to about 81sec. It is nice feature, because does not require connection and few centrals can listen for new data at the same time. The drawback is that BLE5 is not very popular yet.

chegewara avatar Apr 23 '21 13:04 chegewara

@chegewara thanks, that's good to know.

I'm just playing with the technology at the moment. I was constructing a simple scenario where lI have a temperature sensor and I want to read that temperature on an Android app. There may be multiple clients (apps) in the same area wanting that information. Ideally, I'd want the peripheral (temperature sensor) to emit the temperature every so often, and the apps to be able to pick it up. That's of course very broadly stated. In the BLE world I know that involves specific service with specific characteristic(s) pertaining to temperature sensing in thise case. I am still learning how this use case works in BLE. There seems to be more than one way to achieve it. I am not sure of the most "canonical" way. My attempt has been for the central to decide how frequently it wants to be updated so, on a timed basis, makes a connection, reads the data, then disconnects. It has a few non-critical flaws. For example, I seem to have only about 70% success rate at making a connection. Once the app has found the device from an initial scan, it just remembers its MAC address and reconnects using that.

mbratch avatar Apr 23 '21 16:04 mbratch