NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

Client disconnection from server not detected

Open davidk88 opened this issue 8 months ago • 20 comments

Hello,

I'm would to update library to new refactored version.

I tried version 2.2.3 and If client is not cleanly disconnected from BLE server (goes out of range), then the onDisconnect callback is never called and getConnectedCount() still reporting that client is connected.

Currently I'm using library commit https://github.com/h2zero/NimBLE-Arduino/commit/b0ef2f50ac3430d3b13536873ce7cfe1e685902f and on this version there are no such problems (onDisconnect is triggered if device goes out of range).

Best regards

davidk88 avatar Mar 18 '25 10:03 davidk88

Hello,

I checked handleGapEvent and no (unhandled) event comes when client goes out of range. Also notify on characteristic is returning true, and result in onStatus callback is 0. So the problem is in underlying esp-nimble?

Is there any function to get nimble version?

Best regards

davidk88 avatar Mar 19 '25 08:03 davidk88

Thanks for pointing this out, I'm not sure yet why this occurs, it may be an upstream error and I will look into it, though it may be a controller error which is not open source so would require an update to the Arduino core.

There is no function to retrieve the version at this time.

h2zero avatar Mar 19 '25 20:03 h2zero

Hello guys. I conducted several tests that connected with this problem. My device has FreeRTOS tasks with a BLE-client and a BLE-server.

