13#include <NimBLEDevice.h>
14#include "../../Defines.h"
31static NimBLERemoteCharacteristic* _BLEClientCharacteristicFeed;
37static const NimBLEAdvertisedDevice* _advertisedDevice;
39static NimBLEAdvertisedDevice* _advertisedDevice;
42static bool _doConnect =
false;
43static bool _isConnected_BLEClient =
false;
45static uint32_t _scanTimeMs = 5000;
65 SerialTemp.print(
"set skipAddress: ");
66 SerialTemp.println(nameOrAddress);
86 SerialTemp.printf(
"containsSkipAddress(%d): ", flag);
87 SerialTemp.print(deviceInfo);
88 SerialTemp.print(
" skip=");
98 void onConnect(NimBLEClient* pClient)
override
100 void onConnect(NimBLEClient* pClient)
104 SerialMin.println(
" BLE Connected");
123 _isConnected_BLEClient =
true;
127 void onDisconnect(NimBLEClient* pClient,
int reason)
override {
130 SerialDebug.printf(
"%s Disconnected, reason = %d - Starting scan\n", pClient->getPeerAddress().toString().c_str(), reason);
132 void onDisconnect(NimBLEClient* pClient) {
136 SerialMin.println(
" BLE Disconnected - Starting scan");
137 SerialMin.print(pClient->getPeerAddress().toString().c_str());
139 SerialMin.println(
" BLE Disconnected - Starting scan");
140 SerialMin.print(pClient->getPeerAddress().toString().c_str());
144#ifdef M5UNIFIED_notworking_try_old
145 NimBLEDevice::getScan()->start(_scanTimeMs,
false,
true);
156 SerialMin.println(
"*** in OTA update . no scanning ***");
161 _isConnected_BLEClient =
false;
167 uint32_t onPassKeyRequest() {
168 SerialLots.println(
"Client Passkey Request");
173 bool onConfirmPIN(uint32_t pass_key) {
174 SerialLots.print(
"The passkey YES/NO number: ");
175 SerialLots.println(pass_key);
183 void onAuthenticationComplete(NimBLEConnInfo& connInfo)
override
185 if (!connInfo.isEncrypted()) {
186 SerialDebug.printf(
"Encrypt connection failed - disconnecting\n");
188 NimBLEDevice::getClientByHandle(connInfo.getConnHandle())->disconnect();
193 void onAuthenticationComplete(ble_gap_conn_desc* desc) {
194 if (!desc->sec_state.encrypted) {
195 SerialDebug.println(
"Encrypt connection failed - disconnecting");
197 NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
200 _isConnected_BLEClient =
false;
228class AdvertisedDeviceCallbacks :
public NimBLEAdvertisedDeviceCallbacks
231#ifdef M5UNIFIED_notworking
232 void onScanEnd(
const NimBLEScanResults& result,
int reason)
234 SerialLots.printf(
"onScanEnd: %d\n", reason);
236 NimBLEDevice::getScan()->start(_scanTimeMs,
false,
true);
239 void onDiscovered(
const NimBLEAdvertisedDevice* parameter)
241 SerialLots.printf(
"onDiscovered:\n");
244 void onResult( NimBLEAdvertisedDevice* advertisedDevice)
250 void onResult(
const NimBLEAdvertisedDevice* advertisedDevice)
override
252 void onResult(NimBLEAdvertisedDevice* advertisedDevice)
256 SerialLots.printf(
" *** onResult adv, useBLEClient = %d\n",
useBLEClient());
264 SerialLots.print(
"BLE Devices Advertised: ");
265 SerialLots.println(advertisedDevice->toString().c_str());
267 String deviceInfo = advertisedDevice->toString().c_str();
271 boolean foundGEN3 =
false;
274 if (advertisedDevice->isAdvertisingService(NimBLEUUID(
"DEAD")))
276 SerialMin.print(
"Device advertised: ");
277 SerialMin.println(advertisedDevice->getName().c_str());
278 SerialLots.print(
"Device URI: ");
279 SerialLots.println(advertisedDevice->getURI().c_str());
283 if (
getDiscoverM5PTClicker() && (strncmp(advertisedDevice->getName().c_str(), M5_BLE_CLIENT_SERVICE, strlen(M5_BLE_CLIENT_SERVICE)) == 0))
285 SerialDebug.printf(
"** DiscoverM5PTClicker && Found a PTCLICKER .. go for it.. %w\n",advertisedDevice->getName().c_str() );
290 SerialDebug.printf(
"** DiscoverM5PTClicker && **** ESP32 Feeder (%s) but not 'PTClicker M5' skipping..\n", advertisedDevice->getName().c_str());
293 else if (strncmp(advertisedDevice->getName().c_str(), MAIN_BLE_CLIENT_SERVICE, strlen(MAIN_BLE_CLIENT_SERVICE)) != 0)
295 SerialDebug.printf(
" **** ESP32 Feeder (%s) but not 'PTFeeder' skipping..\n", advertisedDevice->getName().c_str());
300 else if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(
PT_SERVICE_UUID) > 0))
303 SerialDebug.println(
" **** Found a GEN3 Device");
306 if (requireGEN3 and !foundGEN3)
308 SerialDebug.println(
" **** Looking for GEN3 but didn't find it .. so not connecting");
313 if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(
PT_SERVICE_UUID) > 0))
315 SerialTemp.println(
"Found candidate BLE Service: ");
316 SerialTemp.println(advertisedDevice->toString().c_str());
317 String deviceInfo = advertisedDevice->toString().c_str();
327 SerialTemp.print(
"Found device, but skip is max .. so connect");
335 SerialTemp.print(
"Found device, but will skip as it contains nameOrAddress: ");
360#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
375 boolean found =
false;
382 SerialTemp.printf(
" containsSubstring(%d, %s)\n", found, pairedDeviceName);
390 SerialTemp.printf(
" containsSubstring(%d, '%s')\n", found, pairedDeviceAddress);
392 if (!found && foundGEN3 && strlen(pairedDeviceAddress)==0)
395 SerialTemp.printf(
" no paired address but a GEN3 so good(%d)\n", found);
401 SerialTemp.println(
"*** FOUND GEN3 PAIRED Device Name: ");
403 SerialTemp.println(
"*** FOUND BLE PAIRED Device Name: ");
405 SerialTemp.println(pairedDeviceName);
410 SerialTemp.println(
" *** Nothing paired ****");
415 SerialTemp.print(
"Not matching desired device name: '");
417 SerialTemp.print(
"' .. or address: ");
431 NimBLEDevice::getScan()->stop();
433 _advertisedDevice = advertisedDevice;
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";
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);
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);
460 SerialLots.println(str.c_str());
467 SerialLots.println(
"Scan Ended");
479 SerialCall.println(
"connectToServer_BLEClient");
480 NimBLEClient* pClient =
nullptr;
487 if (NimBLEDevice::getCreatedClientCount())
490 if (NimBLEDevice::getClientListSize())
497 pClient = NimBLEDevice::getClientByPeerAddress(_advertisedDevice->getAddress());
499 if (!pClient->connect(_advertisedDevice,
false)) {
500 SerialTemp.println(
"Reconnect failed");
503 SerialDebug.println(
"Reconnected pClient");
510 pClient = NimBLEDevice::getDisconnectedClient();
513 SerialTemp.printf(
"Reusing a disconnected pClient: %s\n",pClient? pClient->getPeerAddress().toString().c_str():
"NULL");
530 if (NimBLEDevice::getCreatedClientCount() >= 1 )
532 if (NimBLEDevice::getClientListSize() >= 1 )
535 SerialDebug.println(
"Max clients reached - no more connections available");
539 pClient = NimBLEDevice::createClient();
541 SerialDebug.printf(
"***New client created(%d)\n", pClient);
562 pClient->setConnectionParams(12, 12, 0, 150);
567 pClient->setConnectTimeout(5 * 1000);
570 pClient->setConnectionParams(12, 12, 0, 51);
574 pClient->setConnectTimeout(5);
575 Serial.printf(
"pClient=%d\n",pClient);
576 if (!_advertisedDevice)
578 SerialMin.println(
" **** ERROR: advertisedDevice == NULL");
581 Serial.printf(
"_advertisedDevice=%d\n",_advertisedDevice);
585 if (!pClient->connect(_advertisedDevice))
588 NimBLEDevice::deleteClient(pClient);
589 SerialDebug.println(
"Failed to connect, deleted client");
595 if (!pClient->isConnected())
597 if (!pClient->connect(_advertisedDevice))
599 SerialDebug.printf(
"Failed to connect, deleted client\n");
602 _isConnected_BLEClient =
false;
606 SerialDebug.printf(
"Connected to: %s RSSI: %d\n", pClient->getPeerAddress().toString().c_str(), pClient->getRssi());
615 SerialLots.printf(
"number clients= %d \n\r", NimBLEDevice::getCreatedClientCount());
618 SerialLots.printf(
"number clients= %d \n\r", NimBLEDevice::getClientListSize());
621 SerialMin.print(
" - Connected to pClient: ");
622 SerialMin.println(pClient->getPeerAddress().toString().c_str());
623 SerialLots.print(
"RSSI: ");
624 SerialLots.println(pClient->getRssi());
627 NimBLERemoteService* pSvc =
nullptr;
628 NimBLERemoteCharacteristic* pChr =
nullptr;
629 NimBLERemoteDescriptor* pDsc =
nullptr;
636 pSvc = pClient->getService(
"DEAD");
640 SerialTemp.printf(
"*** v2.0 This is an ESP Based Feeder (not GEN3)***\n");
648 SerialTemp.println(
"*** v2.0 This is an GEN3 Feeder (not ESP32)***");
657 pSvc = pClient->getService(_BLEClientServiceUUID);
660 pChr = pSvc->getCharacteristic(_BLEClientCharacteristicUUID);
661 _BLEClientCharacteristicFeed = pChr;
664 SerialLots.println(
" **** BLEClientNetworking is nil in creation...");
670 SerialLots.print(pChr->getUUID().toString().c_str());
671 SerialLots.print(
" Value: ");
672 SerialLots.println(pChr->readValue().c_str());
677#ifdef DO_IT_ANOTHER_WAY_WITHOUT_SENDING_VALUE
678 String sentValue =
"_ESP_32";
680 if (pChr->canWrite())
684 if (pChr->writeValue(sentValue)) {
686 SerialDebug.print(
"Wrote new value(1) to: ");
687 SerialDebug.println(pChr->getUUID().toString().c_str());
688 SerialDebug.printf(
"'%s'\n", sentValue);
692 SerialDebug.println(
"Disconnecting if write failed");
694 pClient->disconnect();
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)
710 SerialTemp.printf(
"*** This is an ESP Based Feeder (not GEN3)***\n");
718 SerialTemp.println(
"*** This is an GEN3 Feeder (not ESP32)***");
733 if (pChr->canNotify())
736 if (!pChr->subscribe(
true,
notifyCB)) {
738 pClient->disconnect();
743 else if (pChr->canIndicate())
748 if (!pChr->subscribe(
false,
notifyCB))
751 pClient->disconnect();
760 SerialLots.println(
"DEAD service not found.");
775 SerialDebug.print(pChr->getUUID().toString().c_str());
776 SerialDebug.print(
" Value: ");
777 SerialDebug.println(pChr->readValue().c_str());
789#ifdef NOT_USED_FOR_SOME_REASON
790 pDsc = pChr->getDescriptor(NimBLEUUID(
"C01D"));
792 SerialDebug.println(
" .. DOESNT GET HERE");
796 SerialDebug.print(
"Descriptor: ");
797 SerialDebug.print(pDsc->getUUID().toString().c_str());
798 SerialDebug.print(
" Value: ");
799 SerialDebug.println(pDsc->readValue().c_str());
801 SerialDebug.println(
" .. 111");
803 if (pChr->canWrite())
805 if (pChr->writeValue(
"No tip!")) {
806 SerialDebug.print(
"Wrote new value(2) to: ");
807 SerialDebug.println(pChr->getUUID().toString().c_str());
811 pClient->disconnect();
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());
822 SerialDebug.println(
" .. 222");
828 if (pChr->canNotify()) {
830 if (!pChr->subscribe(
true,
notifyCB)) {
832 pClient->disconnect();
836 else if (pChr->canIndicate()) {
839 if (!pChr->subscribe(
false,
notifyCB)) {
841 pClient->disconnect();
845 SerialDebug.println(
" .. 333");
851 SerialLots.println(
"BAAD service not found.");
854 SerialDebug.println(
"Done with this device!");
865 boolean isConnected = _isConnected_BLEClient;
867 SerialLots.printf(
"isConnectedBLEClient: %d\n",isConnected);
874 SerialLots.println(
"sendFeedCommandBLEClient()");
878 std::string newValue =
"s";
879 const uint8_t newValueFeed = { 0x00 };
880 if (!_BLEClientCharacteristicFeed)
882 SerialLots.println(
" **** Error _BLEClientCharacteristicFeed is nil ***");
885 if (_BLEClientCharacteristicFeed->writeValue(newValueFeed, 1)) {
886 SerialMin.print(
"BLEClient writeValue: '");
887 SerialMin.print(newValue.c_str());
888 SerialMin.println(
"' - sent FEED");
904 SerialDebug.print(newValue.c_str());
905 SerialDebug.println(
"FAILED GATT write(1)");
912 if (_BLEClientCharacteristicFeed->canRead()) {
913 std::string value = _BLEClientCharacteristicFeed->readValue();
914 SerialTemp.printf(
"BLE Server response: '%s'\n",(value[0]==0x01)?(
char*)
"01":(
char*)
"");
917 if (value[0] == 0x01) {
932 SerialDebug.println(
"Didn't get a response 0x01");
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");
963 if (cmdString.length() > 0)
965 SerialDebug.println(
" *** GEN3 and command longer than 1 character .. not sending");
974 int len = cmdString.length();
975 String startCmd =
"#MSG_START";
978 for (
int i = 0; i < len;i+=13)
981 if (start + 13 > cmdString.length())
982 s = cmdString.substring(start);
984 s = cmdString.substring(start,start+13);
993 String endCmd =
"#MSG_END";
1000 SerialDebug.print(
"sendCommandBLEClient13(");
1001 SerialDebug.print(cmdString.length());
1002 SerialDebug.print(
"): '");
1003 SerialDebug.print(cmdString);
1004 SerialDebug.println(
"'");
1011 if (!_BLEClientCharacteristicFeed)
1013 SerialDebug.println(
" **** Error _BLEClientCharacteristicFeed is nil ***");
1016 if (_BLEClientCharacteristicFeed->writeValue(cmdString, cmdString.length()),
true) {
1017 SerialDebug.print(
"writeValue:");
1018 SerialDebug.println(cmdString.c_str());
1022 SerialDebug.print(cmdString.c_str());
1023 SerialDebug.println(
"FAILED GATT write(2)");
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) {
1049 SerialDebug.println(
"Didn't get a response 0x01");
1068 SerialDebug.println(
"Starting NimBLE BLEClientNetworking");
1071 NimBLEDevice::init(serviceName);
1096 NimBLEDevice::setSecurityAuth( BLE_SM_PAIR_AUTHREQ_SC);
1099#ifdef M5UNIFIED_notworking
1108 SerialDebug.printf(
"NimBLEDevice::setPower %d\n", value);
1110 NimBLEDevice::setPower(value);
1117 NimBLEDevice::setPower(3);
1120 NimBLEDevice::setPower(ESP_PWR_LVL_P9);
1129 NimBLEScan* pScan = NimBLEDevice::getScan();
1144 pScan->setAdvertisedDeviceCallbacks(
new AdvertisedDeviceCallbacks());
1150#ifdef not_bootstrap_NOT_NOW
1156 pScan->setInterval(100);
1157 pScan->setWindow(100);
1164 pScan->setActiveScan(
true);
1172 SerialDebug.println(
"Before pScan->getResults\n");
1175 pScan->start(_scanTimeMs);
1180 SerialDebug.println(
"After pScan->getResults\n");
1196 SerialDebug.println(
"Starting NimBLE BLEClientNetworking");
1198 NimBLEDevice::init(
"NimBLE-Client");
1201 NimBLEDevice::setPower(3);
1202 NimBLEScan* pScan = NimBLEDevice::getScan();
1208 pScan->setInterval(100);
1209 pScan->setWindow(100);
1215 pScan->setActiveScan(
true);
1218 pScan->start(_scanTimeMs);
1219 SerialDebug.printf(
"Scanning for peripherals\n");
1226 SerialDebug.println(
"calling _pClient->disconnect()");
1233 _isConnected_BLEClient =
false;
1236 SerialDebug.println(
"DONE calling _pClient->disconnect()");
1249 _isConnected_BLEClient =
false;
1265 if (_doConnect ==
true) {
1266 SerialLots.println(
"_doConnect == true");
1268 SerialDebug.println(
"!! Connected to BLE Server.");
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.");
1292 NimBLEDevice::getScan()->start(_scanTimeMs,
false,
true);
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)
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
#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 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
bool containsSubstring(String message, String substring)
check if the string contains the other string. This is a poor man's grammer checker
void callCallbackMain(int callbacksModuleId, int callbackType, char *message)
performs the indirect callback based on the callbackType
#define CALLBACKS_BLE_CLIENT
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
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