Problème callback BLE

Salut tout le monde, j'ai un petit soucis avec mes callbacks de BLE.

Voici mon code pour l'init du BLE

  BLEDevice::init(nameBLEServeurForInit);
  BLEServer *pServer = BLEDevice::createServer();

  //Servive écriture mes paramètres
  BLEService *pMyService = pServer->createService(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);

  //Characteristics nombre de relay
  BLECharacteristic *nbRelayCharacteristic = pMyService->createCharacteristic(
      NB_RELAY_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_READ);

  //Characteristics changement du nom de l'Arduino
  BLECharacteristic *pChangeNameCharacteristic = pMyService->createCharacteristic(
      CHANGENAME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics changement du mdp de l'Arduino
  BLECharacteristic *pChangePasswordCharacteristic = pMyService->createCharacteristic(
      PASSWORD_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics mise à jour de l'heure de l'Arduino
  BLECharacteristic *pSetTimeCharacteristic = pMyService->createCharacteristic(
      TIME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Service Lancement Circuit
  BLEService *pMyLaunchService = pServer->createService(SERVICE_LAUNCH_UUID);

  //Characteristics lancement d'un circuit manuellement
  BLECharacteristic *pStartLaunchManualCharacteristic = pMyLaunchService->createCharacteristic(
      START_M_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics lancements automatique
  BLECharacteristic *psaveAutomaticLaunchCharacteristic = pMyLaunchService->createCharacteristic(
      SAVE_A_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  pChangePasswordCharacteristic->setCallbacks(new changePasswordArduinoCallBacks());
  pChangeNameCharacteristic->setCallbacks(new changeNameArduinoCallBacks());
  pSetTimeCharacteristic->setCallbacks(new changeTimedArduinoCallBacks());

  // pStartLaunchManualCharacteristic->setCallbacks(new startingCircuitCallBacks());
  psaveAutomaticLaunchCharacteristic->setCallbacks(new saveFirtAutomaticLaunchCallBacks());

  nbRelayCharacteristic->setValue(NB_RELAY);

  pMyService->start();
  pMyLaunchService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

Voici mes Callbacks :

class changeNameArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string value = pCharacteristic->getValue();

    if (value.length() > 0)
    {
      eraseEEPROM(addr_name, 50);

      for (int i = 0; i < value.length(); i++)
        EEPROM.write(addr_name + i, value[i]);
    }
    EEPROM.commit();
    Serial.println("Changement du nom effectué");
  }
};

class changePasswordArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string value = pCharacteristic->getValue();

    if (value.length() > 0)
    {
      eraseEEPROM(addr_password, 50);

      for (int i = 0; i < value.length(); i++)
      {
        EEPROM.write(addr_password + i, value[i]);
      }
    }
    EEPROM.commit();
    Serial.println("Changement du mot de passe effectué");
  }
};

class changeTimedArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string value = pCharacteristic->getValue();
    String written_time;

    if (value.length() > 0)
    {
      for (int i = 0; i < value.length(); i++)
      {
        written_time.concat(value[i]);
      }
    }

    rtc.adjust(DateTime(2020, 10, 20, written_time.substring(0, written_time.indexOf(":")).toInt(), written_time.substring(written_time.indexOf(":") + 1, written_time.indexOf(":") * 2 + 1).toInt(), written_time.substring(written_time.indexOf(":") * 3).toInt()));

    Serial.println("Mise à jour de l''heure effectué");

    afficher_date_heure();
  }
};

class startingCircuitCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string value = pCharacteristic->getValue();
    String startCircuit;

    if (value.length() > 0)
    {
      for (int i = 0; i < value.length(); i++)
      {
        startCircuit.concat(value[i]);
      }
    }
    solenoidNumber = startCircuit.substring(0, 2).toInt();
    durationforLaunch = startCircuit.substring(startCircuit.indexOf(" ")).toInt() * 60000;

    time_machine = millis();
  }
};

Pour mettre dans le contexte, dans mon exemple ci-dessous, tous les appels de callbacks sont depuis mon téléphone en Bluetooth.

Mon problème est très bizarre si j'appelle la callback changeNameArduinoCallBacks(), ça fonctionne parfait pareil pour changePasswordArduinoCallBacks() et changeTimedArduinoCallBacks().

