nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.37k stars 710 forks source link

Multiple Servers #538

Open luizahiginoss opened 6 years ago

luizahiginoss commented 6 years ago

I'm trying to develop a bluetooth network with one client and several servers, but they communicate with the client based on "notify". If they have the same service UUID and characteristic UUID i won't be able to do that? Probably i'm just getting confused with GATT and GAP aplications for BLE... Can u help me?

I haven't started the tests yet, but I'm using the BLE examples...

outlandnish commented 6 years ago

@luizahiginoss https://github.com/nkolban/esp32-snippets/pull/541 should help. I made this mod and use it with PlatformIO / ESP32 quite successfully with multiple servers that have the same service and characteristic UUIDs.

luizahiginoss commented 6 years ago

I tried to use one ESP32 as the client and other 3 ESPs as servers. The client only connect with one server and receive the value from its characteristic. The other 2 continue to advertise, but their characteristics values are never showed and the connection never completed.

luizahiginoss commented 6 years ago

The client code I'm using is the one below

/**
 * A BLE client example that is rich in capabilities.
 */

#include "BLEDevice.h"
//#include "BLEScan.h"

// The remote service we wish to connect to.
static BLEUUID serviceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59");
// The characteristic of the remote service we are interested in.
static BLEUUID    charUUID("0d563a58-196a-48ce-ace2-dfec78acc814");

static BLEAddress *pServerAddress;
static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
const uint8_t v[]={0x1,0x0};

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);
}

bool connectToServer(BLEAddress pAddress) {
    Serial.print("Forming a connection to ");
    Serial.println(pAddress.toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    // Connect to the remove BLE Server.
    pClient->connect(pAddress);
    Serial.println(" - Connected to server");

    // 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());
      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());
      return false;
    }
    Serial.println(" - Found our characteristic");

    // Read the value of the characteristic.
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());

    pRemoteCharacteristic->registerForNotify(notifyCallback);
    pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)v,2,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.getServiceUUID().equals(serviceUUID)) {

      // 
      Serial.print("Found our device!  address: "); 
      advertisedDevice.getScan()->stop();

      pServerAddress = new BLEAddress(advertisedDevice.getAddress());
      doConnect = 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 30 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
} // 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(*pServerAddress)) {
      Serial.println("We are now connected to the BLE Server.");
      connected = true;
    } 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 + "\"");
    std::string value = pRemoteCharacteristic->readValue();
    Serial.print("The characteristic value was: ");
    Serial.println(value.c_str());

    //pRemoteCharacteristic->registerForNotify(notifyCallback);
    // Set the characteristic's value to be the array of bytes that is actually a string.
    //pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
  }

  delay(1000); // Delay a second between loops.
} // End of loop

And the Notify code I'm using is the one below

