ESP_IOT v2.5
IOT ESP Coding
BLEClientNetworking.cpp
Go to the documentation of this file.
1/**
2* \link BLEClientNetworking
3*/
4//
5// BLEClientNetworking.cpp
6// M5Stick
7//
8// Created by Scott Moody on 1/20/22.
9//
10
11#include "BLEClientNetworking.h"
12
13#include <NimBLEDevice.h>
14#include "../../Defines.h"
15
16// seems 20 bytes is the max..
17//https://www.esp32.com/viewtopic.php?t=4546
18//!@see https://h2zero.github.io/esp-nimble-cpp/nimconfig_8h_source.html
19//#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 20
20
21//**** NIM BLE Client Code
22
23//!need to device way to change these ...
24
25// uses NimBLEUUID
26
27static NimBLEUUID _BLEClientServiceUUID(PT_SERVICE_UUID);
28//"B0E6A4BF-CCCC-FFFF-330C-0000000000F0"); //??
29static NimBLEUUID _BLEClientCharacteristicUUID(PT_CHARACTERISTIC_UUID);
30//"b0e6a4bf-cccc-ffff-330c-0000000000f1");
31static NimBLERemoteCharacteristic* _BLEClientCharacteristicFeed;
32
33//forward called on the end of the scan
34void scanEndedCB_BLEClient(NimBLEScanResults results);
35
36#ifdef M5UNIFIED
37static const NimBLEAdvertisedDevice* _advertisedDevice;
38#else
39static NimBLEAdvertisedDevice* _advertisedDevice;
40#endif
41//static uint32_t _scanTime = 0; /** 0 = scan forever */
42static bool _doConnect = false;
43static bool _isConnected_BLEClient = false;
44//! scan time in MS
45static uint32_t _scanTimeMs = 5000; /** scan time in milliseconds, 0 = scan forever */
46
47//try storing globally so we can disconnect..
48NimBLEClient *_pClient = nullptr;
49
50//! returns if the BLEClient is turned on.. note, if connected to a BLE device, then disconnect
51boolean useBLEClient()
52{
54 return val;
55}
56
57//!skip logic
60//!address to skip (for a number of times) .. how about 1 for now..
62//! an address or name to skip (for at least 1 time)
64{
65 SerialTemp.print("set skipAddress: ");
66 SerialTemp.println(nameOrAddress);
67
68 strcpy(_skipNameOrAddress_BLEClientNetworking, nameOrAddress);
70}
71//!stops the skip after found something..
73{
75}
76
77//!helper for skip, checking if an actuall address in the skip name or address
78boolean containsSkipAddress(String deviceInfo)
79{
80 boolean flag = false;
81
83 {
85 }
86 SerialTemp.printf("containsSkipAddress(%d): ", flag);
87 SerialTemp.print(deviceInfo);
88 SerialTemp.print(" skip=");
90 return flag;
91}
92
93
94/** None of these are required as they will be handled by the library with defaults. **
95 ** Remove as you see fit for your needs */
96class ClientCallbacks : public NimBLEClientCallbacks {
97#ifdef M5UNIFIED
98 void onConnect(NimBLEClient* pClient) override
99#else
100 void onConnect(NimBLEClient* pClient)
101#endif
102 {
103 SerialMin.printf("TIME: %d: ",getTimeStamp_mainModule());
104 SerialMin.println(" BLE Connected");
105 /** After connection we should change the parameters if we don't need fast response times.
106 * These settings are 150ms interval, 0 latency, 450ms timout.
107 * Timeout should be a multiple of the interval, minimum is 100ms.
108 * I find a multiple of 3-5 * the interval works best for quick response/reconnect.
109 * Min interval: 120 * 1.25ms = 150, Max interval: 120 * 1.25ms = 150, 0 latency, 60 * 10ms = 600ms timeout
110 */
111
112 //@see https://h2zero.github.io/esp-nimble-cpp/class_nim_b_l_e_client.html#aff7d389ec48567286ea732c54d320526
113 /**
114 [in] minInterval The minimum connection interval in 1.25ms units.
115 [in] maxInterval The maximum connection interval in 1.25ms units.
116 [in] latency The number of packets allowed to skip (extends max interval).
117 [in] timeout The timeout time in 10ms units before disconnecting.
118 */
119 //pClient->updateConnParams(120, 120, 0, 60);
120 //tried: no different .. pClient->updateConnParams(120, 120, 5, 120);
121
122 //set the connected flag
123 _isConnected_BLEClient = true;
124 };
125
126#ifdef M5UNIFIED
127 void onDisconnect(NimBLEClient* pClient, int reason) override {
128 SerialMin.printf("TIME: %d: ",getTimeStamp_mainModule());
129 //SerialLots.printf("Unix Time: %d\n", now);
130 SerialDebug.printf("%s Disconnected, reason = %d - Starting scan\n", pClient->getPeerAddress().toString().c_str(), reason);
131#else
132 void onDisconnect(NimBLEClient* pClient) {
133 SerialMin.printf("TIME: %d: ",getTimeStamp_mainModule());
134 //SerialLots.printf("Unix Time: %d\n", now);
135
136 SerialMin.println(" BLE Disconnected - Starting scan");
137 SerialMin.print(pClient->getPeerAddress().toString().c_str());
138#endif
139 SerialMin.println(" BLE Disconnected - Starting scan");
140 SerialMin.print(pClient->getPeerAddress().toString().c_str());
141
143 {
144#ifdef M5UNIFIED_notworking_try_old
145 NimBLEDevice::getScan()->start(_scanTimeMs, false, true);
146
147 //! 6.6.25 @see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#advertising
148 // The callback parameter for NimBLEScan::start has been removed and the blocking overload of NimBLEScan::start has been replaced by an overload of NimBLEScan::getResults with the same parameters.
149 //NimBLEScanResults results = NimBLEDevice::getScan()->getResults(PSCAN_TIME, false); // note the time is now in milliseconds
150#else
151 NimBLEDevice::getScan()->start(PSCAN_TIME, scanEndedCB_BLEClient);
152#endif
153 }
154 else
155 {
156 SerialMin.println("*** in OTA update . no scanning ***");
157 }
158 //print the time of day...
159
160 //set the connected flag = false
161 _isConnected_BLEClient = false;
162 };
163
164
165 /********************* Security handled here **********************
166 ****** Note: these are the same return values as defaults ********/
167 uint32_t onPassKeyRequest() {
168 SerialLots.println("Client Passkey Request");
169 /** return the passkey to send to the server */
170 return 123456;
171 };
172
173 bool onConfirmPIN(uint32_t pass_key) {
174 SerialLots.print("The passkey YES/NO number: ");
175 SerialLots.println(pass_key);
176 /** Return false if passkeys don't match. */
177 return true;
178 };
179 /** Pairing process complete, we can check the results in connInfo */
180 //! 6.6.26 D-Day 82 years, move to version 2.x
181 //!@see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#ble-device
182#ifdef M5UNIFIED
183 void onAuthenticationComplete(NimBLEConnInfo& connInfo) override
184 {
185 if (!connInfo.isEncrypted()) {
186 SerialDebug.printf("Encrypt connection failed - disconnecting\n");
187 /** Find the client with the connection handle provided in connInfo */
188 NimBLEDevice::getClientByHandle(connInfo.getConnHandle())->disconnect();
189 return;
190 }
191 }
192#else
193 void onAuthenticationComplete(ble_gap_conn_desc* desc) {
194 if (!desc->sec_state.encrypted) {
195 SerialDebug.println("Encrypt connection failed - disconnecting");
196 /** Find the client with the connection handle provided in desc */
197 NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
198
199 //not connected
200 _isConnected_BLEClient = false;
201 return;
202 }
203 };
204#endif
205
206}
207#ifdef M5UNIFIED
209#else
210 ;
211#endif
212
213#ifdef M5UNIFIED
214//!6.6.26
215//!@see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#ble-device
216/*
217 NimBLEAdvertisedDeviceCallbacks Has been replaced by NimBLEScanCallbacks which contains the following methods:
218
219 NimBLEScanCallbacks::onResult, functions the same as the old NimBLEAdvertisedDeviceCallbacks::onResult but now takes aa const NimBLEAdvertisedDevice* instead of non-const.
220 NimBLEScanCallbacks::onScanEnd, replaces the scanEnded callback passed to NimBLEScan::start and now takes a const NimBLEScanResults& and int reason parameter.
221 NimBLEScanCallbacks::onDiscovered, This is called immediately when a device is first scanned, before any scan response data is available and takes a const NimBLEAdvertisedDevice* parameter.
222 */
223//class AdvertisedDeviceCallbacks : public NimBLEScanCallbacks
224class ScanCallbacks : public NimBLEScanCallbacks
225
226#else
227/** Define a class to handle the callbacks when advertisments are received */
228class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks
229#endif
230{
231#ifdef M5UNIFIED_notworking
232 void onScanEnd(const NimBLEScanResults& result,int reason)
233 {
234 SerialLots.printf("onScanEnd: %d\n", reason);
235 //! added 6.17.26
236 NimBLEDevice::getScan()->start(_scanTimeMs, false, true);
237
238 }
239 void onDiscovered(const NimBLEAdvertisedDevice* parameter)
240 {
241 SerialLots.printf("onDiscovered:\n");
242
243 }
244 void onResult( NimBLEAdvertisedDevice* advertisedDevice)
245 //void onResult(const NimBLEAdvertisedDevice* advertisedDevice)
246
247#else
248
249#ifdef M5UNIFIED
250 void onResult(const NimBLEAdvertisedDevice* advertisedDevice) override
251#else
252 void onResult(NimBLEAdvertisedDevice* advertisedDevice)
253#endif
254#endif
255 {
256 SerialLots.printf(" *** onResult adv, useBLEClient = %d\n", useBLEClient());
258
259 {
260 //This helps if not already connected...
261 _doConnect = false;
262 return;
263 }
264 SerialLots.print("BLE Devices Advertised: ");
265 SerialLots.println(advertisedDevice->toString().c_str());
266 //The found service, see if its our service..
267 String deviceInfo = advertisedDevice->toString().c_str();
268
269
270 //!if the only-connect-to-GEN3 is turned on .. then wait until a GEN3 is found before connecting.
271 boolean foundGEN3 = false;
272 //temp:
274 if (advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD"))) //this was the original code service called UUID "DEAD"
275 {
276 SerialMin.print("Device advertised: ");
277 SerialMin.println(advertisedDevice->getName().c_str());
278 SerialLots.print("Device URI: ");
279 SerialLots.println(advertisedDevice->getURI().c_str());
280
281 //SerialDebug.println(" **** Found a DEAD service .. meaning it's not a GEN3");
282 // if (strcmp(advertisedDevice->getName().c_str(), MAIN_BLE_CLIENT_SERVICE)!= 0)
283 if (getDiscoverM5PTClicker() && (strncmp(advertisedDevice->getName().c_str(), M5_BLE_CLIENT_SERVICE, strlen(M5_BLE_CLIENT_SERVICE)) == 0))
284 {
285 SerialDebug.printf("** DiscoverM5PTClicker && Found a PTCLICKER .. go for it.. %w\n",advertisedDevice->getName().c_str() );
286 }
287 else if (getDiscoverM5PTClicker())
288 {
289 //! the DiscoverM5PTClicker is set .. so only find PTClickers .. helps in crowded field
290 SerialDebug.printf("** DiscoverM5PTClicker && **** ESP32 Feeder (%s) but not 'PTClicker M5' skipping..\n", advertisedDevice->getName().c_str());
291 return;
292 }
293 else if (strncmp(advertisedDevice->getName().c_str(), MAIN_BLE_CLIENT_SERVICE, strlen(MAIN_BLE_CLIENT_SERVICE)) != 0)
294 {
295 SerialDebug.printf(" **** ESP32 Feeder (%s) but not 'PTFeeder' skipping..\n", advertisedDevice->getName().c_str());
296 //! look for "PTClicker"
297 return;
298 }
299 }
300 else if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(PT_SERVICE_UUID) > 0))
301
302 {
303 SerialDebug.println(" **** Found a GEN3 Device");
304 foundGEN3 = true;
305 }
306 if (requireGEN3 and !foundGEN3)
307 {
308 SerialDebug.println(" **** Looking for GEN3 but didn't find it .. so not connecting");
309 _doConnect = false;
310 return;
311 }
312 //!look for name of service as well.... PTClicker vs PTFeeder
313 if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(PT_SERVICE_UUID) > 0)) //this was the original code service called "DEAD"
314 {
315 SerialTemp.println("Found candidate BLE Service: ");
316 SerialTemp.println(advertisedDevice->toString().c_str());
317 String deviceInfo = advertisedDevice->toString().c_str();
318 //"Name: PTFeeder:PumpkinUno, Address: 08:3a:f2:51:7c:3e, serviceUUID: 0xdead"
319 // Name: PTFeeder, Address: 00:05:c6:75:55:15, txPower: 0 (GEN3 version)
320
321 //see if its one we are skipping..
322 if (containsSkipAddress(deviceInfo))
323 {
326 {
327 SerialTemp.print("Found device, but skip is max .. so connect");
328
329 //and the count of times
331 //fall through ..
332 }
333 else
334 {
335 SerialTemp.print("Found device, but will skip as it contains nameOrAddress: ");
336 SerialTemp.println(_skipNameOrAddress_BLEClientNetworking);
337
338 _doConnect = false;
339 return;
340 }
341 }
342
343 //! THIS CODE doesn't know what pairedDevice name is used (the :name or the :address)
344 //! But just looks for an occurance of that address in the deviceInfo string..
345 //!
346
347 // let the main know we discovered a device (full name, let them parse it)
348 // only if connected...
349
350 //!if not a GEN3 .. look for a requiring a paired device in the deviceIno
351 // if (!foundGEN3)
352 // The address part can also be used for the GEN3 now..
353 {
354 //! look for a paired device in the advertisment..
355 //!P = paired
356
357 //! This just returns that a paired device name or address is set..
358 //! The problem is that for a GEN3 that name is meaninless (except PTFeeder)
360#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
361
362 //if (getPreferenceBoolean_mainModule(PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING))
363#endif
364 {
365 //!REQUIRE a match..
366 _doConnect = false;
367
368 //! Having a paired name but not a paired address .. breaks the GEN3 search .. fix it (10.23.22)
369
370 //! look for the device name to contain the paired device name (no string match)
371 //! NOTE: don't name your device PTFEEDER or it defeats somewhat (but look for a ":")
372 //! Name: PTFeeder, Address: 00:05:c6:75:55:15, txPower: 0 (GEN3 version)
373 if (containsSubstring(deviceInfo,":"))
374 {
375 boolean found = false;
377
378 //! syntax correct, look for the pairedDeviceName (will be false for GEN3 unless paired with Address)
379 if (containsSubstring(deviceInfo, pairedDeviceName))
380 found = true;
381 //!should be false for any where not matching..
382 SerialTemp.printf(" containsSubstring(%d, %s)\n", found, pairedDeviceName);
383 if (!found)
384 {
385 //! this only checks if we previously paired to the name or address, but not a new GEN3
387 if (containsSubstring(deviceInfo,pairedDeviceAddress))
388 found = true;
389
390 SerialTemp.printf(" containsSubstring(%d, '%s')\n", found, pairedDeviceAddress);
391
392 if (!found && foundGEN3 && strlen(pairedDeviceAddress)==0)
393 {
394 found = true;
395 SerialTemp.printf(" no paired address but a GEN3 so good(%d)\n", found);
396
397 }
398 }
399 if (found) {
400 if (foundGEN3)
401 SerialTemp.println("*** FOUND GEN3 PAIRED Device Name: ");
402 else
403 SerialTemp.println("*** FOUND BLE PAIRED Device Name: ");
404
405 SerialTemp.println(pairedDeviceName);
406 _doConnect = true;
407 }
408 else
409 {
410 SerialTemp.println(" *** Nothing paired ****");
411 }
412 }
413 if (!_doConnect)
414 {
415 SerialTemp.print("Not matching desired device name: '");
417 SerialTemp.print("' .. or address: ");
419
420 return;
421 }
422 }
423 }
424 //!continue on as we are good.. so stop scanning,
425 setConnectedBLEDevice_mainModule(&deviceInfo[0], foundGEN3);
426
427 //!invalidate the skip
429
430 /** stop scan before connecting */
431 NimBLEDevice::getScan()->stop();
432 /** Save the device reference in a global for the client to use*/
433 _advertisedDevice = advertisedDevice;
434 /** Ready to connect now */
435 _doConnect = true;
436 }
437 };
439
440
441/** Notification / Indication receiving handler callback */
442void notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
443#if (SERIAL_DEBUG_DEBUG)
444 std::string str = (isNotify == true) ? "Notification" : "Indication";
445 str += " from ";
446 /** NimBLEAddress and NimBLEUUID have std::string operators */
447#ifdef M5UNIFIED
448 //!6.6.26
449 //!@see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#ble-device
450 str += std::string(pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
451 str += ": Service = " + std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
452 str += ", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
453 str += ", Value = " + std::string((char*)pData, length);
454#else
455 str += std::string(pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
456 str += ": Service = " + std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
457 str += ", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
458 str += ", Value = " + std::string((char*)pData, length);
459#endif
460 SerialLots.println(str.c_str());
461#endif //SerialDebug
462}
463
464//!NOTE: this is called all the time... 4.22.22 --even if the "scan-stop" invoked.
465/** Callback to process the results of the last scan or restart it */
466void scanEndedCB_BLEClient(NimBLEScanResults results) {
467 SerialLots.println("Scan Ended");
468}
469
470#ifdef M5UNIFIED
471#else
472/** Create a single global instance of the callback class to be used by all clients */
474#endif
475
476/** Handles the provisioning of clients and connects / interfaces with the server */
478{
479 SerialCall.println("connectToServer_BLEClient");
480 NimBLEClient* pClient = nullptr; //creates a new instance of a pointer to a client(1 for each server it connects to)
481#ifdef M5UNIFIED
482 //! 6.6.26
483 /*
484 NimBLEDevice::getClientListSize replaced with NimBLEDevice::getCreatedClientCount.
485 NimBLEDevice::getClientList was removed and NimBLEDevice::getConnectedClients can be used instead which returns a std::vector of pointers to the connected client instances. This was done because internally the clients are managed in a std::array which replaced the 'std::list`.
486 */
487 if (NimBLEDevice::getCreatedClientCount())
488#else
489 /** Check if we have a client we should reuse first **/
490 if (NimBLEDevice::getClientListSize())
491#endif
492 { //this runs only if #clients>= 1...ie no client instance start yet
493 /** Special case when we already know this device, we send false as the
494 * second argument in connect() to prevent refreshing the service database.
495 * This saves considerable time and power.
496 */
497 pClient = NimBLEDevice::getClientByPeerAddress(_advertisedDevice->getAddress()); //if the server was connected to before there should be an address stored for it -wha
498 if (pClient) {
499 if (!pClient->connect(_advertisedDevice, false)) {
500 SerialTemp.println("Reconnect failed");
501 return false;
502 }
503 SerialDebug.println("Reconnected pClient");
504 }
505 /** We don't already have a client that knows this device,
506 * we will check for a client that is disconnected that we can use.
507 */
508 else {
509
510 pClient = NimBLEDevice::getDisconnectedClient(); //reusing a client that was created but is disconnected -wha
511 if (pClient)
512 {
513 SerialTemp.printf("Reusing a disconnected pClient: %s\n",pClient? pClient->getPeerAddress().toString().c_str():"NULL");
514 }
515 }
516 }
517
518 /** No client to reuse? Create a new one. */
519 if (!pClient)
520 {
521 //if a client instance is created from above this will not be executed -wha
522 //go back to >= 1 (4.22.22)
523
524 //! 6.6.26
525 /*
526 NimBLEDevice::getClientListSize replaced with NimBLEDevice::getCreatedClientCount.
527 NimBLEDevice::getClientList was removed and NimBLEDevice::getConnectedClients can be used instead which returns a std::vector of pointers to the connected client instances. This was done because internally the clients are managed in a std::array which replaced the 'std::list`.
528 */
529#ifdef M5UNIFIED
530 if (NimBLEDevice::getCreatedClientCount() >= 1 )
531#else
532 if (NimBLEDevice::getClientListSize() >= 1 ) //wha -original example code used the max configuration of 3 --> NIMBLE_MAX_CONNECTIONS)
533#endif
534 {
535 SerialDebug.println("Max clients reached - no more connections available");
536 return false;
537 }
538 //! create a new client
539 pClient = NimBLEDevice::createClient();
540
541 SerialDebug.printf("***New client created(%d)\n", pClient);
542
543 //! set callback
544 pClient->setClientCallbacks(&_clientCB_BLEClient, false);
545
546 /** Set initial connection parameters: These settings are 15ms interval, 0 latency, 120ms timout.
547 * These settings are safe for 3 clients to connect reliably, can go faster if you have less
548 * connections. Timeout should be a multiple of the interval, minimum is 100ms.
549 * Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 51 * 10ms = 510ms timeout
550 */
551 /**
552
553 [in] minInterval The minimum connection interval in 1.25ms units.
554 [in] maxInterval The maximum connection interval in 1.25ms units.
555 [in] latency The number of packets allowed to skip (extends max interval).
556 [in] timeout The timeout time in 10ms units before disconnecting.
557 [in] scanInterval The scan interval to use when attempting to connect in 0.625ms units.
558 [in] scanWindow The scan window to use when attempting to connect in 0.625ms units.
559*/
560#ifdef M5UNIFIED
561 //! 6.8.26 set to 150 (from 51)
562 pClient->setConnectionParams(12, 12, 0, 150);
563 //try: no different
564 //pClient->setConnectionParams(12, 12, 10, 51);
565
566 /** Set how long we are willing to wait for the connection to complete (seconds), default is 3000. (was 5)*/
567 pClient->setConnectTimeout(5 * 1000);
568 //pClient->setConnectTimeout(5); // * 1000);
569#else
570 pClient->setConnectionParams(12, 12, 0, 51);
571 //try: no different pClient->setConnectionParams(12, 12, 10, 51);
572
573 /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
574 pClient->setConnectTimeout(5);
575 Serial.printf("pClient=%d\n",pClient); //_advertisedDevice == 0 !!!
576 if (!_advertisedDevice)
577 {
578 SerialMin.println(" **** ERROR: advertisedDevice == NULL");
579 return false;
580 }
581 Serial.printf("_advertisedDevice=%d\n",_advertisedDevice);
582
583#endif
584
585 if (!pClient->connect(_advertisedDevice))
586 {
587 /** Created a client but failed to connect, don't need to keep it as it has no data */
588 NimBLEDevice::deleteClient(pClient);
589 SerialDebug.println("Failed to connect, deleted client");
590 return false;
591 }
592 }
593
594 //try .. doesn't seem to matter..
595 if (!pClient->isConnected())
596 {
597 if (!pClient->connect(_advertisedDevice))
598 {
599 SerialDebug.printf("Failed to connect, deleted client\n");
600
601 //!not connected
602 _isConnected_BLEClient = false;
603 return false;
604 }
605 }
606 SerialDebug.printf("Connected to: %s RSSI: %d\n", pClient->getPeerAddress().toString().c_str(), pClient->getRssi());
607
608 _pClient = pClient;
609#ifdef M5UNIFIED
610 //!6.6.26
611 /*
612 NimBLEDevice::getClientListSize replaced with NimBLEDevice::getCreatedClientCount.
613 NimBLEDevice::getClientList was removed and NimBLEDevice::getConnectedClients can be used instead which returns a std::vector of pointers to the connected client instances. This was done because internally the clients are managed in a std::array which replaced the 'std::list`.
614 */
615 SerialLots.printf("number clients= %d \n\r", NimBLEDevice::getCreatedClientCount()); //
616
617#else
618 SerialLots.printf("number clients= %d \n\r", NimBLEDevice::getClientListSize()); //
619#endif
620 SerialMin.printf("TIME: %d: ",getTimeStamp_mainModule());
621 SerialMin.print(" - Connected to pClient: ");
622 SerialMin.println(pClient->getPeerAddress().toString().c_str());
623 SerialLots.print("RSSI: ");
624 SerialLots.println(pClient->getRssi());
625
626 /** Now we can read/write/subscribe the charateristics of the services we are interested in */
627 NimBLERemoteService* pSvc = nullptr;
628 NimBLERemoteCharacteristic* pChr = nullptr;
629 NimBLERemoteDescriptor* pDsc = nullptr;
630#define NEW_WAY
631 //! **** THATS WHY THE DEAD is there .. only our new ones have that..
632 //! This was added 2022 - for this specific reason
633 //! @see https://github.com/konacurrents/ESP_IOT/issues/161
634#ifdef NEW_WAY
635 //!Try to get our new service == DEAD (for now.. this is not in the GEN3)
636 pSvc = pClient->getService("DEAD");
637 if (pSvc)
638 {
639 //! THIS IS A new ESP32 feeder
640 SerialTemp.printf("*** v2.0 This is an ESP Based Feeder (not GEN3)***\n");
641 // unset the gatewayFlag
642 //! called to set a preference (which will be an identifier and a string, which can be converted to a number or boolean)
644 }
645 else
646 {
647 //! THIS IS A new ESP32 feeder
648 SerialTemp.println("*** v2.0 This is an GEN3 Feeder (not ESP32)***");
649 //set the gateway flag!!
650 //! called to set a preference (which will be an identifier and a string, which can be converted to a number or boolean)
652
653 }
654#endif // NEW_WAY
655
656 // the original was setup for service/characteristic : DEAD-BEEF ..but we are revising for BAAD/F00D
657 pSvc = pClient->getService(_BLEClientServiceUUID); // char* _BLEClientServiceUUID 36 characters
658 if (pSvc)
659 { /** make sure it's not null */
660 pChr = pSvc->getCharacteristic(_BLEClientCharacteristicUUID); //this was the original example code characteristic called "BEEF"
661 _BLEClientCharacteristicFeed = pChr;
662 if (!pChr)
663 {
664 SerialLots.println(" **** BLEClientNetworking is nil in creation...");
665 }
666 else
667 { /** make sure it's not null */
668 if (pChr->canRead())
669 {
670 SerialLots.print(pChr->getUUID().toString().c_str());
671 SerialLots.print(" Value: ");
672 SerialLots.println(pChr->readValue().c_str());
673 }
674
675 //NOTE: this string is also sent onto the ProcessClientCmd() which look at the first character
676 // and if it's say 'B' it turns on the buzzer. So let's make this a character that isn't used..
677#ifdef DO_IT_ANOTHER_WAY_WITHOUT_SENDING_VALUE
678 String sentValue = "_ESP_32";
679
680 if (pChr->canWrite())
681 {
682 //we are going to send a known string "sendValue = BLEClient"
683 // and if we read it back below, we are a new ESP32 feeder, otherwise GEN3
684 if (pChr->writeValue(sentValue)) {
685 //if (pChr->writeValue("Tasty")) {
686 SerialDebug.print("Wrote new value(1) to: ");
687 SerialDebug.println(pChr->getUUID().toString().c_str());
688 SerialDebug.printf("'%s'\n", sentValue);
689 }
690 else
691 {
692 SerialDebug.println("Disconnecting if write failed");
693 /** Disconnect if write failed */
694 pClient->disconnect();
695 return false;
696 }
697
698 //NOTE: this looks good on the Arduino C++ supported (not same, like no "compare" but "compareTo" -- now they tell me:-) 4.23.22
699 // read reply..
700 if (pChr->canRead())
701 {
702 SerialDebug.print("The value(1) of: ");
703 SerialDebug.print(pChr->getUUID().toString().c_str());
704 SerialDebug.print(" is now: '");
705 SerialDebug.print(pChr->readValue().c_str());
706 SerialDebug.println("'");
707 if (sentValue.compareTo(pChr->readValue().c_str()) == 0)
708 {
709 //! THIS IS A new ESP32 feeder
710 SerialTemp.printf("*** This is an ESP Based Feeder (not GEN3)***\n");
711 // unset the gatewayFlag
712 //! called to set a preference (which will be an identifier and a string, which can be converted to a number or boolean)
714 }
715 else
716 {
717 //! THIS IS A new ESP32 feeder
718 SerialTemp.println("*** This is an GEN3 Feeder (not ESP32)***");
719 //set the gateway flag!!
720 //! called to set a preference (which will be an identifier and a string, which can be converted to a number or boolean)
722
723 }
724 //NOTE:
725
726 }
727 }
728#endif //DO_IT_ANOTHER_WAY_WITHOUT_SENDING_VALUE
729 /** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
730 * Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
731 * Unsubscribe parameter defaults are: response=false.
732 */
733 if (pChr->canNotify())
734 {
735 //if(!pChr->registerForNotify(notifyCB)) {
736 if (!pChr->subscribe(true, notifyCB)) {
737 /** Disconnect if subscribe failed */
738 pClient->disconnect();
739
740 return false;
741 }
742 }
743 else if (pChr->canIndicate())
744 {
745
746 /** Send false as first argument to subscribe to indications instead of notifications */
747 //if(!pChr->registerForNotify(notifyCB, false)) {
748 if (!pChr->subscribe(false, notifyCB))
749 {
750 /** Disconnect if subscribe failed */
751 pClient->disconnect();
752 return false;
753 }
754 }
755 }
756
757 }
758 else
759 {
760 SerialLots.println("DEAD service not found.");
761 }
762
763 // original example pSvc = pClient->getService("BAAD"); // reference only---remove after testing
764 if (pSvc)
765 {
766 //SerialDebug.printf("pSvc = %s, pChr = %d\n", pSvc?pSvc:(char*)"NULL", pChr?pChr:(char*)"NULL");
767 /** make sure it's not null */
768 // origional example: pChr = pSvc->getCharacteristic("F00D"); // reference only---remove after testing
769 if (pChr)
770 {
771 /** make sure it's not null */
772 if (pChr->canRead())
773 {
774
775 SerialDebug.print(pChr->getUUID().toString().c_str());
776 SerialDebug.print(" Value: ");
777 SerialDebug.println(pChr->readValue().c_str());
778 }
779 //SerialDebug.println(" .. NEXT LINE HANGS..."); // then reboots
780 /*
781 Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception)
782 Debug exception reason: Stack canary watchpoint triggered (loopTask)
783 Core 1 register dump:
784 */
785
786 //FOR SOME REASON, the getdescriptor hangs on the GEN3 but not on ESP32
787 //So this 'return true' makes things working..
788 return true;
789#ifdef NOT_USED_FOR_SOME_REASON
790 pDsc = pChr->getDescriptor(NimBLEUUID("C01D"));
791
792 SerialDebug.println(" .. DOESNT GET HERE");
793
794 if (pDsc)
795 { /** make sure it's not null */
796 SerialDebug.print("Descriptor: ");
797 SerialDebug.print(pDsc->getUUID().toString().c_str());
798 SerialDebug.print(" Value: ");
799 SerialDebug.println(pDsc->readValue().c_str());
800 }
801 SerialDebug.println(" .. 111");
802#else // try the following code again... 4.22.22
803 if (pChr->canWrite())
804 {
805 if (pChr->writeValue("No tip!")) {
806 SerialDebug.print("Wrote new value(2) to: ");
807 SerialDebug.println(pChr->getUUID().toString().c_str());
808 }
809 else {
810 /** Disconnect if write failed */
811 pClient->disconnect();
812 return false;
813 }
814
815 if (pChr->canRead()) {
816 SerialDebug.print("The value(2) of: ");
817 SerialDebug.print(pChr->getUUID().toString().c_str());
818 SerialDebug.print(" is now: ");
819 SerialDebug.println(pChr->readValue().c_str());
820 }
821 }
822 SerialDebug.println(" .. 222");
823
824 /** registerForNotify() has been deprecated and replaced with subscribe() / unsubscribe().
825 * Subscribe parameter defaults are: notifications=true, notifyCallback=nullptr, response=false.
826 * Unsubscribe parameter defaults are: response=false.
827 */
828 if (pChr->canNotify()) {
829 //if(!pChr->registerForNotify(notifyCB)) {
830 if (!pChr->subscribe(true, notifyCB)) {
831 /** Disconnect if subscribe failed */
832 pClient->disconnect();
833 return false;
834 }
835 }
836 else if (pChr->canIndicate()) {
837 /** Send false as first argument to subscribe to indications instead of notifications */
838 //if(!pChr->registerForNotify(notifyCB, false)) {
839 if (!pChr->subscribe(false, notifyCB)) {
840 /** Disconnect if subscribe failed */
841 pClient->disconnect();
842 return false;
843 }
844 }
845 SerialDebug.println(" .. 333");
846#endif // not used
847 }
848
849 }
850 else {
851 SerialLots.println("BAAD service not found.");
852 }
853
854 SerialDebug.println("Done with this device!");
855 return true;
856}
857
858//! returns whether connected over BLE as a client to a server(like a ESP feeder)
860{
861 //not connected
862 //_isConnected_BLEClient = false;
863 // seems the _BLEClientCharacteristicFeed is not null for ever.. so not usable
864 //boolean isConnected = _BLEClientCharacteristicFeed?true:false;
865 boolean isConnected = _isConnected_BLEClient;
866
867 SerialLots.printf("isConnectedBLEClient: %d\n",isConnected);
868 return isConnected;
869}
870
871//!sends the "feed" command over bluetooth to the connected device..
873{
874 SerialLots.println("sendFeedCommandBLEClient()");
875 // if (FeedFlag == true)
876 //flag is set in button_task
877 // Set the characteristic's value to be the array of bytes that is actually a string.
878 std::string newValue = "s"; // this sets a value to the GATT which is the trigger value for the BLE server feeder
879 const uint8_t newValueFeed = { 0x00 };
880 if (!_BLEClientCharacteristicFeed)
881 {
882 SerialLots.println(" **** Error _BLEClientCharacteristicFeed is nil ***");
883 return;
884 }
885 if (_BLEClientCharacteristicFeed->writeValue(newValueFeed, 1)) { //force the length to 1. newValue.length() may return 0 if newValue=null
886 SerialMin.print("BLEClient writeValue: '");
887 SerialMin.print(newValue.c_str());
888 SerialMin.println("' - sent FEED");
889
890
891
892 // PrevTriggerTime = millis();
893 // FeedCount--;
894 // M5.Beep.beep(); //M5.Beep.tone(4000,200);
895 // delay(50);
896 // M5.Beep.mute();
897 // if (FeedCount <= 0){
898 // FeedCount = 0;//avoid display of negative values
899 // }
900 // M5.Lcd.setCursor(0, 80);
901 // M5.Lcd.printf("Treats= %d \n\r",FeedCount);
902 }
903 else {
904 SerialDebug.print(newValue.c_str());
905 SerialDebug.println("FAILED GATT write(1)");
907
908 }
909 // FeedFlag = false;
910 // delay(100);
911 /* check for the acknowledge from the server which is 0x01 */
912 if (_BLEClientCharacteristicFeed->canRead()) {
913 std::string value = _BLEClientCharacteristicFeed->readValue();
914 SerialTemp.printf("BLE Server response: '%s'\n",(value[0]==0x01)?(char*)"01":(char*)"");
915 //SerialTemp.print(value.c_str());
916 //SerialTemp.println("'");
917 if (value[0] == 0x01) { // server ack is 0x01....so flash client led for the ack from the server wha 9-28-21
918 // Led_ON();
919 // delay(150);
920 // Led_OFF();//
921 // delay(150);
922
923 //call what is registered
925
926 //call what is registered
928
929 }
930 else
931 {
932 SerialDebug.println("Didn't get a response 0x01");
933 //call what is registered
935
936 //call what is registered
938
939 }
940 }
941
942}
943
944//!send a string of 13 characters or less
945void sendCommandBLEClient_13orLess(String cmdString);
946
947//!FOR NOW THIS IS HERE.. but it should be more generic. eg: sendBluetoothCommand() ..
948//!send the feed command
949//!NOTE: if we are a gateway (gen3) then this won't work, as it's not talking back..
950void sendCommandBLEClient(String cmdString)
951{
952 SerialDebug.print("sendCommandBLEClient(");
953 SerialDebug.print(cmdString.length());
954 SerialDebug.print("): '");
955 SerialDebug.print(cmdString);
956 SerialDebug.print("' gateway=");
958 SerialDebug.println(isGatewayGEN3?"gen3":"esp32");
959
960 //!if GEN3 then this handshaking will not work.. so just send the cmd, if longer than 1 character, it hangs .. so don't send
961 if (isGatewayGEN3)
962 {
963 if (cmdString.length() > 0)
964 {
965 SerialDebug.println(" *** GEN3 and command longer than 1 character .. not sending");
966 }
967 else
969 return;
970 }
971
972 //Try to break the packets..
973 //send in packets of 13
974 int len = cmdString.length();
975 String startCmd = "#MSG_START";
977 int start = 0;
978 for (int i = 0; i < len;i+=13)
979 {
980 String s;
981 if (start + 13 > cmdString.length())
982 s = cmdString.substring(start);
983 else
984 s = cmdString.substring(start,start+13);
985 start += 13;
986 //never send a 1 character so the other side can exit on error
987 if (s.length()==1)
988 s += " ";
989 //send this fragment
991 }
992
993 String endCmd = "#MSG_END";
995}
996//!FOR NOW THIS IS HERE.. but it should be more generic. eg: sendBluetoothCommand() ..
997//!send the feed command
998void sendCommandBLEClient_13orLess(String cmdString)
999{
1000 SerialDebug.print("sendCommandBLEClient13(");
1001 SerialDebug.print(cmdString.length());
1002 SerialDebug.print("): '");
1003 SerialDebug.print(cmdString);
1004 SerialDebug.println("'");
1005
1006
1007 //! if (FeedFlag == true)
1008 //!flag is set in button_task
1009 //! Set the characteristic's value to be the array of bytes that is actually a string.
1010 //! this sets a value to the GATT which is the trigger value for the BLE server feeder
1011 if (!_BLEClientCharacteristicFeed)
1012 {
1013 SerialDebug.println(" **** Error _BLEClientCharacteristicFeed is nil ***");
1014 return;
1015 }
1016 if (_BLEClientCharacteristicFeed->writeValue(cmdString, cmdString.length()),true) {
1017 SerialDebug.print("writeValue:");
1018 SerialDebug.println(cmdString.c_str());
1019
1020 }
1021 else {
1022 SerialDebug.print(cmdString.c_str());
1023 SerialDebug.println("FAILED GATT write(2)");
1025
1026 }
1027 //!delay
1028 delay(100);
1029 //! check for the acknowledge from the server which is 0x01
1030 if (_BLEClientCharacteristicFeed->canRead()) {
1031 std::string value = _BLEClientCharacteristicFeed->readValue();
1032 SerialLots.print("BLE Server response: '");
1033 SerialLots.print(value.c_str()); SerialDebug.println("'");
1034 if (value[0] == 0x01) { // server ack is 0x01....so flash client led for the ack from the server wha 9-28-21
1035 // Led_ON();
1036 // delay(150);
1037 // Led_OFF();//
1038 // delay(150);
1039
1040 //call what is registered
1042
1043 //call what is registered
1044 //callCallbackMain(CALLBACKS_BLE_CLIENT, BLE_CLIENT_CALLBACK_STATUS_MESSAGE,(char*)"#FED");
1045
1046 }
1047 else
1048 {
1049 SerialDebug.println("Didn't get a response 0x01");
1050 //call what is registered
1052
1053 //call what is registered
1055
1056 }
1057 }
1058}
1059
1060#ifndef OLD
1061//!the setup() and loop() passing the serviceName to look for..
1062void setup_BLEClientNetworking(char *serviceName, char *serviceUUID, char *characteristicUUID)
1063{
1064 //!address to skip (for a number of times) .. how about 1 for now..
1066
1067 //!start the bluetooth discovery..
1068 SerialDebug.println("Starting NimBLE BLEClientNetworking");
1069 /** Initialize NimBLE, no device name spcified as we are not advertising */
1070 //NimBLEDevice::init("");
1071 NimBLEDevice::init(serviceName);
1072
1073 //https://github.com/nkolban/esp32-snippets/issues/945
1074 //https://www.esp32.com/viewtopic.php?t=4546
1075 // NOTE working .. still only 16 chars (my 13 + 3)
1076 //NOT WORKING...
1077 //NimBLEDevice::setMTU(200);
1078
1079
1080 /** Set the IO capabilities of the device, each option will trigger a different pairing method.
1081 * BLE_HS_IO_KEYBOARD_ONLY - Passkey pairing
1082 * BLE_HS_IO_DISPLAY_YESNO - Numeric comparison pairing
1083 * BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing
1084 */
1085 //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); // use passkey
1086 //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO); //use numeric comparison
1087
1088 /** 2 different ways to set security - both calls achieve the same result.
1089 * no bonding, no man in the middle protection, secure connections.
1090 *
1091 * These are the default values, only shown here for demonstration.
1092 */
1093 //NimBLEDevice::setSecurityAuth(false, false, true);
1094#ifdef use_security
1095 //! 6.17.26 turn off
1096 NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
1097#endif
1098
1099#ifdef M5UNIFIED_notworking
1100 //!6.6.26
1101 //!@see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#ble-device
1102 /*
1103 NimBLEDevice::setPower no longer takes the esp_power_level_t and esp_ble_power_type_t, instead only an integer value in dbm units is accepted, so instead of ESP_PWR_LVL_P9 an int8_t value of 9 would be used for the same result.
1104 */
1105 {
1106 //int8_t value = 9;
1107 int8_t value = 3; /** 3dbm */
1108 SerialDebug.printf("NimBLEDevice::setPower %d\n", value);
1109
1110 NimBLEDevice::setPower(value);
1111 }
1112#else
1113
1114#ifdef M5UNIFIED
1115 /** Optional: set the transmit power, default is 3db */
1116 //NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
1117 NimBLEDevice::setPower(3); /** +9db */
1118#else
1119 /** Optional: set the transmit power, default is 3db */
1120 NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
1121#endif
1122
1123#endif
1124
1125 /** Optional: set any devices you don't want to get advertisments from */
1126 // NimBLEDevice::addIgnored(NimBLEAddress ("aa:bb:cc:dd:ee:ff"));
1127
1128 /** create new scan */
1129 NimBLEScan* pScan = NimBLEDevice::getScan();
1130
1131#ifdef M5UNIFIED
1132 //! 6.6.25 @see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#advertising
1133 /*
1134 NimBLEScan::setAdvertisedDeviceCallbacks(NimBLEAdvertisedDeviceCallbacks* callbacks, bool wantDuplicates) has been changed to NimBLEScan::setScanCallbacks(NimBLEScanCallbacks* callbacks, bool wantDuplicates);
1135 */
1136
1137 /** Set the callbacks to call when scan events occur, no duplicates */
1138 //pScan->setScanCallbacks(new NimBLEScanCallbacks());
1139 pScan->setScanCallbacks(&_scanCallbacks, false);
1140
1141
1142#else
1143 /** create a callback that gets called when advertisers are found */
1144 pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
1145#endif
1146
1147 /** Set scan interval (how often) and window (how long) in milliseconds */
1148// pScan->setInterval(45);
1149// pScan->setWindow(15);
1150#ifdef not_bootstrap_NOT_NOW
1151 pScan->setInterval(PSCAN_INTERVAL);
1152 pScan->setWindow(PSCAN_WINDOW);
1153#else
1154
1155 /** Set scan interval (how often) and window (how long) in milliseconds */
1156 pScan->setInterval(100);
1157 pScan->setWindow(100);
1158#endif
1159
1160
1161 /** Active scan will gather scan response data from advertisers
1162 * but will use more energy from both devices
1163 */
1164 pScan->setActiveScan(true);
1165 /** Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
1166 * Optional callback for when scanning stops.
1167 */
1168#ifdef M5UNIFIED
1169 //! 6.6.25 @see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#advertising
1170 /* The callback parameter for NimBLEScan::start has been removed and the blocking overload of NimBLEScan::start has been replaced by an overload of NimBLEScan::getResults with the same parameters.
1171 */
1172 SerialDebug.println("Before pScan->getResults\n");
1173
1174 /** Start scanning for advertisers */
1175 pScan->start(_scanTimeMs);
1176
1177 // NimBLEScanResults results = pScan->getResults(_scanTimeMs, false); // note the time is now in milliseconds
1178
1179 //NimBLEScanResults results = pScan->getResults(PSCAN_TIME, false); // note the time is now in milliseconds
1180 SerialDebug.println("After pScan->getResults\n");
1181
1182#else
1183 pScan->start(PSCAN_TIME, scanEndedCB_BLEClient);
1184#endif
1185 //M5.Beep.tone(1000);
1186 // M5.Beep.setVolume(90); //???? not sure this call is working wha
1187}
1188#else
1189//!the setup() and loop() passing the serviceName to look for..
1190void setup_BLEClientNetworking(char *serviceName, char *serviceUUID, char *characteristicUUID)
1191{
1192 //!address to skip (for a number of times) .. how about 1 for now..
1194
1195 //!start the bluetooth discovery..
1196 SerialDebug.println("Starting NimBLE BLEClientNetworking");
1197 /** Initialize NimBLE and set the device name */
1198 NimBLEDevice::init("NimBLE-Client");
1199
1200 /** Optional: set the transmit power */
1201 NimBLEDevice::setPower(3); /** 3dbm */
1202 NimBLEScan* pScan = NimBLEDevice::getScan();
1203
1204 /** Set the callbacks to call when scan events occur, no duplicates */
1205 pScan->setScanCallbacks(&_scanCallbacks, false);
1206
1207 /** Set scan interval (how often) and window (how long) in milliseconds */
1208 pScan->setInterval(100);
1209 pScan->setWindow(100);
1210
1211 /**
1212 * Active scan will gather scan response data from advertisers
1213 * but will use more energy from both devices
1214 */
1215 pScan->setActiveScan(true);
1216
1217 /** Start scanning for advertisers */
1218 pScan->start(_scanTimeMs);
1219 SerialDebug.printf("Scanning for peripherals\n");
1220}
1221#endif
1222
1223//! try to disconnect..
1225{
1226 SerialDebug.println("calling _pClient->disconnect()");
1227
1228 //disconnect../
1229 if (_pClient)
1230 _pClient->disconnect();
1231
1232 //!force saying it's disconnected
1233 _isConnected_BLEClient = false;
1234 _doConnect = true;
1235
1236 SerialDebug.println("DONE calling _pClient->disconnect()");
1237
1238}
1239
1240
1241//!the loop()
1243{
1244 //Try to disconnect ..
1245 // if (_isConnected_BLEClient && !useBLEClient())
1246 if (!useBLEClient())
1247 {
1248 _doConnect = false;
1249 _isConnected_BLEClient = false;
1250 if (_pClient)
1251 {
1252 //SerialDebug.println("calling _pClient->disconnect()");
1253
1254 //disconnect../
1255 _pClient->disconnect();
1256
1257 }
1258 else
1259 {
1260 //SerialDebug.println("_isConnectedBLEClient but no _pClient");
1261 }
1262 }
1263
1264 //_doConnect is a command to try and connect using connectToServer_BLEClient() wha 8-11-21
1265 if (_doConnect == true) {
1266 SerialLots.println("_doConnect == true");
1268 SerialDebug.println("!! Connected to BLE Server.");
1270
1271 //!a specialy display for now..
1272 //! 1 = C connected BLE
1273 //specialScreen_displayModule(1);
1274 _doConnect = false; // TRY 6.11.22 (Family Day)
1275 return; /// try 4.22.22
1276 }
1277 else {
1278#ifdef DONT_USE_ONLY_ONE_CONNECTED
1279 SerialDebug.println("We have failed to connect to the server; there is nothin more we will do.");
1281#endif
1282 }
1283 _doConnect = false;
1284#ifdef M5UNIFIED
1285 //! 6.6.25 @see https://github.com/h2zero/NimBLE-Arduino/blob/master/docs/1.x_to2.x_migration_guide.md#advertising
1286 /*
1287 The callback parameter for NimBLEScan::start has been removed and the blocking overload of NimBLEScan::start ha
1288 */
1289 // NimBLEScanResults results = NimBLEDevice::getScan()->getResults(PSCAN_TIME, false); // note the time is now in milliseconds
1290
1291 //! scan more ..
1292 NimBLEDevice::getScan()->start(_scanTimeMs, false, true);
1293#else
1294 // 0=stop scanning after first device found
1295 NimBLEDevice::getScan()->start(PSCAN_TIME, scanEndedCB_BLEClient); //resume scanning for more BLE servers
1296#endif
1297 }
1298
1299 //!note: https://github.com/espressif/esp-idf/issues/5105
1300 //! Might address the error I see:
1301}
int _skipAddressCount
skip logic
char _skipNameOrAddress_BLEClientNetworking[50]
address to skip (for a number of times) .. how about 1 for now..
void loop_BLEClientNetworking()
the loop()
bool connectToServer_BLEClient()
ScanCallbacks _scanCallbacks
void sendCommandBLEClient(String cmdString)
void stopSkip_BLEClientNetworking()
stops the skip after found something..
boolean isConnectedBLEClient()
returns whether connected over BLE as a client to a server(like a ESP feeder)
NimBLEClient * _pClient
void scanEndedCB_BLEClient(NimBLEScanResults results)
NOTE: this is called all the time... 4.22.22 –even if the "scan-stop" invoked.
void sendFeedCommandBLEClient()
sends the "feed" command over bluetooth to the connected device..
void notifyCB(NimBLERemoteCharacteristic *pRemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
boolean useBLEClient()
returns if the BLEClient is turned on.. note, if connected to a BLE device, then disconnect
void setup_BLEClientNetworking(char *serviceName, char *serviceUUID, char *characteristicUUID)
the setup() and loop() passing the serviceName to look for..
void disconnect_BLEClientNetworking()
try to disconnect..
void skipNameOrAddress_BLEClientNetworking(char *nameOrAddress)
an address or name to skip (for at least 1 time)
boolean containsSkipAddress(String deviceInfo)
helper for skip, checking if an actuall address in the skip name or address
void sendCommandBLEClient_13orLess(String cmdString)
send a string of 13 characters or less
ClientCallbacks _clientCB_BLEClient
int _maxSkipAddressCount
#define PSCAN_INTERVAL
https://esp32.com/viewtopic.php?t=2291
#define BLE_CLIENT_CALLBACK_BLINK_LIGHT
the BLE code wants to blink the light
#define PSCAN_WINDOW
#define PSCAN_TIME
#define BLE_CLIENT_CALLBACK_STATUS_MESSAGE
used to send a string message back (which might be sent to MQTT for example)
void setConnectedBLEDevice_mainModule(char *deviceName, boolean isGEN3)
boolean stopAllProcesses_mainModule()
if stopped
Definition: MainModule.cpp:358
bool containsSubstring(String message, String substring)
check if the string contains the other string. This is a poor man's grammer checker
Definition: MainModule.cpp:765
void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
performs the indirect callback based on the callbackType
Definition: MainModule.cpp:900
#define CALLBACKS_BLE_CLIENT
Definition: MainModule.cpp:791
int getTimeStamp_mainModule()
boolean isValidPairedDevice_mainModule()
returns if the paired device is not NONE. Note, the paired Name might be an address now (see below)
#define PT_CHARACTERISTIC_UUID
Definition: MainModule.h:59
#define PT_SERVICE_UUID
Definition: MainModule.h:58
boolean getDiscoverM5PTClicker()
get option
void savePreferenceBoolean_mainModule(int preferenceID, boolean flag)
save a boolean preference
boolean getPreferenceBoolean_mainModule(int preferenceID)
called to set a preference (which will be an identifier and a string, which can be converted to a num...
char * getPreferenceString_mainModule(int preferenceID)
returns the preference but in it's own string buffer. As long as you use it before calling getPrefere...
#define PREFERENCE_PAIRED_DEVICE_ADDRESS_SETTING
the paired device for guest device feeding (6.6.22) .. but the Address 9.3.22
#define PREFERENCE_ONLY_GEN3_CONNECT_SETTING
if true, only BLEClient connect to GEN3 feeders..
#define PREFERENCE_PAIRED_DEVICE_SETTING
the paired device for guest device feeding (6.6.22)
#define PREFERENCE_MAIN_GATEWAY_VALUE
#define PREFERENCE_MAIN_BLE_CLIENT_VALUE