Par contre si j'exécute startingCircuitCallBacks() ou saveFirtAutomaticLaunchCallBacks() toutes les callbacks s'éxécutent.

Si j'exécute startingCircuitCallBacks(), ça m'éxecute changeNameArduinoCallBacks(), changePasswordArduinoCallBacks() et changeTimedArduinoCallBacks()

Merci pour votre aide

Postez un truc complet qui démontre le problème, pas juste des bouts de code (Snippets R Us!)

Je peux pas vraiment mettre plus de code car ce n'est que cette partie là.

Je vais essayer de mieux m'expliquer.

Si depuis mon téléphone j'envoie des données sur la caractéristique psaveAutomaticLaunchCharacteristic, il va d'abord exécuter :
pChangeNameCharacteristic
pChangePasswordCharacteristicp
SetTimeCharacteristic
pStartLaunchManualCharacteristic

Ma sortie console :
Changement du nom effectué
Changement du mot de passe effectué
Mise à jour de l''heure effectué
2020/10/20 (Tuesday) 0:0:0
testLM
Sauvegarde du lancement 1 fait

Mes callbacks :

class changeNameArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pChangeNameCharacteristic)
  {
    std::string value = pChangeNameCharacteristic->getValue();

    if (value.length() > 0)
    {
      eraseEEPROM(addr_name, 50);

      for (int i = 0; i < value.length(); i++)
        EEPROM.write(addr_name + i, value[i]);
    }
    EEPROM.commit();
    Serial.println("Changement du nom effectué");
  }
};

class changePasswordArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pChangePasswordCharacteristic)
  {
    std::string value = pChangePasswordCharacteristic->getValue();

    if (value.length() > 0)
    {
      eraseEEPROM(addr_password, 50);

      for (int i = 0; i < value.length(); i++)
      {
        EEPROM.write(addr_password + i, value[i]);
      }
    }
    EEPROM.commit();
    Serial.println("Changement du mot de passe effectué");
  }
};

class changeTimedArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pSetTimeCharacteristic)
  {
    std::string value = pSetTimeCharacteristic->getValue();
    String written_time;

    if (value.length() > 0)
    {
      for (int i = 0; i < value.length(); i++)
      {
        written_time.concat(value[i]);
      }
    }

    rtc.adjust(DateTime(2020, 10, 20, written_time.substring(0, written_time.indexOf(":")).toInt(), written_time.substring(written_time.indexOf(":") + 1, written_time.indexOf(":") * 2 + 1).toInt(), 0));//written_time.substring(written_time.indexOf(":") * 3).toInt()));
    
    Serial.println("Mise à jour de l''heure effectué");

    afficher_date_heure();
  }
};

class startingCircuitCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pStartLaunchManualCharacteristic)
  {

    Serial.println("testLM");

    std::string value = pStartLaunchManualCharacteristic->getValue();
    String startCircuit;

    if (value.length() > 0)
    {
      for (int i = 0; i < value.length(); i++)
      {
        startCircuit.concat(value[i]);
      }
    }
    solenoidNumber = startCircuit.substring(0, 2).toInt();
    durationforLaunch = startCircuit.substring(startCircuit.indexOf(" ")).toInt() * 60000;

    time_machine = millis();
  }
};

class saveFirtAutomaticLaunchCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *psaveAutomaticLaunchCharacteristic)
  {

    std::string value = psaveAutomaticLaunchCharacteristic->getValue();
    String valueReceived;

    if (value.length() > 0)
    {
      for (int i = 0; i < value.length(); i++)
      {
        valueReceived.concat(value[i]);
      }
    }

    deserializeJson(doc, valueReceived);

    //int id = doc["id"];                           // 1
    int duration = doc["duration"];               // 30
    const char *startTime = doc["startTime"];     // "2000-01-01T04:00:00+01:00"
    bool advancedLaunch = doc["lancementAvance"]; // false

    JsonArray electrovannes = doc["electrovannes"];

    for (int i = 0; i < electrovannes.size(); i++)
    {
      JsonObject electrovanne = electrovannes[i];
      int electrovanne_id = electrovanne["id"];               // 1
      int electrovanne_durationC = electrovanne["durationC"]; // 0
      if (advancedLaunch)
      {
        firstLaunch_solenoid[i] = new Solenoid(electrovanne_id, electrovanne_durationC*1000);
      }
      else
      {
        firstLaunch_solenoid[i] = new Solenoid(electrovanne_id, duration*1000);
      }
    }

    //convert char* to String
    String convertArrayCharToString(startTime);
    firstLaunch_Nb_Solenoid = electrovannes.size();

    firstLaunchSave = true;
    firstLaunchTime = convertArrayCharToString.substring(convertArrayCharToString.indexOf("T") + 1, convertArrayCharToString.indexOf("+"));

    Serial.println("Sauvegarde du lancement 1 fait");
  }
};

