I'm working on BLE based on ESP32.
I configured a custom Service and Characteristics with UUID.
Using 2 ESP32 Dev modules. I can connect them together, but the Client module doesn't disconnect and connect to the new UUID.
I need help disconnecting the Client from Server (UUID suppose 001) and connecting it to Server with UUID (let 002).
I couldn't find any function to disconnect clients from servers.
Below code for Client Node
/** * A BLE client example that is rich in capabilities. * There is a lot new capabilities implemented. * author unknown * updated by chegewara */ #include "BLEDevice.h" //#include "BLEScan.h" // The remote service we wish to connect to. static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331915b"); // The characteristic of the remote service we are interested in. static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b215b"); static boolean doConnect = false; static boolean connected = false; static boolean doScan = false; static BLERemoteCharacteristic* pRemoteCharacteristic; static BLEAdvertisedDevice* myDevice; static void notifyCallback( BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { Serial.print("Notify callback for characteristic "); Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); Serial.print(" of data length "); Serial.println(length); Serial.print("data: "); Serial.println((char*)pData); } class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("Conecction with server"); } void onDisconnect(BLEClient* pclient) { connected = false; Serial.println("onDisconnect"); } }; uint8_t count =0; bool connectToServer() { Serial.print("Forming a connection to "); Serial.println(myDevice->getAddress().toString().c_str()); BLEClient* pClient = BLEDevice::createClient(); Serial.println(" - Created client"); pClient->setClientCallbacks(new MyClientCallback()); // Connect to the remove BLE Server. pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private) Serial.println(" - Connected to server"); pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise) // if(count>5) { pClient->disconnect(); static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b214b"); Serial.println("DISCONNECTION \n\n"); return false; } // Obtain a reference to the service we are after in the remote BLE server. BLERemoteService* pRemoteService = pClient->getService(serviceUUID); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(serviceUUID.toString().c_str()); pClient->disconnect(); return false; } Serial.println(" - Found our service"); // Obtain a reference to the characteristic in the service of the remote BLE server. pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); if (pRemoteCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID: "); Serial.println(charUUID.toString().c_str()); pClient->disconnect(); return false; } Serial.println(" - Found our characteristic"); // Read the value of the characteristic. if(pRemoteCharacteristic->canRead()) { std::string value = pRemoteCharacteristic->readValue(); Serial.print("The characteristic value was: "); Serial.println(value.c_str()); } if(pRemoteCharacteristic->canNotify()) pRemoteCharacteristic->registerForNotify(notifyCallback); connected = true; return true; } /** * Scan for BLE servers and find the first one that advertises the service we are looking for. */ class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { /** * Called for each advertising BLE server. */ void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); // We have found a device, let us now see if it contains the service we are looking for. if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) { BLEDevice::getScan()->stop(); myDevice = new BLEAdvertisedDevice(advertisedDevice); doConnect = true; doScan = true; } // Found our server } // onResult }; // MyAdvertisedDeviceCallbacks void setup() { Serial.begin(115200); Serial.println("Starting Arduino BLE Client application..."); BLEDevice::init(""); // Retrieve a Scanner and set the callback we want to use to be informed when we // have detected a new device. Specify that we want active scanning and start the // scan to run for 5 seconds. BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setInterval(1349); pBLEScan->setWindow(449); pBLEScan->setActiveScan(true); pBLEScan->start(5, false); } // End of setup. // This is the Arduino main loop function. void loop() { // If the flag "doConnect" is true then we have scanned for and found the desired // BLE Server with which we wish to connect. Now we connect to it. Once we are // connected we set the connected flag to be true. if (doConnect == true) { if (connectToServer()) { Serial.println("We are now connected to the BLE Server."); } else { Serial.println("We have failed to connect to the server; there is nothin more we will do."); } doConnect = false; } // If we are connected to a peer BLE Server, update the characteristic each time we are reached // with the current time since boot. if (connected) { String newValue = "Time since boot: " + String(millis()/1000); Serial.println("Setting new characteristic value to \"" + newValue + "\""); // Set the characteristic's value to be the array of bytes that is actually a string. pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); }else if(doScan){ BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino } count++; delay(1000); // Delay a second between loops. } // End of loop
After Count reaches to greater than 5, I run below part for
client->disconnect
if(count>5) { pClient->disconnect(); static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b214b"); Serial.println("DISCONNECTION \n\n"); return false; }
Below code for Server Node
/* Video: https://www.youtube.com/watch?v=oCMOYS71NIU Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp Ported to Arduino ESP32 by Evandro Copercini updated by chegewara Create a BLE server that, once we receive a connection, will send periodic notifications. The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8 The design of creating the BLE server is: 1. Create a BLE Server 2. Create a BLE Service 3. Create a BLE Characteristic on the Service 4. Create a BLE Descriptor on the characteristic 5. Start the service. 6. Start advertising. A connect hander associated with the server starts a background task that performs notification every couple of seconds. */ #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> BLEServer* pServer = NULL; BLECharacteristic* pCharacteristic = NULL; bool deviceConnected = false; bool oldDeviceConnected = false; uint32_t value = 0; // See the following for generating UUIDs: // https://www.uuidgenerator.net/ #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b214b" class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { Serial.println("Conecction with client"); deviceConnected = true; BLEDevice::startAdvertising(); }; void onDisconnect(BLEServer* pServer) { Serial.println("Disconnection with client"); deviceConnected = false; } }; uint8_t once1 = 0; void setup() { Serial.begin(115200); // Create the BLE Device BLEDevice::init("ESP32"); // Create the BLE Server pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE ); // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml // Create a BLE Descriptor pCharacteristic->addDescriptor(new BLE2902()); // Start the service pService->start(); // Start advertising BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(false); pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter BLEDevice::startAdvertising(); Serial.println("Waiting a client connection to notify..."); } void loop() { // notify changed value // if (deviceConnected) { // pCharacteristic->setValue((uint8_t*)&value, 4); // pCharacteristic->notify(); // } value++; delay(2000); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms // disconnecting if (!deviceConnected && oldDeviceConnected) { delay(500); // give the bluetooth stack the chance to get things ready pServer->startAdvertising(); // restart advertising Serial.println("start advertising"); oldDeviceConnected = deviceConnected; } // connecting if (deviceConnected && !oldDeviceConnected) { // do stuff here on connecting oldDeviceConnected = deviceConnected; } }
Anyone can guide me how can I achieve this? All I need is resetting way for Service and Characteristics for either client or server node.