/*
    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
   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;
uint8_t value = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "91bad492-b950-4226-aa2b-4ede9fa42f59"
#define CHARACTERISTIC_UUID "0d563a58-196a-48ce-ace2-dfec78acc814"

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

void setup() {
  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init("ESP30");

  // 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();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);    //<--- ADD THIS LINE
  pAdvertising->start();
  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
    // notify changed value
    if (deviceConnected) {
        pCharacteristic->setValue("Hello world says Luli");
        pCharacteristic->notify();
        value++;
        delay(20000); // bluetooth stack will go into congestion, if too many packets are sent
    }
    // 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;
    }
}
outlandnish commented 6 years ago

It looks like the code above doesn't try connecting because doConnect gets set to false after the first connection. I can post an example of it connecting to multiple servers later today.

luizahiginoss commented 6 years ago

Ok! Ty

luizahiginoss commented 6 years ago

I was able to connect two devices (now using server code) making a few changes in the Client code. It works for at least 1 ou 2 minutes.

Forming a connection to 30:ae:a4:92:0b:be
 - Created client
 - Connected to server
 - Found our service
 - Found our characteristic
The characteristic value was: Hello World says Xastre
We are now connected to the BLE Server. 1
E (167657) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
E (167659) BT: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
Forming a connection to 30:ae:a4:92:6b:72
 - Created client
 - Connected to server
 - Found our service
 - Found our characteristic
The characteristic value was: Hello World says Luli
We are now connected to the BLE Server 2.
E (171227) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
E (171230) BT: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
Forming a connection to 30:ae:a4:92:0b:be
 - Created client
 - Connected to server
 - Found our service
 - Found our characteristic
The characteristic value was: Hello World says Xastre
We are now connected to the BLE Server. 1
E (174902) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
E (174905) BT: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016

--> So far, the messages are completely normal because I am using pClient->disconnect();, and then this happens

Forming a connection to 30:ae:a4:92:6b:72
 - Created client
E (178064) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x003e
E (178065) BT: p_conn is NULL in bta_gattc_conn_cback

E (178066) BT: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x003e
E (178073) BT: p_conn is NULL in bta_gattc_conn_cback

We are now connected to the BLE Server 2.

We are now connected to the BLE Server 2.
Forming a connection to 30:ae:a4:92:0b:be
 - Created client
 - Connected to server
 - Found our service
 - Found our characteristic
The characteristic value was: Hello World says Xastre
We are now connected to the BLE Server. 1
E (181757) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
E (181760) BT: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
E (181767) BT: bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0016
Forming a connection to 30:ae:a4:92:6b:72
 - Created client
E (184756) BT: application already registered.
E (184756) BT: Register with GATT stack failed.

E (184758) BT: application already registered.
E (184762) BT: Register with GATT stack failed.

E (184766) BT: bta_gattc_process_api_open Failed, unknown client_if: 0

After this, everything stops.

The code I'm using for client is in this txt file

BLE_client.txt

Donderda commented 6 years ago

Were you able to fix this problem?

luizahiginoss commented 6 years ago

No, I wasn't...

mangooose commented 6 years ago

Can you please provide multiple servers connection example? I was able to connect to 2 servers and get the characteristics but somehow writeValue works only for the first server and hangs there.

chegewara commented 6 years ago

@luizahiginoss @mangooose @Donderda @nsamala Ok, i have good news. I have working code for one esp32 client connecting to multiple peripherals. As for now works connecting, disconnecting and register for notifications with receiving notifications of course.

Only thing that does not work for me, but im pretty sure its because of my simplified main_app code, is write to remote characteristic. In theory it suppose to work too.

All i have to do now is to cleanup code and make some improvements, because i have to marge multiple clients with multiple servers.

mangooose commented 6 years ago

@chegewara Great :D thanks a lot. Which ESP32 module are you using?

chegewara commented 6 years ago

I am using devKitC and analog lamb esp32 wrover mini.

chegewara commented 6 years ago

I would like to apology for mess in code, because i am working on many additions, changes and bugfixes now. This will be code for testing purposes only. I will create new branch for it and all issues or questions please post on my repository:

https://github.com/chegewara/esp32-snippets-enchancements-test/tree/multi_connect_test

Starting point to write own client and server are SampleServer and SampleClient from main subfolder (its just suggestion).

PS i am able to connect to 4 peripherals simultaneously and send independent write request to each of them, also receiving notifications. some crash occurs when 1 of 4 peripherals disconnects.

chegewara commented 6 years ago

Added arduino compatibility, you just need to export library to arduino on your own. https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/ArduinoBLE.md#replacing-the-version-that-comes-with-arduino-esp32

PS there is arduino example in library too

chegewara commented 6 years ago

Hi, i have to solve one or two issues and i can post nicely working version that can be used both ways (one server to multi client and one client to multi peripherals). Biggest issue now is how esp-idf stack works. When esp32 is running in central/master role (BLEClient) and there is few peripherals connected, when one peripheral got disconnected bt stack is disconnecting all peripheral devices. This and few more small issues drives me crazy, but i am working on it. If there is request to publish current version library to my repository just tell me.

mangooose commented 6 years ago

@chegewara please publish it

mangooose commented 6 years ago

@chegewara currently I use the latest code in master and i couldn't connect to multiple servers should i use this repo ?

chegewara commented 6 years ago

Yes, but its not published yet. Give me few minutes.

I have nice rig setup now:

Now, esp32 client is performing infinite scanning for peripherals, when peripheral is found client is connecting to it and starts sending write message to remote characteristic on that peripheral. This is happening every 1000 ms with vTaskDelayUntil. When peripheral receive write request then its sending echo with notification to every connected client device. As for now all works fine, from time to time i have central crash, but it seems to be esp-idf bt stack related. With smartphone i can monitor peripherals. So i can have one central esp32 connected to many peripherals that also can be connected to many centrals.

chegewara commented 6 years ago

@mangooose Most API has not been changed, but in BLEScan is few changes. Those are not breaking older code changes but are useful during multi connecting.

mangooose commented 6 years ago

@chegewara which repo should I use?

chegewara commented 6 years ago

https://github.com/chegewara/esp32-snippets-enchancements-test/tree/multi_connect_test

chegewara commented 6 years ago

Implemented in latest version.

victorChB commented 5 years ago

https://github.com/chegewara/esp32-snippets-enchancements-test/tree/multi_connect_test

@chegewara I can't acces the link, is it merged somewhere?

chegewara commented 5 years ago

Its merged already in master.

Bryanbaring commented 5 years ago

"404 didnt find anyrhing here" . i cant open the link.

chegewara commented 5 years ago

Its because repository is no longer public since code is merged here.

helmym commented 5 years ago

@chegeware I can’t access to the link And I need esp32 ble code to connect BLE server to 4 Clint have the same uuid

Donderda commented 5 years ago

Its already in the latest master

Written with two thumbs on my mobile device...

Am 03.06.2019 um 00:55 schrieb helmym notifications@github.com:

@chegeware I can’t access to the link And I need esp32 ble code to connect BLE server to 4 Clint have the same uuid

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

Jerry0045 commented 5 years ago

@chegewara Hello, I´m trying to connect one ESP32 as the client and other 6 ESPs as servers but i'm able to connect client to only one server. You said that you are able to connect multiple servers and its in the master but i'm not able to find it. Can you please help me where i can find it or is there any example? Thanks for response.

chegewara commented 5 years ago

No, there is no example, at least i dont know any.

You have to remember that with arduino its limited to 3 simultaneous connection and with esp-idf you need to chanage setting with make menuconfig.

There is nothing special you have to do, just create BLEClient for every server you want to connect to.

luizahiginoss commented 5 years ago

@chegewara I tried to find your client code for multiple servers, but i couldn't. Can you show me the link?

chegewara commented 5 years ago

This is very old code and its for sure not production ready, but it should works:

/**
 * Create a sample BLE client that connects to a BLE server and then retrieves the current
 * characteristic value.  It will then periodically update the value of the characteristic on the
 * remote server with the current time since boot.
 */
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_log.h>
#include <string>
#include <sstream>
#include <sys/time.h>
#include "BLEDevice.h"
#include "FreeRTOS.h"
#include <nvs_flash.h>