Mon setup() :

void setup()
{

  Serial.begin(115200);
  EEPROM.begin(512);

  pinMode(SOLENOID_1, OUTPUT);
  pinMode(SOLENOID_2, OUTPUT);
  pinMode(SOLENOID_3, OUTPUT);
  pinMode(SOLENOID_4, OUTPUT);
  pinMode(SOLENOID_5, OUTPUT);
  pinMode(SOLENOID_6, OUTPUT);
  pinMode(SOLENOID_7, OUTPUT);
  pinMode(SOLENOID_8, OUTPUT);
  pinMode(SOLENOID_9, OUTPUT);
  pinMode(SOLENOID_10, OUTPUT);
  pinMode(SOLENOID_11, OUTPUT);
  pinMode(SOLENOID_12, OUTPUT);

  for (int i = addr_name; i < addr_name + 50; ++i)
  {
    nameBLEServeur += char(EEPROM.read(i));
  }

  for (int i = addr_password; i < addr_password + 50; ++i)
  {
    passwordBLEServeur += char(EEPROM.read(i));
  }

  if (char(EEPROM.read(addr_name)) == 0)
  {
    nameBLEServeur = SERIE_NUMBER;
  }

  if (char(EEPROM.read(addr_password)) == 0)
  {
    passwordBLEServeur = DEFAULT_PASSWORD;
  }

  nameBLEServeurForInit = nameBLEServeur.c_str();

  BLEDevice::init(nameBLEServeurForInit);
  BLEServer *pServer = BLEDevice::createServer();

  //Servive écriture mes paramètres
  BLEService *pMyService = pServer->createService(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);

  //Characteristics nombre de relay
  BLECharacteristic *nbRelayCharacteristic = pMyService->createCharacteristic(
      NB_RELAY_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_READ);

  //Characteristics changement du nom de l'Arduino
  BLECharacteristic *pChangeNameCharacteristic = pMyService->createCharacteristic(
      CHANGENAME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics changement du mdp de l'Arduino
  BLECharacteristic *pChangePasswordCharacteristic = pMyService->createCharacteristic(
      PASSWORD_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics mise à jour de l'heure de l'Arduino
  BLECharacteristic *pSetTimeCharacteristic = pMyService->createCharacteristic(
      TIME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Service Lancement Circuit
  BLEService *pMyLaunchService = pServer->createService(SERVICE_LAUNCH_UUID);

  //Characteristics lancement d'un circuit manuellement
  BLECharacteristic *pStartLaunchManualCharacteristic = pMyLaunchService->createCharacteristic(
      START_M_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics lancements automatique
  BLECharacteristic *psaveAutomaticLaunchCharacteristic = pMyLaunchService->createCharacteristic(
      SAVE_A_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  pChangePasswordCharacteristic->setCallbacks(new changePasswordArduinoCallBacks());
  pChangeNameCharacteristic->setCallbacks(new changeNameArduinoCallBacks());
  pSetTimeCharacteristic->setCallbacks(new changeTimedArduinoCallBacks());

  pStartLaunchManualCharacteristic->setCallbacks(new startingCircuitCallBacks());
  psaveAutomaticLaunchCharacteristic->setCallbacks(new saveFirtAutomaticLaunchCallBacks());

  nbRelayCharacteristic->setValue(NB_RELAY);

  pMyService->start();
  pMyLaunchService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

  Serial.println("Programmateur " + nameBLEServeur);

  //all solenoid are OFF
  stop_Launch(0);

  //get time machine
  time_machine = millis();

  if (!rtc.begin())
  {
    Serial.println("ERROR : Couldn't find RTC");
    while (1)
      ;
  }

  afficher_date_heure();
}

Je ne comprends pas pourquoi quand je tape sur psaveAutomaticLaunchCharacteristic ça m'exécute aussi tout mes autres callbacks.
Alors que si j'exécute les autres, le déclenchement se fait bien et pour qu'une seul callback.
Par exemple si je tape sur pChangePasswordCharacteristic, il me change bien le mot de passe mais c'est tout, pareil pour pChangeNameCharacteristic, pSetTimeCharacteristic et pStartLaunchManualCharacteristic

Je peux pas vraiment mettre plus de code car ce n'est que cette partie là.

Faites un code qui compile avec uniquement cela... sans ça difficile de vous aider, ce ne sont pas vos explications qu’il nous faut mais un code complet qui montre le souci.

Je vous ai mis tout mon code, comme ça vous pouvez tester

Pas lisible sur mon smartphone.. je pourrais jeter un oeil ce week end éventuellement

Vérifiez les définitions de BLECharacteristic pour qu’elles soient bien différentes et pas trop longue (Il y avait eu ce souci et il faut vous assurer que vos String sont persistantes si vous utilisez c_str() qui est le pointeur directement dans la zone mémoire de la String (et donc qui peut pointer n’importe où si la String est libérée)

c’est pour cela qu’un exemple minimaliste sans rien de connecté à la carte serait plus simple à vérifier à la fois pour vous et nous.

Il vous suffit de nettoyer tout ce qui est lié à votre projet et de ne garder que la partie BT, et des callbacks qui affichent un truc dans la console et c’est tout. Pas de gestion mémoire, EEPROM, pins etc.

Ok je vais essayer de vous faire, du coup je vais enlever les fichiers

J’ai tapé quelques éléments en plus pendant que vous répondiez - à vérifier

Vérifiez les définitions de BLECharacteristic pour qu'elles soient bien différentes et pas trop longue (Il y avait eu ce souci et il faut vous assurer que vos String sont persistantes si vous utilisez c_str() qui est le pointeur directement dans la zone mémoire de la String (et donc qui peut pointer n'importe où si la String est libérée)

Bon j'ai préparé un code comme vous me l'avez demandé, j'ai testé quand même et je suis content car j'ai toujours le même problème.

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <EEPROM.h>
#include <ArduinoJson.h>
#include <Solenoid.h>
#include <RTClib.h>


#define SERIE_NUMBER "RAIN1"
#define DEFAULT_PASSWORD ")a3C8"
#define NB_RELAY "12"
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

//Service Params Arduino
#define SERVICE_CHANGE_PARAMS_ARDUINO_UUID "e660bdcb-638c-4dc6-b613-31610945bddb"

//Service Bluetooth for launch
#define SERVICE_LAUNCH_UUID "11a163ee-12b2-48e4-97d5-19a8f492e019"

//Read the number of solenoid valves available
#define NB_RELAY_CHARACTERISTIC_UUID "b6c0a045-715f-468d-a271-22d135b4762f"

//Rename Scheduler
#define CHANGENAME_CHARACTERISTIC_UUID "9354398f-9105-44da-a58e-80de9a7f5fdc"

//Change password of Scheduler
#define PASSWORD_CHARACTERISTIC_UUID "27349bf0-cd6b-4391-a08f-d7745058b985"

//Set Time for Scheduler
#define TIME_CHARACTERISTIC_UUID "ee1c0d7f-fec3-4f89-ab2f-bb1a1807260d"

//Start a manual start of a solenoid valve
#define START_M_LAUNCH_CHARACTERISTIC_UUID "caada16d-3b79-4fe2-a6e0-bc923f3d09bc"

//Start a manual start of a solenoid valve
#define SAVE_A_LAUNCH_CHARACTERISTIC_UUID "d66addbe-49eb-480d-a8d8-54bac35aaf12"

String nameBLEServeur = "";
std::string nameBLEServeurForInit = "testBLE";
String passwordBLEServeur = "";


class changeNameArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pChangeNameCharacteristic)
  {
    std::string value = pChangeNameCharacteristic->getValue();
    Serial.println("Changement du nom effectué");
  }
};

class changePasswordArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pChangePasswordCharacteristic)
  {
    std::string value = pChangePasswordCharacteristic->getValue();
    Serial.println("Changement du mot de passe effectué");
  }
};

class changeTimedArduinoCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pSetTimeCharacteristic)
  {
    std::string value = pSetTimeCharacteristic->getValue();    
    Serial.println("Mise à jour de l''heure effectué");
  }
};

class startingCircuitCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pStartLaunchManualCharacteristic)
  {
    std::string value = pStartLaunchManualCharacteristic->getValue();
    Serial.println("Lancement manuel");
  }
};

class saveFirtAutomaticLaunchCallBacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *psaveAutomaticLaunchCharacteristic)
  {
    std::string value = psaveAutomaticLaunchCharacteristic->getValue();
    Serial.println("Sauvegarde du lancement 1 fait");
  }
};

void setup()
{

  Serial.begin(115200);

  // pinMode(SOLENOID_1, OUTPUT);
  // pinMode(SOLENOID_2, OUTPUT);
  // pinMode(SOLENOID_3, OUTPUT);
  // pinMode(SOLENOID_4, OUTPUT);
  // pinMode(SOLENOID_5, OUTPUT);
  // pinMode(SOLENOID_6, OUTPUT);
  // pinMode(SOLENOID_7, OUTPUT);
  // pinMode(SOLENOID_8, OUTPUT);
  // pinMode(SOLENOID_9, OUTPUT);
  // pinMode(SOLENOID_10, OUTPUT);
  // pinMode(SOLENOID_11, OUTPUT);
  // pinMode(SOLENOID_12, OUTPUT);

  BLEDevice::init(nameBLEServeurForInit);
  BLEServer *pServer = BLEDevice::createServer();

  //Servive écriture mes paramètres
  BLEService *pMyService = pServer->createService(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);

  //Characteristics nombre de relay
  BLECharacteristic *nbRelayCharacteristic = pMyService->createCharacteristic(
      NB_RELAY_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_READ);

  //Characteristics changement du nom de l'Arduino
  BLECharacteristic *pChangeNameCharacteristic = pMyService->createCharacteristic(
      CHANGENAME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics changement du mdp de l'Arduino
  BLECharacteristic *pChangePasswordCharacteristic = pMyService->createCharacteristic(
      PASSWORD_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics mise à jour de l'heure de l'Arduino
  BLECharacteristic *pSetTimeCharacteristic = pMyService->createCharacteristic(
      TIME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Service Lancement Circuit
  BLEService *pMyLaunchService = pServer->createService(SERVICE_LAUNCH_UUID);

  //Characteristics lancement d'un circuit manuellement
  BLECharacteristic *pStartLaunchManualCharacteristic = pMyLaunchService->createCharacteristic(
      START_M_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  //Characteristics lancements automatique
  BLECharacteristic *psaveAutomaticLaunchCharacteristic = pMyLaunchService->createCharacteristic(
      SAVE_A_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);

  pChangePasswordCharacteristic->setCallbacks(new changePasswordArduinoCallBacks());
  pChangeNameCharacteristic->setCallbacks(new changeNameArduinoCallBacks());
  pSetTimeCharacteristic->setCallbacks(new changeTimedArduinoCallBacks());

  pStartLaunchManualCharacteristic->setCallbacks(new startingCircuitCallBacks());
  psaveAutomaticLaunchCharacteristic->setCallbacks(new saveFirtAutomaticLaunchCallBacks());

  nbRelayCharacteristic->setValue(NB_RELAY);

  pMyService->start();
  pMyLaunchService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

  Serial.println("Programmateur " + nameBLEServeur);

}
void loop()
{
}

Bon j'ai essayé pleins de chose :

  • Changer l'UUID
  • renommer ma caractéristique
  • enlever le getvalue() dans ma callback
  • renommer ma callback

Donc je comprends pas trop le problème.

Et après je n'ai pas compris cette partie, je suis jeune et un noob en dev C++

Vérifiez les définitions de BLECharacteristic pour qu'elles soient bien différentes et pas trop longue (Il y avait eu ce souci et il faut vous assurer que vos String sont persistantes si vous utilisez c_str() qui est le pointeur directement dans la zone mémoire de la String (et donc qui peut pointer n'importe où si la String est libérée)

j'ai nettoyé un peu plus votre code et conservé qu'un seul service. vous pouvez tester cela

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

#define NB_RELAY              "12"
#define nameBLEServeurForInit "testBLE"

BLEServer *pServer;
BLECharacteristic *nbRelayCharacteristic;
BLECharacteristic *pChangeNameCharacteristic;
BLECharacteristic *pChangePasswordCharacteristic;
BLECharacteristic *pSetTimeCharacteristic;
BLECharacteristic *pStartLaunchManualCharacteristic;
BLECharacteristic *psaveAutomaticLaunchCharacteristic;

#define SERVICE_CHANGE_PARAMS_ARDUINO_UUID "e660bdcb-638c-4dc6-b613-31610945bddb"   //Service Params Arduino
#define NB_RELAY_CHARACTERISTIC_UUID        "b6c0a045-715f-468d-a271-22d135b4762f"  //Read the number of solenoid valves available
#define CHANGENAME_CHARACTERISTIC_UUID      "9354398f-9105-44da-a58e-80de9a7f5fdc"  //Rename Scheduler
#define PASSWORD_CHARACTERISTIC_UUID        "27349bf0-cd6b-4391-a08f-d7745058b985"  //Change password of Scheduler
#define TIME_CHARACTERISTIC_UUID            "ee1c0d7f-fec3-4f89-ab2f-bb1a1807260d"  //Set Time for Scheduler


class changeNameArduinoCallBacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pChangeNameCharacteristic)
    {
      std::string value = pChangeNameCharacteristic->getValue();
      Serial.println("Changement du nom effectué");
    }
};

class changePasswordArduinoCallBacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pChangePasswordCharacteristic)
    {
      std::string value = pChangePasswordCharacteristic->getValue();
      Serial.println("Changement du mot de passe effectué");
    }
};

class changeTimedArduinoCallBacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pSetTimeCharacteristic)
    {
      std::string value = pSetTimeCharacteristic->getValue();
      Serial.println("Mise à jour de l''heure effectué");
    }
};

class startingCircuitCallBacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *pStartLaunchManualCharacteristic)
    {
      std::string value = pStartLaunchManualCharacteristic->getValue();
      Serial.println("Lancement manuel");
    }
};

class saveFirtAutomaticLaunchCallBacks : public BLECharacteristicCallbacks
{
    void onWrite(BLECharacteristic *psaveAutomaticLaunchCharacteristic)
    {
      std::string value = psaveAutomaticLaunchCharacteristic->getValue();
      Serial.println("Sauvegarde du lancement 1 fait");
    }
};


void setup()
{

  Serial.begin(115200);

  // Create the BLE Device
  BLEDevice::init(nameBLEServeurForInit);

  // Create the BLE Server
  pServer = BLEDevice::createServer();

  // Create the BLE Service
  BLEService *pMyService = pServer->createService(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);

  // *** Characteristics nombre de relay ***
  nbRelayCharacteristic = pMyService->createCharacteristic(
                            NB_RELAY_CHARACTERISTIC_UUID,
                            BLECharacteristic::PROPERTY_READ);
  nbRelayCharacteristic->setValue(NB_RELAY);

  // *** Characteristics changement du nom de l'Arduino ***
  pChangeNameCharacteristic = pMyService->createCharacteristic(
                                CHANGENAME_CHARACTERISTIC_UUID,
                                BLECharacteristic::PROPERTY_WRITE);
  pChangeNameCharacteristic->setCallbacks(new changeNameArduinoCallBacks());

  // *** Characteristics changement du mdp de l'Arduino ***
  pChangePasswordCharacteristic = pMyService->createCharacteristic(
                                    PASSWORD_CHARACTERISTIC_UUID,
                                    BLECharacteristic::PROPERTY_WRITE);
  pChangePasswordCharacteristic->setCallbacks(new changePasswordArduinoCallBacks());

  // *** Characteristics mise à jour de l'heure de l'Arduino ***
  pSetTimeCharacteristic = pMyService->createCharacteristic(
                             TIME_CHARACTERISTIC_UUID,
                             BLECharacteristic::PROPERTY_WRITE);
  pSetTimeCharacteristic->setCallbacks(new changeTimedArduinoCallBacks());

  // start services
  pMyService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  Serial.println("Go ! ");
}


