77#include < BLE2902.h>
88#include < semaphore>
99
10+ #include " Remote.h"
11+
1012#define NORDIC_UART_SERVICE_UUID " 6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
1113#define NORDIC_UART_CHARACTERISTIC_UUID_RX " 6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
1214#define NORDIC_UART_CHARACTERISTIC_UUID_TX " 6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
1315
14- class NordicUART : public BLEServerCallbacks , public BLECharacteristicCallbacks {
16+ class NordicUART : public Stream , public BLEServerCallbacks , public BLECharacteristicCallbacks {
1517private:
1618 // BLE components
1719 BLEServer* pServer;
@@ -53,7 +55,7 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
5355 pServer->getAdvertising ()->addServiceUUID (NORDIC_UART_SERVICE_UUID);
5456 pService = pServer->createService (NORDIC_UART_SERVICE_UUID);
5557 pTxCharacteristic = pService->createCharacteristic (NORDIC_UART_CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
56- pTxCharacteristic->setCallbacks (this ); // onSubscribe
58+ pTxCharacteristic->setCallbacks (this ); // onSubscribe/onStatus
5759 pRxCharacteristic = pService->createCharacteristic (NORDIC_UART_CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
5860 pRxCharacteristic->setCallbacks (this ); // onWrite
5961 pService->start ();
@@ -109,11 +111,26 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
109111 }
110112 }
111113
114+ void onStatus (BLECharacteristic *pCharacteristic, Status s, uint32_t code)
115+ {
116+ // if(code) Serial.println(code);
117+ }
118+
112119 int available ()
113120 {
114121 return unreadByteCount;
115122 }
116123
124+ int peek ()
125+ {
126+ if (unreadByteCount > 0 )
127+ {
128+ size_t index = incomingPacket.length () - unreadByteCount;
129+ return incomingPacket[index];
130+ }
131+ return -1 ;
132+ }
133+
117134 int read ()
118135 {
119136 if (unreadByteCount > 0 )
@@ -128,22 +145,90 @@ class NordicUART : public BLEServerCallbacks, public BLECharacteristicCallbacks
128145 return -1 ;
129146 }
130147
131- size_t write (uint8_t *data, size_t size)
148+ // It is hard to achieve max throughput witout using delays...
149+ //
150+ // https://github.com/nkolban/esp32-snippets/issues/773
151+ // https://github.com/espressif/arduino-esp32/issues/8413
152+ // https://github.com/espressif/esp-idf/issues/9097
153+ // https://github.com/espressif/esp-idf/issues/16889
154+ // https://github.com/espressif/esp-nimble/issues/75
155+ // https://github.com/espressif/esp-nimble/issues/106
156+ // https://github.com/h2zero/esp-nimble-cpp/issues/347
157+ size_t write (const uint8_t *data, size_t size)
132158 {
133- if (pTxCharacteristic)
134- {
135- pTxCharacteristic->setValue (data, size);
136- pTxCharacteristic->notify ();
137- return size;
138- }
139- else
159+ if (pTxCharacteristic)
160+ {
161+ // Data is sent in chunks of MTU size to avoid data loss
162+ // as each chunk is notified separately
163+ size_t chunkSize = BLEDevice::getMTU ();
164+ size_t remainingByteCount = size;
165+ while (remainingByteCount >= chunkSize)
166+ {
167+ delay (20 );
168+ pTxCharacteristic->setValue (data, chunkSize);
169+ pTxCharacteristic->notify ();
170+ data += chunkSize;
171+ remainingByteCount -= chunkSize;
172+ }
173+ if (remainingByteCount > 0 )
174+ {
175+ delay (20 );
176+ pTxCharacteristic->setValue (data, remainingByteCount);
177+ pTxCharacteristic->notify ();
178+ }
179+ return size;
180+ }
181+ else
140182 return 0 ;
141183 }
142184
143185 size_t write (uint8_t byte)
144186 {
145187 return write (&byte, 1 );
146- };
188+ }
189+
190+ size_t print (std::string str)
191+ {
192+ return write ((const uint8_t *)str.data (), str.length ());
193+ }
194+
195+ size_t printf (const char *format, ...)
196+ {
197+ char dummy;
198+ va_list args;
199+ va_start (args, format);
200+ int requiredSize = vsnprintf (&dummy, 1 , format, args);
201+ va_end (args);
202+ if (requiredSize == 0 )
203+ {
204+ return write ((uint8_t *)&dummy, 1 );
205+ }
206+ else if (requiredSize > 0 )
207+ {
208+ char *buffer = (char *)malloc (requiredSize + 1 );
209+ if (buffer)
210+ {
211+ va_start (args, format);
212+ int result = vsnprintf (buffer, requiredSize + 1 , format, args);
213+ va_end (args);
214+ if ((result >= 0 ) && (result <= requiredSize))
215+ {
216+ size_t writtenBytesCount = write ((uint8_t *)buffer, result + 1 );
217+ free (buffer);
218+ return writtenBytesCount;
219+ }
220+ free (buffer);
221+ }
222+ }
223+ return 0 ;
224+ }
147225};
148226
227+ void bleInit (uint8_t bleMode);
228+ void bleStop ();
229+ int8_t getBleStatus ();
230+ void remoteBLETickTime (Stream* stream, RemoteState* state, uint8_t bleMode);
231+ int bleDoCommand (Stream* stream, RemoteState* state, uint8_t bleMode);
232+ extern NordicUART BLESerial;
233+
149234#endif
0 commit comments