#include "BLEAdvertisedDevice.h"
#include "BLEClient.h"
#include "BLEScan.h"
#include "BLEUtils.h"
#include "Task.h"

#include "sdkconfig.h"
#define TICKS_TO_DELAY 1000
BLEScan *pBLEScan;
static const char* LOG_TAG = "TEST";
// esp_ble_addr_type_t addressType;
TaskHandle_t handle;
TaskHandle_t xTaskGetHandle( const char *pcWriteBuffer );

static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
static BLEUUID    charUUID1("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static BLEUUID    charUUID2("beb5483e-36e2-4688-b7f5-ea07361b26a8");
static BLEUUID    charUUID3("beb5483e-36e3-4688-b7f5-ea07361b26a8");

void scan1(void*);

static void notifyCallback(
    BLERemoteCharacteristic* pBLERemoteCharacteristic,
    uint8_t* pData,
    size_t length,
    bool isNotify) {
        ESP_LOGE(LOG_TAG, "Notify callback for characteristic %s of data %s length %d",
                pBLERemoteCharacteristic->getUUID().toString().c_str(), ((char*) pData), length);
}

class MyCallbacks : public BLEClientCallbacks {
    void onConnect(BLEClient* pC){
            // xTaskCreate(scan1, "scan", 4048, NULL, 5, NULL);
    }
    void onDisconnect(BLEClient* pC) {
        // pBLEScan->erase(pC->getPeerAddress());
    }
};
esp_ble_addr_type_t type;
class MyClient: public Task {
    void run(void* data) {
        ESP_LOGI(LOG_TAG, "Advertised Device: %s", ((BLEAddress*)data)->toString().c_str());
         BLEAddress addr = *(BLEAddress*)data;
       BLEClient*  pClient  = BLEDevice::createClient();
        pClient->setClientCallbacks(new MyCallbacks());
        // esp_ble_gap_set_prefer_conn_params(*addr.getNative(), 100,125, 2, 0x03e8);
        pClient->connect(addr, type);

        // xTaskCreate(scan1, "scan", 4048, NULL, 5, NULL);

        BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
        if (pRemoteService == nullptr) {
            ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
            pClient->disconnect();
            stop();
            return;
        }

        BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID1);
        if (pRemoteCharacteristic != nullptr) {
            ESP_LOGW(LOG_TAG, "Found our characteristic UUID1: %s", charUUID1.toString().c_str());
            goto ready;
        }

        pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID2);
        if (pRemoteCharacteristic != nullptr) {
            ESP_LOGW(LOG_TAG, "Found our characteristic UUID2: %s", charUUID2.toString().c_str());
            goto ready;
        }

        pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID3);
        if (pRemoteCharacteristic == nullptr) {
            ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s, disconnecting", charUUID1.toString().c_str());
            pClient->disconnect();
            stop();
            return;
        }
