ArduinoDumbDisplay v0.9.9-r50
DumbDisplay Arduino Library -- https://github.com/trevorwslee/Arduino-DumbDisplay
 
Loading...
Searching...
No Matches
esp32bledumbdisplay.h
1//************************************************//
2//*** must define DD_4_ESP32 before includeing ***/
3//************************************************//
4
5#ifndef esp32bledumbdisplay_h
6#define esp32bledumbdisplay_h
7
8// after inclusion, can check DD_USING_WIFI to be sure WIFI is used
9#define DD_USING_LE
10
11// #ifndef DD_4_ESP32
12// #error DD_4_ESP32 need be defined in order to use DumbDisplay for ESP32 BLE
13// #else
14
15
16#ifndef ESP32
17 #error DDBLESerialIO is for ESP32
18#endif
19
20// #ifndef ESP32
21// #error DDBLESerialIO is for ESP32
22// #else
23
24#include "sdkconfig.h"
25
26#include <BLEDevice.h>
27#include <BLEServer.h>
28#include <BLEUtils.h>
29#include <BLE2902.h>
30#include "dumbdisplay.h"
31
32#define DD_SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
33#define DD_CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
34#define DD_CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
35
36#define DD_RECEIVE_BUFFER_SIZE 256
37#define DD_SEND_BUFFER_SIZE 20
38
39// using DD_BLE_NOTIFY is faster, but not as reliable
40// #define DD_BLE_NOTIFY
41
42//#define DD_DEBUG_BLE
43//#define DD_DEBUG_BLE_SEND
44//#define DD_DEBUG_BLE_RECEIVE
45
46
47
50 public:
51 /* ESP32 BLE IO mechanism */
52 /* - deviceName -- BLE device name */
53 /* - enableSerial: enable Serial as well or not (if enabled, connecting via USB will also work) */
54 /* - serialBaud: Serial baud rate (if enableSerial) */
55 DDBLESerialIO(const String& deviceName, bool enableSerial = false,
56 unsigned long serialBaud = DD_SERIAL_BAUD):
57 DDInputOutput(serialBaud, enableSerial, enableSerial) {
58 this->deviceName = deviceName;
59 this->initialized = false;
60 // if (!enableSerial) {
61 // Serial.begin(serialBaud);
62 // }
63 }
64 const char* getWhat() {
65 return "ESP32BLE";
66 }
67 bool available() {
68 return pCallbacks->available();
69 }
70 char read() {
71 return pCallbacks->read();
72 }
73 void print(const String &s) {
74 pCallbacks->print(s.c_str());
75 }
76 void print(const char *p) {
77 pCallbacks->print(p);
78 }
79 void write(uint8_t b) {
80 pCallbacks->write(b);
81 }
82 bool preConnect(bool firstCall) {
83#ifdef DD_DEBUG_BLE
84 if (!setupForSerial) {
85 Serial.begin(115200);
86 }
87#endif
88 DDInputOutput::preConnect(firstCall);
89 if (!initialized) {
90 initBLE();
91 } else {
92 if (!willUseSerial()) { // since 2024-08-13
93 if (firstCall) {
94 if (!Serial) Serial.begin(DD_SERIAL_BAUD);
95 }
96 Serial.println("ble address: " + address);
97 }
98// #ifdef DD_DEBUG_BLE
99// if (firstCall) {
100// Serial.println("FIRST preConnect() called, but already initialized");
101// } else {
102// Serial.println("preConnect() called, but already initialized");
103// }
104// #endif
105 if (pServerCallbacks->isDisconnected()) {
106 pServerCallbacks->restartAdvertising();
107 }
108 }
109 return true;
110 }
111 void flush() {
112 }
113 void validConnection() {
114 if (pServerCallbacks->isDisconnected()) {
115 delay(500); // give the bluetooth stack the chance to get things ready
116 pServerCallbacks->restartAdvertising();
117#ifdef DD_DEBUG_BLE
118 Serial.println("... connection lost ... waiting for re-connection ...");
119#endif
120 }
121 }
122 bool canConnectPassive() {
123 return true;
124 }
125 bool canUseBuffer() {
126 return false;
127 }
128 private:
129 class ServerCallbacks: public BLEServerCallbacks {
130 public:
131 ServerCallbacks(BLEServer* pServer) {
132 this->pServer = pServer;
133 this->connectionState = 0; // assume connecting
134 }
135 public:
136 void restartAdvertising() {
137 pServer->startAdvertising();
138 connectionState = 0;
139#ifdef DD_DEBUG_BLE
140 Serial.println("restarted advertising");
141#endif
142 }
143 bool isDisconnected() { return connectionState == -1; }
144 bool isConnected() { return connectionState == 1; }
145 bool isConnecting() { return connectionState == 0; }
146 public:
147 void onConnect(BLEServer* pServer) {
148 connectionState = 1;
149#ifdef DD_DEBUG_BLE
150 Serial.println("BLE connected");
151#endif
152 };
153 void onDisconnect(BLEServer* pServer) {
154 connectionState = -1;
155#ifdef DD_DEBUG_BLE
156 Serial.println("BLE disconnected");
157#endif
158 }
159 private:
160 BLEServer* pServer;
161 int connectionState;
162 };
163 class Callbacks: public BLECharacteristicCallbacks {
164 public:
165 Callbacks(BLECharacteristic *pTx, ServerCallbacks* pServerCallbacks) {
166 this->pTx = pTx;
167 this->pServerCallbacks = pServerCallbacks;
168 this->buffering = false;
169 this->bufferStart = 0;
170 this->bufferEnd = 0;
171#ifdef DD_SEND_BUFFER_SIZE
172 this->sendBufferSize = 0;
173#endif
174 }
175 public:
176#ifdef CONFIG_IDF_INIT_VERSION
177 void print(String s) {
178#else
179 void print(std::string s) {
180#endif
181#ifdef DD_SEND_BUFFER_SIZE
182 int len = s.length();
183 if ((len + sendBufferSize) > DD_SEND_BUFFER_SIZE) {
184 _flushSendBuffer();
185 if (len > DD_SEND_BUFFER_SIZE) {
186 _print(s.c_str());
187 return;
188 }
189 }
190 for (int i = 0; i < len; i++) {
191 sendBuffer[sendBufferSize++] = s[i];
192 }
193 if (sendBufferSize > 0 && sendBuffer[sendBufferSize - 1] == '\n') {
194 _flushSendBuffer();
195 }
196#else
197 _print(s.c_str());
198#endif
199 }
200 void write(uint8_t b) {
201 int s = b;
202 pTx->setValue(s);
203#ifdef DD_BLE_NOTIFY
204 pTx->notify();
205#else
206 pTx->indicate();
207#endif
208 }
209 bool available() {
210 while (true) {
211 if (!buffering) {
212 return bufferStart != bufferEnd;
213 }
214 yield();
215 }
216 }
217 char read() {
218 while (true) {
219 if (!buffering) {
220 char c = buffer[bufferStart];
221 if (++bufferStart >= DD_RECEIVE_BUFFER_SIZE) {
222 bufferStart = 0;
223 }
224 return c;
225 }
226 yield();
227 }
228 }
229 private:
230#ifdef DD_SEND_BUFFER_SIZE
231 void _flushSendBuffer() {
232 if (sendBufferSize > 0) {
233 sendBuffer[sendBufferSize] = 0;
234 _print(sendBuffer);
235 sendBufferSize = 0;
236 }
237 }
238#endif
239#ifdef CONFIG_IDF_INIT_VERSION
240 void _print(String s) {
241#else
242 void _print(std::string s) {
243#endif
244#if defined(DD_DEBUG_BLE_SEND)
245 if (pServerCallbacks->isConnected()) {
246 } else if (pServerCallbacks->isConnecting()) {
247 Serial.print("[connecting] ");
248 } else {
249 Serial.print("[not connected] ");
250 }
251 Serial.print("BLE sent ... [");
252 Serial.print(s.c_str());
253 Serial.println("]");
254#endif
255 int len = s.length();
256 while (len > 0) {
257 if (len <= 20) { // 20 is the BLE limit
258 pTx->setValue(s);
259#ifdef DD_BLE_NOTIFY
260 pTx->notify();
261#else
262 pTx->indicate();
263#endif
264 break;
265 } else {
266#ifdef CONFIG_IDF_INIT_VERSION
267 pTx->setValue(s.substring(0, 20));
268#else
269 pTx->setValue(s.substr(0, 20));
270#endif
271#ifdef DD_BLE_NOTIFY
272 pTx->notify();
273#else
274 pTx->indicate();
275#endif
276#ifdef CONFIG_IDF_INIT_VERSION
277 s = s.substring(20);
278#else
279 s = s.substr(20);
280#endif
281 len -= 20;
282 }
283 }
284 }
285 public:
286 void onWrite(BLECharacteristic *pCharacteristic) {
287 buffering = true;
288#ifdef CONFIG_IDF_INIT_VERSION
289 String rxValue = pCharacteristic->getValue();
290 int count = rxValue.length();
291#else
292 std::string rxValue = pCharacteristic->getValue();
293 int count = rxValue.size();
294#endif
295 for (int i = 0; i < count; i++) {
296 int nextBufferEnd = bufferEnd + 1;
297 if (nextBufferEnd >= DD_RECEIVE_BUFFER_SIZE) {
298 nextBufferEnd = 0;
299 }
300 if (nextBufferEnd == bufferStart) {
301 break;
302 }
303 buffer[bufferEnd] = rxValue[i];
304 bufferEnd = nextBufferEnd;
305 }
306#ifdef DD_DEBUG_BLE_RECEIVE
307 Serial.print("BLE received ... ");
308 Serial.print(count);
309 Serial.print(" ... [");
310 Serial.print(rxValue.c_str());
311 Serial.print("] ==> ");
312 Serial.print(bufferStart);
313 Serial.print('-');
314 Serial.print(bufferEnd);
315 Serial.print('/');
316 Serial.print(DD_RECEIVE_BUFFER_SIZE);
317 Serial.println();
318#endif
319 buffering = false;
320 }
321 private:
322 BLECharacteristic *pTx;
323 ServerCallbacks* pServerCallbacks;
324 volatile bool buffering;
325 uint8_t bufferStart;
326 uint8_t bufferEnd;
327 char buffer[DD_RECEIVE_BUFFER_SIZE];
328#ifdef DD_SEND_BUFFER_SIZE
329 uint8_t sendBufferSize;
330 char sendBuffer[DD_SEND_BUFFER_SIZE + 1];
331#endif
332 };
333 private:
334 void initBLE() {
335#ifdef DD_DEBUG_BLE
336 Serial.println("initialized BLE ...");
337#endif
338 BLEDevice::init(deviceName.c_str());
339 BLEServer *pServer = BLEDevice::createServer();
340 pServerCallbacks = new ServerCallbacks(pServer);
341 pServer->setCallbacks(pServerCallbacks);
342 BLEService *pService = pServer->createService(DD_SERVICE_UUID);
343 BLECharacteristic *pTx = pService->createCharacteristic(
344 DD_CHARACTERISTIC_UUID_TX,
345#ifdef DD_BLE_NOTIFY
346 BLECharacteristic::PROPERTY_NOTIFY
347#else
348 BLECharacteristic::PROPERTY_INDICATE
349#endif
350 );
351 pTx->addDescriptor(new BLE2902());
352 BLECharacteristic *pRx = pService->createCharacteristic(
353 DD_CHARACTERISTIC_UUID_RX,
354 BLECharacteristic::PROPERTY_WRITE
355 );
356 pCallbacks = new Callbacks(pTx, pServerCallbacks);
357 pRx->setCallbacks(pCallbacks);
358 pService->start();
359 pServer->getAdvertising()->start();
360 initialized = true;
361 address = BLEDevice::getAddress().toString().c_str();
362 address.toUpperCase();
363 //serviceUUID = pService->getUUID().toString().c_str();
364#ifdef DD_DEBUG_BLE
365 Serial.println("... done initialized BLE ... waiting for connection ...");
366#endif
367 }
368 private:
369 String deviceName;
370 String address;
371 bool initialized;
372 ServerCallbacks* pServerCallbacks;
373 Callbacks* pCallbacks;
374};
375
376
377//#endif
378#endif
Subclass of DDInputOutput.
Definition: esp32bledumbdisplay.h:49
Class for DD input/output; you explicitly constructed it, pass in when instantiate DumbDisplay,...
Definition: _dd_io.h:9