taks / esp32-nimble

A wrapper for the ESP32 NimBLE Bluetooth stack.
Apache License 2.0
106 stars 32 forks source link

How to not stop advertising when a device is bonded? #70

Closed ChocolateLoverRaj closed 7 months ago

ChocolateLoverRaj commented 7 months ago

I am using a characteristic that needs authentication to read. Once I connect to it with one device, the advertising stops, making me unable to detect the ESP32-C3 from a different device. Is there a way to make the advertising not stop or to immediately start advertising again?

W (2928) esp32_nimble::server::ble_server: unhandled event: 18
I (15698) esp32_nimble::server::ble_server: AuthenticationComplete
W (15698) esp32_nimble::server::ble_server: unhandled event: 16
I (15698) NimBLE: GAP procedure initiated: stop advertising.
taks commented 7 months ago

Advertising can be restarted immediately by adding the following code.

  server.on_connect(|server, desc| {
    if server.connected_count() < (esp_idf_sys::CONFIG_BT_NIMBLE_MAX_CONNECTIONS as _) {
      ble_device.get_advertising().start().unwrap();
    }
  });
ChocolateLoverRaj commented 7 months ago

@taks I already have that in my code. What happens is if I enter the pin (for example 123456) in one device, it stops the advertisement, and on_connect is not called, which makes new devices not able to see the ESP32.

taks commented 7 months ago

I have verified and found the following.

It seems to be a problem with esp-idf itself.

ChocolateLoverRaj commented 7 months ago

@taks is the bug you found the underlying issue to this issue?

taks commented 7 months ago

Because the end of advertising cannot be detected, it cannot be immediately restart. It is possible to solve this problem forcibly by checking the state of advertising at regular intervals and restarting it if it has stopped.

ChocolateLoverRaj commented 7 months ago

Here is a reproducable example: https://github.com/ChocolateLoverRaj/esp32-nimble/blob/778adeb20f38de6b054a8ec0c82ef80588e0b0c8/examples/ble_secure_server.rs. Here is how to reproduce:

  1. Connect to the ESP32
  2. Read from the secure characteristic
  3. Enter the code 123456
  4. See the messages:
    I (54475) esp32_nimble::server::ble_server: AuthenticationComplete
    I (54485) NimBLE: GAP procedure initiated: stop advertising.

I think a simple fix would be to start advertising (or call a function which can start advertising itself) in the AuthenticationComplete function: https://github.com/taks/esp32-nimble/blob/02e47f71a2a96660563ea7fc67686deac488b35b/src/server/ble_server.rs#L310

taks commented 7 months ago

Advertising is stopped after AuthenticationComplete. Therefore, starting it in AuthenticationComplete did not work.

ChocolateLoverRaj commented 7 months ago

Is there a way of executing code after the message I (54485) NimBLE: GAP procedure initiated: stop advertising.? What about setting a delay after AuthenticationComplete and then advertising again?

ChocolateLoverRaj commented 7 months ago

I have found a workaround: Advertise on read. Here is a working example: https://github.com/ChocolateLoverRaj/esp32-nimble/blob/c23f18d0ccf4bd20fbed5b73cba07be0378f864e/examples/ble_secure_server.rs#L49-L56. This isn't an ideal solution because then every secure characteristic would have to manually implement on_read and on_write

taks commented 7 months ago

I found that the following code works well in my environment. Please check it.

  server.on_connect(|server, desc| {
    if server.connected_count() < (esp_idf_sys::CONFIG_BT_NIMBLE_MAX_CONNECTIONS as _) {
      ble_device.get_advertising().start().unwrap();
    }
  });

  advertising.on_complete(|_| {
    BLEDevice::take().get_advertising().start();
  });

advertising.on_complete is not yet released.

ChocolateLoverRaj commented 7 months ago

I checkout out the authentication-complete branch and it works.