ready:      
        pRemoteCharacteristic->registerForNotify(notifyCallback);
    // handle = xTaskGetHandle("btuT");
        xTaskCreate(scan1, "scan", 4048, NULL, 1, NULL);

        TickType_t last_wake_time;
        last_wake_time = xTaskGetTickCount();

        while(pClient->isConnected()) {
        // ESP_LOGI(LOG_TAG, "5--> %d", uxTaskGetStackHighWaterMark(NULL));
            std::ostringstream stringStream;
            struct timeval tv;
            gettimeofday(&tv, nullptr);
            stringStream << "Time sent to uuid: " << pRemoteCharacteristic->getUUID().toString().c_str() << tv.tv_sec << "." << tv.tv_usec;
            pRemoteCharacteristic->writeValue(stringStream.str());

            vTaskDelayUntil(&last_wake_time, TICKS_TO_DELAY/portTICK_PERIOD_MS);
            // if(handle)
            //  ESP_LOGW(LOG_TAG, "btuT highwater--> %d", uxTaskGetStackHighWaterMark(handle));
            // heap_caps_print_heap_info(MALLOC_CAP_EXEC | MALLOC_CAP_8BIT );
        }

        // pClient->disconnect();
        ESP_LOGD(LOG_TAG, "%s", pClient->toString().c_str());
        ESP_LOGD(LOG_TAG, "-- End of task");
        stop();
    } // run
}; // MyClient

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
        ESP_LOGI(LOG_TAG, "Advertised Device: %s", advertisedDevice.toString().c_str());
        ESP_LOG_BUFFER_HEX_LEVEL(__func__, advertisedDevice.getPayload(), advertisedDevice.getPayloadLength(), ESP_LOG_WARN);
        if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID("00001234"))) {
            pBLEScan->stop();  // <--- it is required to always stop scan before we try to connect to another device, if we wont stop app will stall in esp-idf bt stack
            type = advertisedDevice.getAddressType();

            MyClient* pMyClient = new MyClient();
            pMyClient->setStackSize(5000);
            pMyClient->start(new BLEAddress(*advertisedDevice.getAddress().getNative()));
        } 
    } 
}; 
static void my_gap_event_handler(esp_gap_ble_cb_event_t  event, esp_ble_gap_cb_param_t* param) {
    ESP_LOGW(LOG_TAG, "custom gap event handler, event: %d", (uint8_t)event);
}

