11#include < NimBLEDevice.h>
2+ #include < esp_hpl.hpp>
3+ #include < esp_timer.h>
24
3- // See the following for generating UUIDs:
4- // https://www.uuidgenerator.net/
5-
6- // The remote service we wish to connect to.
7- static BLEUUID serviceUUID (" dcbc7255-1e9e-49a0-a360-b0430b6c6905" );
8- // The characteristic of the remote service we are interested in.
9- static BLEUUID charUUID (" 371a55c8-f251-4ad2-90b3-c7c195b049be" );
10-
11- #define L2CAP_CHANNEL 150
5+ #define L2CAP_PSM 192
126#define L2CAP_MTU 5000
7+ #define INITIAL_PAYLOAD_SIZE 64
8+ #define BLOCKS_BEFORE_DOUBLE 50
9+ #define MAX_PAYLOAD_SIZE 4900
1310
1411const BLEAdvertisedDevice* theDevice = NULL ;
1512BLEClient* theClient = NULL ;
1613BLEL2CAPChannel* theChannel = NULL ;
1714
1815size_t bytesSent = 0 ;
1916size_t bytesReceived = 0 ;
17+ size_t currentPayloadSize = INITIAL_PAYLOAD_SIZE;
18+ uint32_t blocksSent = 0 ;
19+ uint64_t startTime = 0 ;
20+
21+ // Heap monitoring
22+ size_t initialHeap = 0 ;
23+ size_t lastHeap = 0 ;
24+ size_t heapDecreaseCount = 0 ;
25+ const size_t HEAP_LEAK_THRESHOLD = 10 ; // Warn after 10 consecutive decreases
2026
2127class L2CAPChannelCallbacks : public BLEL2CAPChannelCallbacks {
2228
@@ -43,7 +49,7 @@ class MyClientCallbacks: public BLEClientCallbacks {
4349 printf (" GAP connected\n " );
4450 pClient->setDataLen (251 );
4551
46- theChannel = BLEL2CAPChannel::connect (pClient, L2CAP_CHANNEL , L2CAP_MTU, new L2CAPChannelCallbacks ());
52+ theChannel = BLEL2CAPChannel::connect (pClient, L2CAP_PSM , L2CAP_MTU, new L2CAPChannelCallbacks ());
4753 }
4854
4955 void onDisconnect (BLEClient* pClient, int reason) {
@@ -61,23 +67,72 @@ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
6167 if (theDevice) { return ; }
6268 printf (" BLE Advertised Device found: %s\n " , advertisedDevice->toString ().c_str ());
6369
64- if (!advertisedDevice->haveServiceUUID ()) { return ; }
65- if (!advertisedDevice->isAdvertisingService (serviceUUID)) { return ; }
70+ // Look for device named "l2cap"
71+ if (advertisedDevice->haveName () && advertisedDevice->getName () == " l2cap" ) {
72+ printf (" Found l2cap device!\n " );
73+ BLEDevice::getScan ()->stop ();
74+ theDevice = advertisedDevice;
75+ }
76+ }
77+ };
78+
79+ void statusTask (void *pvParameters) {
80+ while (true ) {
81+ vTaskDelay (1000 / portTICK_PERIOD_MS);
82+
83+ if (startTime > 0 && blocksSent > 0 ) {
84+ uint64_t currentTime = esp_timer_get_time ();
85+ double elapsedSeconds = (currentTime - startTime) / 1000000.0 ;
86+ double bytesPerSecond = 0.0 ;
87+ double kbPerSecond = 0.0 ;
88+ if (elapsedSeconds > 0.0 ) {
89+ bytesPerSecond = bytesSent / elapsedSeconds;
90+ kbPerSecond = bytesPerSecond / 1024.0 ;
91+ }
6692
67- printf (" Found the device we're interested in!\n " );
68- BLEDevice::getScan ()->stop ();
93+ // Heap monitoring
94+ size_t currentHeap = esp_get_free_heap_size ();
95+ size_t minHeap = esp_get_minimum_free_heap_size ();
6996
70- // Hand over the device to the other task
71- theDevice = advertisedDevice;
97+ // Track heap for leak detection
98+ if (initialHeap == 0 ) {
99+ initialHeap = currentHeap;
100+ lastHeap = currentHeap;
101+ }
102+
103+ // Check for consistent heap decrease
104+ if (currentHeap < lastHeap) {
105+ heapDecreaseCount++;
106+ if (heapDecreaseCount >= HEAP_LEAK_THRESHOLD) {
107+ printf (" \n ⚠️ WARNING: POSSIBLE MEMORY LEAK DETECTED! ⚠️\n " );
108+ printf (" Heap has decreased %zu times in a row\n " , heapDecreaseCount);
109+ printf (" Initial heap: %zu, Current heap: %zu, Lost: %zu bytes\n " ,
110+ initialHeap, currentHeap, initialHeap - currentHeap);
111+ }
112+ } else if (currentHeap >= lastHeap) {
113+ heapDecreaseCount = 0 ; // Reset counter if heap stabilizes or increases
114+ }
115+ lastHeap = currentHeap;
116+
117+ printf (" \n === STATUS UPDATE ===\n " );
118+ printf (" Blocks sent: %lu\n " , (unsigned long )blocksSent);
119+ printf (" Total bytes sent: %zu\n " , bytesSent);
120+ printf (" Current payload size: %zu bytes\n " , currentPayloadSize);
121+ printf (" Elapsed time: %.1f seconds\n " , elapsedSeconds);
122+ printf (" Bandwidth: %.2f KB/s (%.2f Mbps)\n " , kbPerSecond, (bytesPerSecond * 8 ) / 1000000.0 );
123+ printf (" Heap: %zu free (min: %zu), Used since start: %zu\n " ,
124+ currentHeap, minHeap, initialHeap > 0 ? initialHeap - currentHeap : 0 );
125+ printf (" ==================\n\n " );
126+ }
72127 }
73- };
128+ }
74129
75130void connectTask (void *pvParameters) {
76131
77132 uint8_t sequenceNumber = 0 ;
78133
79134 while (true ) {
80-
135+
81136 if (!theDevice) {
82137 vTaskDelay (1000 / portTICK_PERIOD_MS);
83138 continue ;
@@ -96,7 +151,7 @@ void connectTask(void *pvParameters) {
96151 break ;
97152 }
98153 vTaskDelay (2000 / portTICK_PERIOD_MS);
99- continue ;
154+ continue ;
100155 }
101156
102157 if (!theChannel) {
@@ -112,22 +167,58 @@ void connectTask(void *pvParameters) {
112167 }
113168
114169 while (theChannel->isConnected ()) {
170+ // Create framed packet: [seqno 8bit] [16bit payload length] [payload]
171+ std::vector<uint8_t > packet;
172+ packet.reserve (3 + currentPayloadSize);
173+
174+ // Add sequence number (8 bits)
175+ packet.push_back (sequenceNumber);
176+
177+ // Add payload length (16 bits, big endian - network byte order)
178+ uint16_t payloadLen = currentPayloadSize;
179+ packet.push_back ((payloadLen >> 8 ) & 0xFF ); // High byte first
180+ packet.push_back (payloadLen & 0xFF ); // Low byte second
115181
116- /*
117- static auto initialDelay = true;
118- if (initialDelay) {
119- printf("Waiting gracefully 3 seconds before sending data\n");
120- vTaskDelay(3000 / portTICK_PERIOD_MS);
121- initialDelay = false;
122- };
123- */
124- std::vector<uint8_t > data (5000 , sequenceNumber++);
125- if (theChannel->write (data)) {
126- bytesSent += data.size ();
182+ // Add payload
183+ for (size_t i = 0 ; i < currentPayloadSize; i++) {
184+ packet.push_back (i & 0xFF );
185+ }
186+
187+ if (theChannel->write (packet)) {
188+ if (startTime == 0 ) {
189+ startTime = esp_timer_get_time ();
190+ }
191+ bytesSent += packet.size ();
192+ blocksSent++;
193+
194+ // Print every block since we're sending slowly now
195+ printf (" Sent block %lu (seq=%d, payload=%zu bytes, frame_size=%zu)\n " ,
196+ (unsigned long )blocksSent, sequenceNumber, currentPayloadSize, packet.size ());
197+
198+ sequenceNumber++;
199+
200+ // After every 50 blocks, double payload size
201+ if (blocksSent % BLOCKS_BEFORE_DOUBLE == 0 ) {
202+ size_t newSize = currentPayloadSize * 2 ;
203+
204+ // Cap at maximum safe payload size
205+ if (newSize > MAX_PAYLOAD_SIZE) {
206+ if (currentPayloadSize < MAX_PAYLOAD_SIZE) {
207+ currentPayloadSize = MAX_PAYLOAD_SIZE;
208+ printf (" \n === Reached maximum payload size of %zu bytes after %lu blocks ===\n " , currentPayloadSize, (unsigned long )blocksSent);
209+ }
210+ // Already at max, don't increase further
211+ } else {
212+ currentPayloadSize = newSize;
213+ printf (" \n === Doubling payload size to %zu bytes after %lu blocks ===\n " , currentPayloadSize, (unsigned long )blocksSent);
214+ }
215+ }
127216 } else {
128217 printf (" failed to send!\n " );
129- abort ();
218+ abort ();
130219 }
220+
221+ // No delay - send as fast as possible
131222 }
132223
133224 vTaskDelay (1000 / portTICK_PERIOD_MS);
@@ -136,9 +227,13 @@ void connectTask(void *pvParameters) {
136227
137228extern " C"
138229void app_main (void ) {
230+ // Install high performance logging before any output
231+ esp_hpl::HighPerformanceLogger::init ();
232+
139233 printf (" Starting L2CAP client example\n " );
140234
141235 xTaskCreate (connectTask, " connectTask" , 5000 , NULL , 1 , NULL );
236+ xTaskCreate (statusTask, " statusTask" , 3000 , NULL , 1 , NULL );
142237
143238 BLEDevice::init (" L2CAP-Client" );
144239 BLEDevice::setMTU (BLE_ATT_MTU_MAX);
@@ -151,15 +246,8 @@ void app_main(void) {
151246 scan->setActiveScan (true );
152247 scan->start (25 * 1000 , false );
153248
154- int numberOfSeconds = 0 ;
155-
156- while (bytesSent == 0 ) {
157- vTaskDelay (10 / portTICK_PERIOD_MS);
158- }
159-
249+ // Main task just waits
160250 while (true ) {
161251 vTaskDelay (1000 / portTICK_PERIOD_MS);
162- int bytesSentPerSeconds = bytesSent / ++numberOfSeconds;
163- printf (" Bandwidth: %d b/sec = %d KB/sec\n " , bytesSentPerSeconds, bytesSentPerSeconds / 1024 );
164252 }
165253}
0 commit comments