[ 61897][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -105
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 61994][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -76
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62093][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -108
[ 62181][D][ble_client.cpp:32] onScanEnd(): [BLE_CLIENT] onScanEnd
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62194][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -101
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62306][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -105
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62393][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -109
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62493][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -98
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62594][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -105
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62696][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -99
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62797][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -100
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62892][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -106
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 62993][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -104
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 63092][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -98
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 63196][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -99
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 63313][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -40
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX

Here I'm resetting ble-adapter on my pc

[ 63393][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -105
[ 63492][E][ble_server.cpp:193] BLETask(): [BLE_SERVER] E NimBLECharacteristic: << sendValue: failed to allocate mbuf. 
[ 63511][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -97
[ 63591][E][ble_server.cpp:193] BLETask(): [BLE_SERVER] E NimBLECharacteristic: << sendValue: failed to allocate mbuf. 
[ 63609][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3 rx: 3 | RSSi -97
[ 63694][E][ble_server.cpp:193] BLETask(): [BLE_SERVER] E NimBLECharacteristic: << sendValue: failed to allocate mbuf. 
[ 63714][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3 rx: 3 | RSSi -97
[ 63797][E][ble_server.cpp:193] BLETask(): [BLE_SERVER] E NimBLECharacteristic: << sendValue: failed to allocate mbuf. 

....(than massages repeats many times)...

After that I see:

[ 71806][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 71896][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 71996][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 72097][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 3  rx: 3  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX

Now I'm starting another ble-device (server) for my ble-client:

[ 74275][D][ble_client.cpp:248] HeartRateClientTask(): [BLE_CLIENT] Try to connect to HRM
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74315][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi 0
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74394][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -98
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74494][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -104
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74594][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -101
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74694][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74796][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -101
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74896][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -70
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 74995][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -97
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 75090][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -66
......
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 79793][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -66
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 79893][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -45
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 79995][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -35
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 80095][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -33
E NimBLEServer: >> handleGapEvent: BLE_GAP_EVENT_NOTIFY_TX
[ 80194][D][ble_server.cpp:210] BLETask(): [BLE_SERVER] ble_gap_read_le_phy tx: 1  rx: 1  |  RSSi -40
E NimBLEClient: Connect timeout - cancelling
E NimBLEClient: Connection failed; status=13 
[ 80285][E][ble_client.cpp:178] connectToHeartRateServer(): [BLE_CLIENT] Failed to connect to heart rate server

assert failed: heap_caps_free heap_caps.c:381 (heap != NULL && "free() target pointer is outside heap areas")
Core  0 register dump:
MEPC    : 0x40382fb6  RA      : 0x4038ac5a  SP      : 0x3fcc91a0  GP      : 0x3fc92800  
TP      : 0x3fcabb44  T0      : 0x37363534  T1      : 0x7271706f  T2      : 0x33323130  
S0/FP   : 0x3fcc933d  S1      : 0x0000005a  A0      : 0x3fcc9204  A1      : 0x3fc94f21  
A2      : 0x00000001  A3      : 0x00000029  A4      : 0x00000001  A5      : 0x3fc9f000  
A6      : 0x7a797877  A7      : 0x76757473  S2      : 0x3fcc91f8  S3      : 0x00000001  
S4      : 0x3fcc91f8  S5      : 0x4038346a  S6      : 0x04c91093  S7      : 0x00000000  
S8      : 0x3fc9e000  S9      : 0x3c0a0000  S10     : 0x3c0a0000  S11     : 0x3c0a01d0  
T3      : 0x6e6d6c6b  T4      : 0x6a696867  T5      : 0x66656463  T6      : 0x62613938  
MSTATUS : 0x00001801  MTVEC   : 0x40380001  MCAUSE  : 0x00000007  MTVAL   : 0x00000000  
MHARTID : 0x00000000  

As you can see, here another device-server begins to be perceived by the main device as a client, which ultimately brings crash..

truefalsenone avatar Mar 26 '25 09:03 truefalsenone

Thank you @truefalsenone, this is quite the problem for sure. The crash appears to be caused by something that occurs after the connection fails, can you decode this and post back. Also some more details and simplified code example to allow me to reproduce this would be greatly appreciated.

h2zero avatar Mar 27 '25 23:03 h2zero

Hello,

I am facing the same issue when trying to make the connection between an Android phone (acting as central) and an Arduino C3 (acting as server) more robust.

My own findings:

  • when I turn my Android phone to Airplane mode while a subscription was active, the Arduino server triggers a onSubscribe(status:0) event, but no onDisconnect() event.

  • when moving "out of range", neither onSubscribe(status:0) nor onDisconnect() events are triggered

In either case, getConnectedCount()>0 reports that the client is connected (as per @davidk88), and the only way to restablish a connection seems to be a reboot of the Arduino.

To avoid implementing a heartbeat/watchdog mechanism, is there a way for the Arduino to poll/detect this "semi-disconnected" state so that it decides to reboot ?

Thank you

Jeronimo59 avatar Apr 10 '25 06:04 Jeronimo59

Thank you for the information @Jeronimo59, at this time I have not found any reasonable solution to this, nor have I been able to reproduce it. If you can enable debug logs and post the output here it may provide a clue.

h2zero avatar Apr 10 '25 15:04 h2zero

Hello,

Let me correct my statement wrt airplane mode: all is fine, it was a dumb mistake on my side ...

When it comes to "out of range", all is fine as long as Arduino server does not send characteristic notifications:

  • .onDisconnect() is invoked with reason 520 when Arduino is out of range (where my callback restarts advertising)
  • .onConnect() is invoked when it comes back in range

Here is the log:

EE8Device::onSubscribe() : status: 0
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent:
!!!!!!!!!!!!!!!!!!!! EE8Device::onDisconnect() : disconnected from 52:33:ae:14:b7:87 (reason:520) (0 connections)
D NimBLEAdvertising: >> Advertising start: duration=0, dirAddr=NULL
D NimBLEAdvertising: << Advertising start
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent:
***************** EE8Device::onConnect() : connected to 6d:27:2a:3e:cf:77
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=18, subscribed: true

EE8Device::onSubscribe() : status: 1
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
D NimBLEServer: << handleGapEvent

Now if I add a characteristic notification in the main loop (triggered by a timeout every second)

      if (pServer->getConnectedCount() > 0)
      {
         Serial.print("N");     // log that a notification is being sent
         pCharacteristic->setValue(timerValue); 
         pCharacteristic->notify();           
      } 

here is what I get:

***************** EE8Device::onConnect() : connected to 58:95:b6:72:5d:c5
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
ND NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
NNNNNNNNNND NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=18, subscribed: true

EE8Device::onSubscribe() : status: 1
D NimBLEServer: << handleGapEvent
ND NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLEServer: << handleGapEvent
ND NimBLEServer: Gatt Read event
[...]
D NimBLEServer: >> handleGapEvent:
D NimBLEServer: << handleGapEvent
ND NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLEServer: << handleGapEvent

Loss of connection is not detected on server/Arduino side (while it is detected on my Android phone/client), which means .onDisconnect() cannot restart advertising... which means my phone cannot reconnect.

Could it be that the periodic pCharacteristic->notify() calls (1 per second) fool the Arduino server, letting it to believe that the connection is still alive, although it is out of range from the Android client ?

Thank you.

Jeronimo59 avatar Apr 12 '25 06:04 Jeronimo59

Hello @h2zero,

Do you think my diagnostic could be right ? If you give me some pointer to how/where the loss of coverage is detected, I could do further testing, and look for a fix.

Thanks.

Jeronimo59 avatar Apr 22 '25 19:04 Jeronimo59

@Jeronimo59 It's an interesting thought, maybe the buffers are getting exhausted and preventing the disconnect event from being triggered. If instead you use the onStatus callback to send the notification you might be able to prove this theory.

h2zero avatar Apr 22 '25 19:04 h2zero

@Jeronimo59 It's an interesting thought, maybe the buffers are getting exhausted and preventing the disconnect event from being triggered. If instead you use the onStatus callback to send the notification you might be able to prove this theory.

Do you mean calling pServer->notify() from onStatus() callback instead of main loop() ? I will try that.

You certainly know better, but I thought that maybe there was a watchdog/timeout in nimbke server codethat would trigger the onDisconnect() in absence of network activity over a certain period, and that invocation of pServer->notify() would unwillingly reset that watchdog, hence preventing it to trigger when out of range...

Jeronimo59 avatar Apr 22 '25 20:04 Jeronimo59

Do you mean calling pServer->notify() from onStatus() callback instead of main loop() ?

Yes, or from main loop if you want and set a flag in onStatus to tell the loop it's safe to send.

There is a supervision timeout for connections but if the stack runs out of buffers it may not be able to send an event, though I don't think that is what's happening as they should not be related, but it's worth testing.

h2zero avatar Apr 22 '25 20:04 h2zero

I have this kind of logic implemented: notify then wait for onStatus. But onStatus is keep giving result 0 (success) (as mentioned in second post).

davidk88 avatar Apr 23 '25 08:04 davidk88

Hopefully this is resolved now in the master branch as I have updated the nimble core.

h2zero avatar Apr 23 '25 11:04 h2zero

I'm afraid not ... it still doesn't detect "out of range condition" when pServer->notify() is called repetitively either in main loop or within onStatus() callback.

Without those notifications and with additional "[OutOfRange]" logs added, I was able to track the disconnect eventing process back to ble_hs_event_rx_hci_ev() function being called with a BLE_HCI_EVCODE_DISCONN_CMP (=5) event . With notifications active, this function is not called (at least with BLE_HCI_EVCODE_DISCONN_CMP event), and none of my logs show up. So the issue must be upstream...

D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
.D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
.........
E [OutOfRange]: ble_hs_event_rx_hci_ev(hci_ev->opcode:BLE_HCI_EVCODE_DISCONN_CMP=5)
E [OutOfRange]: ble_hs_hci_evt_process(BLE_HCI_EVCODE_DISCONN_CMP ev->opcode:5)
E [OutOfRange]: ble_hs_hci_evt_dispatch_find(event_code:BLE_HCI_EVCODE_DISCONN_CMP=5)
E [OutOfRange]: ble_hs_hci_evt_disconn_complete()
E [OutOfRange]: ble_gap_rx_disconn_complete()
D NimBLEServer: >> handleGapEvent:
I NimBLEServer: subscribe event; attr_handle=18, subscribed: false

EE8Device::onSubscribe() : status: 0
ND NimBLEServer: << handleGapEvent
E [OutOfRange]: ble_gap_conn_broken() reason=520
D NimBLEServer: >> handleGapEvent: 
E [OutOfRange]: handleGapEvent() event:BLE_GAP_EVENT_DISCONNECT reason=Connection Timeout
EE8Device::onDisconnect() : disconnected from 4d:a9:62:e6:44:d1 (reason:520) (0 connections)

As a side comment, I had to modify line 317 in NimBLEAttValue.h to get your code to compile properly (I'm using Platform.io):

        if (std::is_convertible<NimBLEAttValue, T>::value) {
# ifdef JERONIMO
            return *(reinterpret_cast<const T*>(this));
# else
            return *this;
# endif
        } else {

I hope this helps...

Jeronimo59 avatar Apr 28 '25 17:04 Jeronimo59

Thanks @Jeronimo59 can you share your pio environment? Not sure why that change was needed to compile as it builds fine everywhere I've tried.

h2zero avatar Apr 28 '25 18:04 h2zero

Here is the error reported

In file included from lib/NimBLE-Arduino-master/src/NimBLERemoteValueAttribute.h:36,
                 from lib/NimBLE-Arduino-master/src/NimBLERemoteCharacteristic.h:24,
                 from lib/NimBLE-Arduino-master/src/NimBLEDevice.h:265,
                 from lib/EE8Device/ee8device.h:6,
                 from src/main.cpp:40:
lib/NimBLE-Arduino-master/src/NimBLEAttValue.h: In instantiation of 'T NimBLEAttValue::getValue(time_t*, bool) const [with T = unsigned char; time_t = long int]':
lib/NimBLE-Arduino-master/src/NimBLELocalValueAttribute.h:113:60:   required from 'T NimBLELocalValueAttribute::getValue(time_t*, bool) const [with T = unsigned char; time_t = long int]'
lib/EE8Device/ee8device.h:24:58:   required from here
lib/NimBLE-Arduino-master/src/NimBLEAttValue.h:320:21: error: invalid user-defined conversion from 'const NimBLEAttValue' to 'unsigned char' [-fpermissive]
             return *this;
                     ^~~~
lib/NimBLE-Arduino-master/src/NimBLEAttValue.h:342:5: note: candidate is: 'NimBLEAttValue::operator const uint8_t*() const' <near match>
     operator const uint8_t*() const { return m_attr_value; }
     ^~~~~~~~
lib/NimBLE-Arduino-master/src/NimBLEAttValue.h:342:5: note:   no known conversion from 'const uint8_t*' {aka 'const unsigned char*'} to 'unsigned char'

and here is my platformio.ini file (I added your library under myProject/lib/NimBLE-Arduino-Master, hence it does not show up in lib_deps):

[env:seeed_xiao_esp32c3]
platform = espressif32
board = seeed_xiao_esp32c3
framework = arduino
lib_deps = 
	olikraus/U8g2@^2.36.5
	symlink://../../Arduino/libraries/mp3_player_module_wire-main

build_flags = 
   -DCORE_DEBUG_LEVEL=4
   -DCONFIG_NIMBLE_CPP_LOG_LEVEL=4
   -DCONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT=true
   -DJH=true
   -I../include

monitor_speed = 9600

Jeronimo59 avatar Apr 28 '25 18:04 Jeronimo59

The error is because your code is not using a const uint8_t, emphasis on the const that's by design so that you can't change the internal data of the class. I suggest using the NimBLEAttValue class directly to access the data:

auto val = pChr->getValue();
printf("val[0] = %u\n", val[0]);

Looks like the disconnect event fix is in arduino core 3.2, you'll need to use pioarduino for that.

h2zero avatar Apr 28 '25 20:04 h2zero

I'm afraid these C++ subtleties go beyond my skills, so I'll "blindly" follow your advice ;-).

In terms of "Out of range" detection, I updated to arduino core 3.2, but no progress :-(.

Here is my platformio.ini

[env:seeed_xiao_esp32c3]
;platform = espressif32
platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip
board = seeed_xiao_esp32c3
framework = arduino
lib_deps = 
	olikraus/U8g2@^2.36.5
	symlink://../../Arduino/libraries/mp3_player_module_wire-main

build_flags = 
   -DCORE_DEBUG_LEVEL=2
   -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
   -DCONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT=true
   -DJH=true
   -I../include

And here's my build log:

Processing seeed_xiao_esp32c3 (platform: https://github.com/pioarduino/platform-espressif32/releases/download/54.03.20/platform-espressif32.zip; board: seeed_xiao_esp32c3; framework: arduino)
-------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/seeed_xiao_esp32c3.html
PLATFORM: Espressif 32 (54.3.20) > Seeed Studio XIAO ESP32C3
HARDWARE: ESP32C3 160MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-builtin, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 @ 3.2.0
 - framework-arduinoespressif32-libs @ 5.4.0+sha.2f7dcd862a 
 - tool-esptoolpy @ 4.8.9
 - tool-mklittlefs @ 3.2.0
 - tool-riscv32-esp-elf-gdb @ 14.2.0+20240403
 - tool-xtensa-esp-elf-gdb @ 14.2.0+20240403
 - toolchain-riscv32-esp @ 14.2.0+20241119
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 45 compatible libraries
Scanning dependencies...
Dependency Graph
|-- U8g2 @ 2.36.5
|-- mp3_player_module_wire @ 1.0.0
|-- EE8Device
|-- SPI @ 3.2.0
|-- Wire @ 3.2.0
Building in release mode
Retrieving maximum program size .pio\build\seeed_xiao_esp32c3\firmware.elf
Checking size .pio\build\seeed_xiao_esp32c3\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]   7.1% (used 23152 bytes from 327680 bytes)
Flash: [=====     ]  46.0% (used 602600 bytes from 1310720 bytes)
========================================== [SUCCESS] Took 40.70 seconds ==========================================
 

Jeronimo59 avatar Apr 29 '25 10:04 Jeronimo59

Hello @h2zero ,

Can you confirm my setup does use arduino core 3.2 that should have addressed the issue ? Any suggestion for further troubleshooting ?

Thanks.

Jeronimo59 avatar May 05 '25 15:05 Jeronimo59

Hi @Jeronimo59, yes the build log shows that it is on 3.2, I'm not sure what else can be done at this point.

h2zero avatar May 05 '25 17:05 h2zero