static void my_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param) {
    ESP_LOGW(LOG_TAG, "custom gattc event handler, event: %d", (uint8_t)event);
}

static void my_gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param) {
    ESP_LOGW(LOG_TAG, "custom gatts event handler, event: %d", (uint8_t)event);
}
void SampleClient2(void) {
    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("BLEUtils", ESP_LOG_NONE);
            // heap_caps_print_heap_info(MALLOC_CAP_EXEC | MALLOC_CAP_8BIT );

// new BLEUUID("00001234-0000-1000-8000-00805f9b34fb");
    BLEDevice::init("esp32");
    nvs_flash_erase();
        BLEDevice::setCustomGapHandler(my_gap_event_handler);
        BLEDevice::setCustomGattsHandler(my_gatts_event_handler);
        BLEDevice::setCustomGattcHandler(my_gattc_event_handler);
    BLEDevice::setMTU(100);
    handle = xTaskGetHandle("btuT");
    pBLEScan = BLEDevice::getScan();
    pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
    pBLEScan->setActiveScan(true);
    pBLEScan->setInterval(1389);
    pBLEScan->setWindow(349);

    xTaskCreate(scan1, "scan", 4048, NULL, 1, NULL);
} // SampleClient

void scan1(void*){
    ESP_LOGI(LOG_TAG, "start scan");
    pBLEScan->start(0, true);
    ESP_LOGI(LOG_TAG, "scan stop success");

    vTaskDelete(NULL);
}
// this code is only for debug purpose, to see if we have problem wit esp-idf btuT task stack
TaskHandle_t xTaskGetHandle( const char *pcWriteBuffer )
{
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x;
uint32_t ulTotalRunTime;
    uxArraySize = uxTaskGetNumberOfTasks();
    pxTaskStatusArray = (TaskStatus_t *)pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
    if( pxTaskStatusArray != NULL )
    {
        uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
        for( x = 0; x < uxArraySize; x++ )
        {
            ESP_LOGW(LOG_TAG, "%s highwater--> %d, state: %d ", pxTaskStatusArray[x].pcTaskName, uxTaskGetStackHighWaterMark(pxTaskStatusArray[x].xHandle), (uint8_t)pxTaskStatusArray[x].eCurrentState);
            if(strncmp(pxTaskStatusArray[x].pcTaskName, pcWriteBuffer, strlen(pcWriteBuffer)) == 0){
                vPortFree( pxTaskStatusArray );
                return  pxTaskStatusArray[x].xHandle;
            }
        }
        vPortFree( pxTaskStatusArray );
    }
    return nullptr;
}
Chedeshri commented 5 years ago

This is very old code and its for sure not production ready, but it should works:

/**
 * Create a sample BLE client that connects to a BLE server and then retrieves the current
 * characteristic value.  It will then periodically update the value of the characteristic on the
 * remote server with the current time since boot.
 */
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_log.h>
#include <string>
#include <sstream>
#include <sys/time.h>
#include "BLEDevice.h"
#include "FreeRTOS.h"
#include <nvs_flash.h>

#include "BLEAdvertisedDevice.h"
#include "BLEClient.h"
#include "BLEScan.h"
#include "BLEUtils.h"
#include "Task.h"

#include "sdkconfig.h"
#define TICKS_TO_DELAY 1000
BLEScan *pBLEScan;
static const char* LOG_TAG = "TEST";
// esp_ble_addr_type_t addressType;
TaskHandle_t handle;
TaskHandle_t xTaskGetHandle( const char *pcWriteBuffer );