void loop() {
  yield();
}

(tapé sur mon smartphone, pas testé)

Si je test votre code tout est fonctionnel par contre si dans le même service j'exécute ma callback saveautomatics il m'exécute toutes les callbacks.

Et même truc un peu plus difficile à comprendre, j'ai fais directement une caractéristique pour saveAutomatic et pas pour lancementmanuel. Eh ben même lancementmanuel s'exécute même sans caractéristique associée

J'ai un peu repris votre code car il est plus lisible, j'ai refait mes deux services séparés et j'aimerais savoir si c'est possible de faire ça :

  BLEDevice::init(nameBLEServeurForInit);

  pServer = BLEDevice::createServer();

  //Servive écriture mes paramètres
  BLEService *pMyService = pServer->createService(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);

  //Characteristics nombre de relay
  nbRelayCharacteristic = pMyService->createCharacteristic(
      NB_RELAY_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_READ);
  nbRelayCharacteristic->setValue(NB_RELAY);

  //Characteristics changement du nom de l'Arduino
  pChangeNameCharacteristic = pMyService->createCharacteristic(
      CHANGENAME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);
  pChangeNameCharacteristic->setCallbacks(new changeNameArduinoCallBacks());

  //Characteristics changement du mdp de l'Arduino
  pChangePasswordCharacteristic = pMyService->createCharacteristic(
      PASSWORD_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);
  pChangePasswordCharacteristic->setCallbacks(new changePasswordArduinoCallBacks());

  //Characteristics mise à jour de l'heure de l'Arduino
  pSetTimeCharacteristic = pMyService->createCharacteristic(
      TIME_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);
  pSetTimeCharacteristic->setCallbacks(new changeTimedArduinoCallBacks());

  //Service Lancement Circuit
  BLEService *pMyLaunchService = pServer->createService(SERVICE_LAUNCH_UUID);

  //Characteristics lancement d'un circuit manuellement
  pStartLaunchManualCharacteristic = pMyLaunchService->createCharacteristic(
      START_M_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);
  pStartLaunchManualCharacteristic->setCallbacks(new startingCircuitCallBacks());

  //Characteristics lancements automatique
  psaveAutomaticLaunchCharacteristic = pMyLaunchService->createCharacteristic(
      SAVE_A_LAUNCH_CHARACTERISTIC_UUID,
      BLECharacteristic::PROPERTY_WRITE);
  psaveAutomaticLaunchCharacteristic->setCallbacks(new saveFirtAutomaticLaunchCallBacks());

  pMyService->start();
  pMyLaunchService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_CHANGE_PARAMS_ARDUINO_UUID);
  pAdvertising->addServiceUUID(SERVICE_LAUNCH_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);

  BLEDevice::startAdvertising();

