14#include "../../Defines.h"
31static NimBLERemoteCharacteristic* _BLEClientCharacteristicFeed;
36static NimBLEAdvertisedDevice* _advertisedDevice;
38static bool _doConnect =
false;
39static bool _isConnected_BLEClient =
false;
58 SerialTemp.print(
"set skipAddress: ");
59 SerialTemp.println(nameOrAddress);
79 SerialTemp.printf(
"containsSkipAddress(%d): ", flag);
80 SerialTemp.print(deviceInfo);
81 SerialTemp.print(
" skip=");
90 void onConnect(NimBLEClient* pClient) {
92 SerialMin.println(
" BLE Connected");
107 pClient->updateConnParams(120, 120, 0, 60);
111 _isConnected_BLEClient =
true;
114 void onDisconnect(NimBLEClient* pClient) {
118 SerialMin.println(
" BLE Disconnected - Starting scan");
119 SerialMin.print(pClient->getPeerAddress().toString().c_str());
127 SerialMin.println(
"*** in OTA update . no scanning ***");
132 _isConnected_BLEClient =
false;
139 bool onConnParamsUpdateRequest(NimBLEClient* pClient,
const ble_gap_upd_params* params) {
141 SerialMin.println(
" onConnParamsUpdateRequest");
142 if (params->itvl_min < 24) {
145 else if (params->itvl_max > 40) {
148 else if (params->latency > 2) {
151 else if (params->supervision_timeout > 100) {
160 uint32_t onPassKeyRequest() {
161 SerialLots.println(
"Client Passkey Request");
166 bool onConfirmPIN(uint32_t pass_key) {
167 SerialLots.print(
"The passkey YES/NO number: ");
168 SerialLots.println(pass_key);
174 void onAuthenticationComplete(ble_gap_conn_desc* desc) {
175 if (!desc->sec_state.encrypted) {
176 SerialDebug.println(
"Encrypt connection failed - disconnecting");
178 NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
181 _isConnected_BLEClient =
false;
191 void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
192 SerialLots.printf(
" *** onResult adv, useBLEClient = %d\n",
useBLEClient());
200 SerialLots.print(
"BLE Devices Advertised: ");
201 SerialLots.println(advertisedDevice->toString().c_str());
203 String deviceInfo = advertisedDevice->toString().c_str();
205 SerialLots.print(
"Device advertised: ");
206 SerialLots.println(advertisedDevice->getName().c_str());
207 SerialLots.print(
"Device URI: ");
208 SerialLots.println(advertisedDevice->getURI().c_str());
210 boolean foundGEN3 =
false;
213 if (advertisedDevice->isAdvertisingService(NimBLEUUID(
"DEAD")))
217 if (
getDiscoverM5PTClicker() && (strncmp(advertisedDevice->getName().c_str(), M5_BLE_CLIENT_SERVICE, strlen(M5_BLE_CLIENT_SERVICE)) == 0))
219 SerialDebug.printf(
"** DiscoverM5PTClicker && Found a PTCLICKER .. go for it.. %w\n",advertisedDevice->getName().c_str() );
224 SerialDebug.printf(
"** DiscoverM5PTClicker && **** ESP32 Feeder (%s) but not 'PTClicker M5' skipping..\n", advertisedDevice->getName().c_str());
227 else if (strncmp(advertisedDevice->getName().c_str(), MAIN_BLE_CLIENT_SERVICE, strlen(MAIN_BLE_CLIENT_SERVICE)) != 0)
229 SerialDebug.printf(
" **** ESP32 Feeder (%s) but not 'PTFeeder' skipping..\n", advertisedDevice->getName().c_str());
234 else if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(
PT_SERVICE_UUID) > 0))
237 SerialDebug.println(
" **** Found a GEN3 Device");
240 if (requireGEN3 and !foundGEN3)
242 SerialDebug.println(
" **** Looking for GEN3 but didn't find it .. so not connecting");
247 if (advertisedDevice->isAdvertisingService(NimBLEUUID(_BLEClientServiceUUID)) || (deviceInfo.indexOf(
PT_SERVICE_UUID) > 0))
249 SerialTemp.println(
"Found candidate BLE Service: ");
250 SerialTemp.println(advertisedDevice->toString().c_str());
251 String deviceInfo = advertisedDevice->toString().c_str();
261 SerialTemp.print(
"Found device, but skip is max .. so connect");
269 SerialTemp.print(
"Found device, but will skip as it contains nameOrAddress: ");
294#ifdef NO_MORE_PREFERENCE_BLE_USE_DISCOVERED_PAIRED_DEVICE_SETTING
309 boolean found =
false;
316 SerialTemp.printf(
" containsSubstring(%d, %s)\n", found, pairedDeviceName);
324 SerialTemp.printf(
" containsSubstring(%d, '%s')\n", found, pairedDeviceAddress);
326 if (!found && foundGEN3 && strlen(pairedDeviceAddress)==0)
329 SerialTemp.printf(
" no paired address but a GEN3 so good(%d)\n", found);
335 SerialTemp.println(
"*** FOUND GEN3 PAIRED Device Name: ");
337 SerialTemp.println(
"*** FOUND BLE PAIRED Device Name: ");
339 SerialTemp.println(pairedDeviceName);
344 SerialTemp.println(
" *** Nothing paired ****");
349 SerialTemp.print(
"Not matching desired device name: '");
351 SerialTemp.print(
"' .. or address: ");
365 NimBLEDevice::getScan()->stop();
367 _advertisedDevice = advertisedDevice;
376void notifyCB(NimBLERemoteCharacteristic* pRemoteCharacteristic, uint8_t* pData,
size_t length,
bool isNotify) {
377#if (SERIAL_DEBUG_DEBUG)
378 std::string str = (isNotify ==
true) ?
"Notification" :
"Indication";
381 str += std::string(pRemoteCharacteristic->getRemoteService()->getClient()->getPeerAddress());
382 str +=
": Service = " + std::string(pRemoteCharacteristic->getRemoteService()->getUUID());
383 str +=
", Characteristic = " + std::string(pRemoteCharacteristic->getUUID());
384 str +=
", Value = " + std::string((
char*)pData, length);
385 SerialDebug.println(str.c_str());
392 SerialLots.println(
"Scan Ended");
401 SerialCall.println(
"connectToServer_BLEClient");
402 NimBLEClient* pClient =
nullptr;
404 if (NimBLEDevice::getClientListSize()) {
409 pClient = NimBLEDevice::getClientByPeerAddress(_advertisedDevice->getAddress());
411 if (!pClient->connect(_advertisedDevice,
false)) {
412 SerialLots.println(
"Reconnect failed");
415 SerialLots.println(
"Reconnected pClient");
422 pClient = NimBLEDevice::getDisconnectedClient();
425 SerialLots.printf(
"Reusing a disconnected pClient: %s\n",pClient? pClient->getPeerAddress().toString().c_str():
"NULL");
434#ifdef ONLY_DIFFERENCE_FROM_WORKING_VERSION
435 if (NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS)
437 if (NimBLEDevice::getClientListSize() >= 1 )
444 pClient = NimBLEDevice::createClient();
446 SerialDebug.printf(
"***New client created(%d)\n", pClient);
448 pClient->setClientCallbacks(&_clientCB_BLEClient,
false);
465 pClient->setConnectionParams(12, 12, 0, 51);
469 pClient->setConnectTimeout(5);
470 Serial.printf(
"pClient=%d\n",pClient);
471 if (!_advertisedDevice)
473 SerialMin.println(
" **** ERROR: advertisedDevice == NULL");
476 Serial.printf(
"_advertisedDevice=%d\n",_advertisedDevice);
478 if (!pClient->connect(_advertisedDevice)) {
481 NimBLEDevice::deleteClient(pClient);
482 SerialDebug.println(
"Failed to connect, deleted client");
490 if (!pClient->isConnected()) {
491 if (!pClient->connect(_advertisedDevice)) {
492 SerialDebug.println(
"Failed to connect");
495 _isConnected_BLEClient =
false;
501 SerialLots.printf(
"number clients= %d \n\r", NimBLEDevice::getClientListSize());
503 SerialMin.print(
" - Connected to pClient: ");
504 SerialMin.println(pClient->getPeerAddress().toString().c_str());
505 SerialLots.print(
"RSSI: ");
506 SerialLots.println(pClient->getRssi());
509 NimBLERemoteService* pSvc =
nullptr;
510 NimBLERemoteCharacteristic* pChr =
nullptr;
511 NimBLERemoteDescriptor* pDsc =
nullptr;
515 pSvc = pClient->getService(
"DEAD");
519 SerialTemp.printf(
"*** v2.0 This is an ESP Based Feeder (not GEN3)***\n");
527 SerialTemp.println(
"*** v2.0 This is an GEN3 Feeder (not ESP32)***");
536 pSvc = pClient->getService(_BLEClientServiceUUID);
539 pChr = pSvc->getCharacteristic(_BLEClientCharacteristicUUID);
540 _BLEClientCharacteristicFeed = pChr;
543 SerialLots.println(
" **** BLEClientNetworking is nil in creation...");
549 SerialLots.print(pChr->getUUID().toString().c_str());
550 SerialLots.print(
" Value: ");
551 SerialLots.println(pChr->readValue().c_str());
556#ifdef DO_IT_ANOTHER_WAY_WITHOUT_SENDING_VALUE
557 String sentValue =
"_ESP_32";
559 if (pChr->canWrite())
563 if (pChr->writeValue(sentValue)) {
565 SerialDebug.print(
"Wrote new value(1) to: ");
566 SerialDebug.println(pChr->getUUID().toString().c_str());
567 SerialDebug.printf(
"'%s'\n", sentValue);
571 SerialDebug.println(
"Disconnecting if write failed");
573 pClient->disconnect();
581 SerialDebug.print(
"The value(1) of: ");
582 SerialDebug.print(pChr->getUUID().toString().c_str());
583 SerialDebug.print(
" is now: '");
584 SerialDebug.print(pChr->readValue().c_str());
585 SerialDebug.println(
"'");
586 if (sentValue.compareTo(pChr->readValue().c_str()) == 0)
589 SerialTemp.printf(
"*** This is an ESP Based Feeder (not GEN3)***\n");
597 SerialTemp.println(
"*** This is an GEN3 Feeder (not ESP32)***");
612 if (pChr->canNotify())
615 if (!pChr->subscribe(
true,
notifyCB)) {
617 pClient->disconnect();
622 else if (pChr->canIndicate())
627 if (!pChr->subscribe(
false,
notifyCB))
630 pClient->disconnect();
639 SerialLots.println(
"DEAD service not found.");
654 SerialDebug.print(pChr->getUUID().toString().c_str());
655 SerialDebug.print(
" Value: ");
656 SerialDebug.println(pChr->readValue().c_str());
668#ifdef NOT_USED_FOR_SOME_REASON
669 pDsc = pChr->getDescriptor(NimBLEUUID(
"C01D"));
671 SerialDebug.println(
" .. DOESNT GET HERE");
675 SerialDebug.print(
"Descriptor: ");
676 SerialDebug.print(pDsc->getUUID().toString().c_str());
677 SerialDebug.print(
" Value: ");
678 SerialDebug.println(pDsc->readValue().c_str());
680 SerialDebug.println(
" .. 111");
682 if (pChr->canWrite())
684 if (pChr->writeValue(
"No tip!")) {
685 SerialDebug.print(
"Wrote new value(2) to: ");
686 SerialDebug.println(pChr->getUUID().toString().c_str());
690 pClient->disconnect();
694 if (pChr->canRead()) {
695 SerialDebug.print(
"The value(2) of: ");
696 SerialDebug.print(pChr->getUUID().toString().c_str());
697 SerialDebug.print(
" is now: ");
698 SerialDebug.println(pChr->readValue().c_str());
701 SerialDebug.println(
" .. 222");
707 if (pChr->canNotify()) {
709 if (!pChr->subscribe(
true,
notifyCB)) {
711 pClient->disconnect();
715 else if (pChr->canIndicate()) {
718 if (!pChr->subscribe(
false,
notifyCB)) {
720 pClient->disconnect();
724 SerialDebug.println(
" .. 333");
730 SerialLots.println(
"BAAD service not found.");
733 SerialDebug.println(
"Done with this device!");
744 boolean isConnected = _isConnected_BLEClient;
746 SerialLots.printf(
"isConnectedBLEClient: %d\n",isConnected);
753 SerialLots.println(
"sendFeedCommandBLEClient()");
757 std::string newValue =
"s";
758 const uint8_t newValueFeed = { 0x00 };
759 if (!_BLEClientCharacteristicFeed)
761 SerialLots.println(
" **** Error _BLEClientCharacteristicFeed is nil ***");
764 if (_BLEClientCharacteristicFeed->writeValue(newValueFeed, 1)) {
765 SerialMin.print(
"BLEClient writeValue: '");
766 SerialMin.print(newValue.c_str());
767 SerialMin.println(
"' - sent FEED");
783 SerialDebug.print(newValue.c_str());
784 SerialDebug.println(
"FAILED GATT write(1)");
791 if (_BLEClientCharacteristicFeed->canRead()) {
792 std::string value = _BLEClientCharacteristicFeed->readValue();
793 SerialTemp.printf(
"BLE Server response: '%s'\n",(value[0]==0x01)?(
char*)
"01":(
char*)
"");
796 if (value[0] == 0x01) {
811 SerialDebug.println(
"Didn't get a response 0x01");
831 SerialDebug.print(
"sendCommandBLEClient(");
832 SerialDebug.print(cmdString.length());
833 SerialDebug.print(
"): '");
834 SerialDebug.print(cmdString);
835 SerialDebug.print(
"' gateway=");
837 SerialDebug.println(isGatewayGEN3?
"gen3":
"esp32");
842 if (cmdString.length() > 0)
844 SerialDebug.println(
" *** GEN3 and command longer than 1 character .. not sending");
853 int len = cmdString.length();
854 String startCmd =
"#MSG_START";
857 for (
int i = 0; i < len;i+=13)
860 if (start + 13 > cmdString.length())
861 s = cmdString.substring(start);
863 s = cmdString.substring(start,start+13);
872 String endCmd =
"#MSG_END";
879 SerialDebug.print(
"sendCommandBLEClient13(");
880 SerialDebug.print(cmdString.length());
881 SerialDebug.print(
"): '");
882 SerialDebug.print(cmdString);
883 SerialDebug.println(
"'");
890 if (!_BLEClientCharacteristicFeed)
892 SerialDebug.println(
" **** Error _BLEClientCharacteristicFeed is nil ***");
895 if (_BLEClientCharacteristicFeed->writeValue(cmdString, cmdString.length()),
true) {
896 SerialDebug.print(
"writeValue:");
897 SerialDebug.println(cmdString.c_str());
901 SerialDebug.print(cmdString.c_str());
902 SerialDebug.println(
"FAILED GATT write(2)");
909 if (_BLEClientCharacteristicFeed->canRead()) {
910 std::string value = _BLEClientCharacteristicFeed->readValue();
911 SerialLots.print(
"BLE Server response: '");
912 SerialLots.print(value.c_str()); SerialDebug.println(
"'");
913 if (value[0] == 0x01) {
928 SerialDebug.println(
"Didn't get a response 0x01");
946 SerialDebug.println(
"Starting NimBLE BLEClientNetworking");
948 NimBLEDevice::init(
"");
972 NimBLEDevice::setSecurityAuth( BLE_SM_PAIR_AUTHREQ_SC);
975 NimBLEDevice::setPower(ESP_PWR_LVL_P9);
981 NimBLEScan* pScan = NimBLEDevice::getScan();
997 pScan->setActiveScan(
true);
1009 SerialDebug.println(
"calling _pClient->disconnect()");
1016 _isConnected_BLEClient =
false;
1019 SerialDebug.println(
"DONE calling _pClient->disconnect()");
1032 _isConnected_BLEClient =
false;
1048 if (_doConnect ==
true) {
1049 SerialLots.println(
"_doConnect == true");
1051 SerialDebug.println(
"!! Connected to BLE Server.");
1061#ifdef DONT_USE_ONLY_ONE_CONNECTED
1062 SerialDebug.println(
"We have failed to connect to the server; there is nothin more we will do.");
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()
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
#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