static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
static BLEUUID    charUUID1("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static BLEUUID    charUUID2("beb5483e-36e2-4688-b7f5-ea07361b26a8");
static BLEUUID    charUUID3("beb5483e-36e3-4688-b7f5-ea07361b26a8");

void scan1(void*);

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
      ESP_LOGE(LOG_TAG, "Notify callback for characteristic %s of data %s length %d",
              pBLERemoteCharacteristic->getUUID().toString().c_str(), ((char*) pData), length);
}

class MyCallbacks : public BLEClientCallbacks {
  void onConnect(BLEClient* pC){
          // xTaskCreate(scan1, "scan", 4048, NULL, 5, NULL);
  }
  void onDisconnect(BLEClient* pC) {
      // pBLEScan->erase(pC->getPeerAddress());
  }
};
esp_ble_addr_type_t type;
class MyClient: public Task {
  void run(void* data) {
      ESP_LOGI(LOG_TAG, "Advertised Device: %s", ((BLEAddress*)data)->toString().c_str());
       BLEAddress addr = *(BLEAddress*)data;
       BLEClient*  pClient  = BLEDevice::createClient();
        pClient->setClientCallbacks(new MyCallbacks());
      // esp_ble_gap_set_prefer_conn_params(*addr.getNative(), 100,125, 2, 0x03e8);
        pClient->connect(addr, type);

        // xTaskCreate(scan1, "scan", 4048, NULL, 5, NULL);

      BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
      if (pRemoteService == nullptr) {
          ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", serviceUUID.toString().c_str());
          pClient->disconnect();
          stop();
          return;
      }

      BLERemoteCharacteristic* pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID1);
      if (pRemoteCharacteristic != nullptr) {
          ESP_LOGW(LOG_TAG, "Found our characteristic UUID1: %s", charUUID1.toString().c_str());
          goto ready;
      }

      pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID2);
      if (pRemoteCharacteristic != nullptr) {
          ESP_LOGW(LOG_TAG, "Found our characteristic UUID2: %s", charUUID2.toString().c_str());
          goto ready;
      }

      pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID3);
      if (pRemoteCharacteristic == nullptr) {
          ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s, disconnecting", charUUID1.toString().c_str());
          pClient->disconnect();
          stop();
          return;
      }
ready:        
      pRemoteCharacteristic->registerForNotify(notifyCallback);
  // handle = xTaskGetHandle("btuT");
        xTaskCreate(scan1, "scan", 4048, NULL, 1, NULL);

      TickType_t last_wake_time;
      last_wake_time = xTaskGetTickCount();

      while(pClient->isConnected()) {
      // ESP_LOGI(LOG_TAG, "5--> %d", uxTaskGetStackHighWaterMark(NULL));
          std::ostringstream stringStream;
          struct timeval tv;
          gettimeofday(&tv, nullptr);
          stringStream << "Time sent to uuid: " << pRemoteCharacteristic->getUUID().toString().c_str() << tv.tv_sec << "." << tv.tv_usec;
          pRemoteCharacteristic->writeValue(stringStream.str());

          vTaskDelayUntil(&last_wake_time, TICKS_TO_DELAY/portTICK_PERIOD_MS);
          // if(handle)
          //  ESP_LOGW(LOG_TAG, "btuT highwater--> %d", uxTaskGetStackHighWaterMark(handle));
          // heap_caps_print_heap_info(MALLOC_CAP_EXEC | MALLOC_CAP_8BIT );
      }

        // pClient->disconnect();
      ESP_LOGD(LOG_TAG, "%s", pClient->toString().c_str());
      ESP_LOGD(LOG_TAG, "-- End of task");
      stop();
  } // run
}; // MyClient

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
      ESP_LOGI(LOG_TAG, "Advertised Device: %s", advertisedDevice.toString().c_str());
      ESP_LOG_BUFFER_HEX_LEVEL(__func__, advertisedDevice.getPayload(), advertisedDevice.getPayloadLength(), ESP_LOG_WARN);
      if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(BLEUUID("00001234"))) {
          pBLEScan->stop();  // <--- it is required to always stop scan before we try to connect to another device, if we wont stop app will stall in esp-idf bt stack
            type = advertisedDevice.getAddressType();

            MyClient* pMyClient = new MyClient();
            pMyClient->setStackSize(5000);
            pMyClient->start(new BLEAddress(*advertisedDevice.getAddress().getNative()));
      } 
  } 
}; 
static void my_gap_event_handler(esp_gap_ble_cb_event_t  event, esp_ble_gap_cb_param_t* param) {
  ESP_LOGW(LOG_TAG, "custom gap event handler, event: %d", (uint8_t)event);
}