Après j'ai regarder sur Arduin.com la lib BLE, j'ai trouvé un ça, est-ce que c'est pas utilise dans mon cas ?
ArduinoBLE - Arduino Reference

par contre si dans le même service j'exécute ma callback saveautomatics il m'exécute toutes les callbacks.

concrètement ça veut dire quoi ? quel code ? (votre callback est dans une sous classe. vous l'instanciez et appelez la méthode onWrite() ??

Après j'ai regarder sur Arduin.com la lib BLE

Quand on "subscribe" à une Characteristic c'est comme si vous vous "abonnez" pour recevoir les modifications sans avoir à constamment demander. unsubscribe ça veut dire qu'on ne veut plus recevoir les notifications

Par exemple je suis sur mon application,

Je veux changer le nom donc dans ma console : (changeNameArduinoCallBacks())
Changement du nom effectué

Je veux changer le mot de passe donc dans ma console : (changePasswordArduinoCallBacks())
Changement du mot de passe effectué

Je veux changer l'heure donc dans ma console : (changeTimedArduinoCallBacks())
Mise à jour de l''heure effectué
2020/10/20 9:44:0

Je veux exécuté un lancement manuellement donc dans ma console : (startingCircuitCallBacks())
testLM
Wattering circuit n°1

Et là si je veux faire une sauvegarde de mon circuit automatique dans ma console j'ai tout ça qui s'ajoute : (saveFirtAutomaticLaunchCallBacks())
Changement du nom effectué
Changement du mot de passe effectué
Mise à jour de l''heure effectué
2020/10/20 9:44:0
testLM
Sauvegarde du lancement 1 fait

Quand la callback saveFirtAutomaticLaunchCallBacks() est appelé, j'ai l'impression quelle exécute toutes les autres callbacks

J'ai repris votre code du post 8 sans modifications, lorsque je l'installe sur mon ESP et que je me connecte depuis mon smartphone avec l'application LightBlue, je vois bien les infos des 2 services

et quand j'essaye de les modifier les values une par une, la console me dit

[color=purple]
Changement du nom effectué
Changement du mot de passe effectué
Mise à jour de l''heure effectué
Lancement manuel
Sauvegarde du lancement 1 fait
[/color]

et la lecture de la propriété en mode READ me dit bien "12" (en hexa 0x3132 qui sont les codes ascii associés)

donc je ne vois pas le souci que vous avez d'exécutions multiples

J'ai essayé de même et effectivement pas de problème de multi exécution, donc je pense que je vais relire mon code côté application car je pense que mon soucis et par là.

Juste comment faire pour "nommer" les services et caractéristiques, pour éviter d'avoir l'UUID sur un scanner comme dans votre photo

Bon je viens de comprendre une partie de mon problème.

J'ai essayer avec mon code C++ d'utiliser LightBlue.

Si je passe imaginons juste un "Salut" il m'exécute bien que ma callbacks, par contre si j'envoie avec lightBlue le texte que mon appli envoie, la toutes mes callbacks sont exécutées.

Par exemple j'ai essayé et si j'envoie "azertyuiopqsdfghjklm" tout va bien mais "azertyuiopqsdfghjklmw" toutes les callbacks sont appelées.

vous mettez bien un '\0' à la fin de votre modification ?

Juste comment faire pour "nommer" les services et caractéristiques, pour éviter d'avoir l'UUID sur un scanner comme dans votre photo

De mémoire il faut rajouter un descriptor ("Characteristic User Description Descriptor") à votre caractéristique. Les descripteurs de caractéristiques du GATT (communément appelés simplement descripteurs) sont principalement utilisés pour fournir au client des métadonnées (informations supplémentaires sur la caractéristique et sa valeur). Ils sont toujours placés dans la définition de caractéristique et après l'attribut de valeur de caractéristique

EDIT: j'ai eu un peu de temps, voici un bout de code:
Dans votre code du post 8, si vous définissez votre characteristic du nombre de relais comme avant mais ajoutez un descriptor supplémentaire

  //Characteristics nombre de relay
  BLECharacteristic *nbRelayCharacteristic = pMyService->createCharacteristic(
        NB_RELAY_CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ);

  BLEDescriptor *nbRelayDescriptor = new BLEDescriptor((uint16_t)0x2901); // Characteristic User Description
  nbRelayDescriptor->setValue("NB RELAY");
  nbRelayCharacteristic->addDescriptor(nbRelayDescriptor);

Alors ce descripteur standard est repris par les outils de scan

(attention je crois qu'il y a un nombre max de handles qui est assez faible - je ne me souviens plus exactement de combien - 16 peut-être)

EDIT: ça m'énervait de ne pas me souvenir, donc c'est dans le prototype de la méthode createService() du BLEServer BLEService*    createService(BLEUUID uuid, uint32_t numHandles=15, uint8_t inst_id=0);donc si vous voulez dépasser 15 il faut appeler createService() avec un second paramètre plus grand.

Les caractéristiques ont besoin de 2 handles et un descripteur en consomme un.

vous mettez bien un '\0' à la fin de votre modification ?

Je n'ai pas compris ou je dois mettre ça ? Car je n'en mets pas et à quoi sert-il ?

//Characteristics nombre de relay

BLECharacteristic *nbRelayCharacteristic = pMyService->createCharacteristic(
        NB_RELAY_CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ);

BLEDescriptor *nbRelayDescriptor = new BLEDescriptor((uint16_t)0x2901); // Characteristic User Description
  nbRelayDescriptor->setValue("NB RELAY");
  nbRelayCharacteristic->addDescriptor(nbRelayDescriptor);

A quoi sert le (uint16_t)0x2901 ?

donc si vous voulez dépasser 15 il faut appeler createService() avec un second paramètre plus grand.

Les caractéristiques ont besoin de 2 handles et un descripteur en consomme un.

Il me faudrait plus d'infos car je connais très peu le bluetooth du coup je n'ai pas compris.

Mais merci beaucoup pour les réponses