static void my_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param) {
  ESP_LOGW(LOG_TAG, "custom gattc event handler, event: %d", (uint8_t)event);
}

static void my_gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param) {
  ESP_LOGW(LOG_TAG, "custom gatts event handler, event: %d", (uint8_t)event);
}
void SampleClient2(void) {
  esp_log_level_set("*", ESP_LOG_INFO);
  esp_log_level_set("BLEUtils", ESP_LOG_NONE);
          // heap_caps_print_heap_info(MALLOC_CAP_EXEC | MALLOC_CAP_8BIT );

// new BLEUUID("00001234-0000-1000-8000-00805f9b34fb");
  BLEDevice::init("esp32");
    nvs_flash_erase();
      BLEDevice::setCustomGapHandler(my_gap_event_handler);
      BLEDevice::setCustomGattsHandler(my_gatts_event_handler);
      BLEDevice::setCustomGattcHandler(my_gattc_event_handler);
    BLEDevice::setMTU(100);
  handle = xTaskGetHandle("btuT");
  pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->setInterval(1389);
    pBLEScan->setWindow(349);

  xTaskCreate(scan1, "scan", 4048, NULL, 1, NULL);
} // SampleClient

void scan1(void*){
  ESP_LOGI(LOG_TAG, "start scan");
  pBLEScan->start(0, true);
    ESP_LOGI(LOG_TAG, "scan stop success");

  vTaskDelete(NULL);
}
// this code is only for debug purpose, to see if we have problem wit esp-idf btuT task stack
TaskHandle_t xTaskGetHandle( const char *pcWriteBuffer )
{
TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x;
uint32_t ulTotalRunTime;
  uxArraySize = uxTaskGetNumberOfTasks();
  pxTaskStatusArray = (TaskStatus_t *)pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
  if( pxTaskStatusArray != NULL )
  {
      uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
      for( x = 0; x < uxArraySize; x++ )
      {
          ESP_LOGW(LOG_TAG, "%s highwater--> %d, state: %d ", pxTaskStatusArray[x].pcTaskName, uxTaskGetStackHighWaterMark(pxTaskStatusArray[x].xHandle), (uint8_t)pxTaskStatusArray[x].eCurrentState);
          if(strncmp(pxTaskStatusArray[x].pcTaskName, pcWriteBuffer, strlen(pcWriteBuffer)) == 0){
              vPortFree( pxTaskStatusArray );
              return  pxTaskStatusArray[x].xHandle;
          }
      }
      vPortFree( pxTaskStatusArray );
  }
  return nullptr;
}

Hello @chegewara , I am trying the same example and i am getting guru meditation error which i opened as other issue , my application is same as mentioend in this example, i am working on that error since a month, could you give me step by step guidance on this one, i think i am missing somehting, i coulnt thank you more !

Regards,

chegewara commented 5 years ago

I can try to help with errors, but you need to provide some more info and logs.

Asmaa-do commented 3 years ago

hi @luizahiginoss @chegewara @mangooose

I'm trying to develop a bluetooth network with one client and several servers, but they communicate with the client based on "notify". each server is connected to a sensor (DHT11). i am able to connect to one server and get the temp characteristic.

i need a code for one esp32 client connecting to multiple ESP32 server .

I'm using the BLE examples

Asmaa-do commented 3 years ago

i came across this "multi-connection example’s main source file is gattc_multi_connect.c." https://github.com/espressif/esp-idf/blob/a6f33a9d366e8179fa7d18a81f205254a15db117/examples/bluetooth/bluedroid/ble/gattc_multi_connect/main/gattc_multi_connect.c but it seems its not for arduino IDE

guevaj5 commented 3 years ago

hi @AS123-y

I am currently attempting to build a bluetooth network of ESP32s one client and about 3 servers, similar to your project. each server would be connected to accelerometers. I just plan on sending the different accelerometer values to the client, which would display them on some LCD display. Were you able to figure out your project?

Asmaa-do commented 3 years ago

hi @guevaj5 no, I still didn't figure out a solution. Please keep me updated on the status of things.

helmym commented 3 years ago

Can you send me WhatsApp please 00201121106662

On Thu, 25 Nov 2021 at 12:05 PM AS123-y @.***> wrote:

hi @guevaj5 https://github.com/guevaj5 no, I still didn't figure out a solution. Please keep me updated on the status of things.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/538#issuecomment-979053226, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMHM6L4ZFIHPWRY2A2KS3C3UNYC6LANCNFSM4FCCGN2Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

Sireevenkat commented 1 year ago

@luizahiginoss @mangooose @AS123-y Do you find solution to connect multiple ESP32 BLE servers with one ESP32 BLE client on Arduino IDE?
@luizahiginoss [BLE_client.txt] Did you solved the issue?

helmym commented 1 year ago

Hello Yes I had do it Send me your issue and we will discuss it

On Thu, 9 Feb 2023 at 8:58 AM Sireevenkat @.***> wrote:

@luizahiginoss https://github.com/luizahiginoss @mangooose https://github.com/mangooose @AS123-y https://github.com/AS123-y Do you find solution to connect multiple ESP32 BLE servers with one ESP32 BLE client on Arduino IDE? @luizahiginoss https://github.com/luizahiginoss [BLE_client.txt] Did you solved the issue?

— Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/538#issuecomment-1423723842, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMHM6L5DTKPHZ7DCYX5EZC3WWSIS5ANCNFSM4FCCGN2Q . You are receiving this because you commented.Message ID: @.***>

Asmaa-do commented 1 year ago

@luizahiginoss @mangooose @AS123-y Do you find solution to connect multiple ESP32 BLE servers with one ESP32 BLE client on Arduino IDE? @luizahiginoss [BLE_client.txt] Did you solved the issue?

Hi @Sireevenkat i still did not find a solution @helmym can you share your findings?

helmym commented 1 year ago

Send me WhatsApp please 00201121106662

On Thu, 9 Feb 2023 at 1:44 PM Helmy Mohamed @.***> wrote:

Hello Yes I had do it Send me your issue and we will discuss it

On Thu, 9 Feb 2023 at 8:58 AM Sireevenkat @.***> wrote:

@luizahiginoss https://github.com/luizahiginoss @mangooose https://github.com/mangooose @AS123-y https://github.com/AS123-y Do you find solution to connect multiple ESP32 BLE servers with one ESP32 BLE client on Arduino IDE? @luizahiginoss https://github.com/luizahiginoss [BLE_client.txt] Did you solved the issue?

— Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/538#issuecomment-1423723842, or unsubscribe https://github.com/notifications/unsubscribe-auth/AMHM6L5DTKPHZ7DCYX5EZC3WWSIS5ANCNFSM4FCCGN2Q . You are receiving this because you commented.Message ID: @.***>

Sireevenkat commented 1 year ago

Hi, @helmym,@chegewara,@AS123-y I am working with ESP32-S3 module on Arduino IDE.I need to connect multiple BLE servers to one client and able send and receive data from client to all servers at a time. Can You share your findings. Thanks