Aquaboun's /// gestion d'aquarium recifal

J-M-L:
un petit coup d’AJAX sans doute - faut que je trouve le temps de faire un petit tuto

Laisse tombé, y a ma femme pour ça !

plus sérieusement, si je comprend bien l'ajax permettrais de mettre a jour les variable sur la page web sans avoir besoin de la recharger ?

Pas très galant tout cela ...

Oui avec AJAX la page statique pourrait venir du SPIFFS (un système de fichier simple sur l’ESP) et cette page mettrait à jour des sous parties par une approche AJAX. comme on envoie moins de données c’est plus efficace malgré les ACK et c’est plus joli à l’oeil Car on ne recharge pas toute la page

petit début de tuto posté pour la partie SPIFFS

le reste quand j'ai un peu plus de temps....

Comme conseiller j'ai installer la bibliothèque FSBrowserNG et tout celle associées.
Cloner manuellement l'esp8266
Et j'ai fini par réussir a compiler sans erreur.

J'ai donc voulu televerser le code exemple Userconfigexemple.

Et j'arrive toujours a ce message:

Archiving built core (caching) in: C:\Users\djbouns\AppData\Local\Temp\arduino_cache_384035\core\core_esp8266com_esp8266_d1_mini_lite_CpuFrequency_80,FlashSize_1M0,LwIPVariant_open,Debug_Disabled,DebugLevel_None____,UploadSpeed_115200_59f27b87b1649ba33697614d4ec8334b.a
Le croquis utilise 367911 octets (35%) de l'espace de stockage de programmes. Le maximum est de 1023984 octets.
Les variables globales utilisent 40820 octets (49%) de mémoire dynamique, ce qui laisse 41100 octets pour les variables locales. Le maximum est de 81920 octets.
java.io.IOException: Cannot run program "C:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266/tools/esptool/esptool.exe": CreateProcess error=2, Le fichier spécifié est introuvable
 at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
 at processing.app.helpers.ProcessUtils.exec(ProcessUtils.java:26)
 at cc.arduino.packages.Uploader.executeUploadCommand(Uploader.java:129)
 at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:207)
 at cc.arduino.UploaderUtils.upload(UploaderUtils.java:78)
 at processing.app.SketchController.upload(SketchController.java:713)
 at processing.app.SketchController.exportApplet(SketchController.java:686)
 at processing.app.Editor$DefaultExportHandler.run(Editor.java:2168)
 at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: CreateProcess error=2, Le fichier spécifié est introuvable
 at java.lang.ProcessImpl.create(Native Method)
 at java.lang.ProcessImpl.<init>(ProcessImpl.java:386)
 at java.lang.ProcessImpl.start(ProcessImpl.java:137)
 at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
 ... 8 more
Une erreur est survenue lors du transfert du croquis
C:\Program Files (x86)\Arduino\hardware\esp8266com\esp8266/tools/esptool/esptool.exe
Le fichier spécifié est introuvable

esptool.exe est bien a cette emplacement.

Une idée ?

djbouns:
J'ai intégré la parti web a mon code principal.
Pas de problème a la compilation.
Mais une fois televersé, rien ne se lance.
J'ai placé des "Serial.print" a différent endroit pour voir ou était le problème et même pas uns ligne sur le moniteur ... donc j'en déduit un bug total :frowning:

Depuis ce jour la , impossible de refaire fonctionné mon code, même en retirant toute la partie web ...
Ça va passer par la fenêtre ...

il faut peut-être revenir à la version précédente de la librairie pour votre code?

J-M-L:
il faut peut-être revenir à la version précédente de la librairie pour votre code?

Je n'ai pas changer de librairie ...

djbouns:
Depuis ce jour la , impossible de refaire fonctionné mon code, même en retirant toute la partie web ...
Ça va passer par la fenêtre ...

Avec vos #include de code source c’est quasiment impossible de comprendre la structure de la loop, le chevauchement possible de variables et l’allocation mémoire....

Peut être débordez vous la mémoire au run time ?

Il faut que que cree tout ces fonction en VOID et que je les laisses en une page ?

l'idéal serait de définir "proprement" ce que doit faire la loop() sous forme sans doute d'une machine à état pour chacun des sous systèmes.

Chaque appel dans la loop() doit être non bloquant et rapide.

J-M-L:
l'idéal serait de définir "proprement" ce que doit faire la loop() sous forme sans doute d'une machine à état pour chacun des sous systèmes.

Chaque appel dans la loop() doit être non bloquant et rapide.

Je ne comprend pas du tout comment mettre cela en forme de cette façon.

A tu un exemple sous cette forme que je vois stp ?

cf mon tuto éventuellement

La loop() écoute les différents événements possibles et agit en conséquence. Il y a une variable globale (ou plusieurs si plusieurs sous systèmes) qui vont aider à savoir là où on en est dans les différents traitements.

c'est pour cela que je vous demandais le cahier des charges. il y a un bon début de boulot dans ce que vous avez partagé, mais il manque la "logique" (ce qu'il faut faire) pour chaque sous système . Quelles décisions doivent être prises par l'Arduino et en fonction de quoi

Comme très souvent je comprend le principe ... Ya qu'a ... lol
la plus part des fonctions sont generé en fonction de l'heure.
exemple, de 10h a 12h lever soleil
de 12h a 20h soleil zenith
20h a 22h coucher soleil
de 22h a 10h eteint

Le code donne ca:

if ((time >= LEVERbleu1) && (time < finLEVERbleu1)){ 
  pwmbleu1 = map(time, LEVERbleu1, finLEVERbleu1, 0, puissancebleu);
  analogWrite (bleu1, pwmbleu1);
  }
else if ((time >= COUCHERbleu1) && (time < finCOUCHERbleu1)){  
  pwmbleu1 = map(time, COUCHERbleu1, finCOUCHERbleu1, puissancebleu, 0);
  analogWrite (bleu1, pwmbleu1); 
  }   
else if ((time >= finLEVERbleu1 ) && (time < COUCHERbleu1)) {
  pwmbleu1 = puissancebleu;
  analogWrite(bleu1, puissancebleu);
  }
else {
  pwmbleu1 = 0;
  analogWrite(bleu1, 0);

Dans le loop il faut donc mettre la lecture de l'heure.
Dans le setup, associé chaque créneau horaire a une fonction
Déclarer chaque fonction en VOID

c'est ca ?

J'ai vu d'autre exemple (mais pas d'exemple avec des condition comme moi) sur le net et si je les adaptes j'arrive a :

void debutleverblanc1 {
  if ((Time >= debut_LEVER_blanc1) && (Time < fin_LEVER_blanc1)){ 
  pwm_blanc1 = map(Time, debut_LEVER_blanc1, fin_LEVER_blanc1, 0, puissance_blanc);
  analogWrite (pinOUT_blanc1, pwm_blanc1);
  }
}

void debutcoucherblanc1{
if ((Time >= debut_COUCHER_blanc1) && (Time < fin_COUCHER_blanc1)){  
  pwm_blanc1 = map(Time, debut_COUCHER_blanc1, fin_COUCHER_blanc1, puissance_blanc, 0);
  analogWrite (pinOUT_blanc1, pwm_blanc1); 
  }
}
   
void finleverblanc1 {
  if ((Time >= fin_LEVER_blanc1 ) && (Time < debut_COUCHER_blanc1)) {
  pwm_blanc1 = puissance_blanc;
  analogWrite(pinOUT_blanc1, puissance_blanc);
  }
}

Mais pour le else ?

else {
  pwm_blanc1 = 0;
  analogWrite(pinOUT_blanc1, 0);
}

Si je le met dans un void il ne feras pas le lien avec les if dans les void précédent ?

djbouns:
Donc dans le serial le sms est bien lu mais la réponse recu par sms est toujours la même quelque soit le sms envoyer commencant pas ssid

La config est la suivante : SSID = d

Je me suis re penché sur la partie SMS.
Je suis arrivé a avoir une réponse correcte a mes demandes.

Voyer vous des incohérences ? si non, je l’inclus dans mon code principale

#define gsm Serial1

char * _SSID ;
char * _MDP ;

const byte ctrlZ = 0x1A;
const char * ctrlZString = "\x1A";
const char * escapeString = "\x1B";

const char * ATString = "AT";
const char * OKShortString = "OK";
const char * OKLongString = "\r\nOK\r\n";

const byte max_SSID = 50;// prévoir la bonne longueur
char copie_SSID[max_SSID+1]; 
const byte max_MDP = 50;// prévoir la bonne longueur
char copie_MDP[max_MDP+1]; 

          
const uint32_t oneSecond = 1000ul;

const byte maxMessageSize = 200;
char GSM_MessageLine[maxMessageSize + 1]; // +1 pour le '\0' à la fin de la c-string

// --------------------------------------
// gsmPrintlnAndWaitATCommand executes an AT commmand by adding at the end a CR LF
// then it checks if endMarker string is receivedon the GSM Serial port
// for max duration ms returns a boolean stating if the marker was found
// with the verbose option, the output from the GSM is also printed to Serial
// --------------------------------------

boolean gsmPrintlnAndWaitATCommand(const char * command, const char * endMarker, unsigned long duration, boolean verbose)
{
  gsm.println(command);
  return waitForString(endMarker, duration, verbose);
}

boolean gsmPrintAndWaitATCommand(const char * command, const char * endMarker, unsigned long duration, boolean verbose)
{
  gsm.print(command);
  return waitForString(endMarker, duration, verbose);
}

// --------------------------------------
// gsmPrintATCommand or gsmpWriteATCommand is used when you don't want to send the CR LF
// at the end of the commmand line; use it to build up a multi part command
// same syntax as print as they are Variadic Macros using print or write
// --------------------------------------
#define gsmPrintATCommand(...)    gsm.print(__VA_ARGS__)
#define gsmPrintlnATCommand(...)  gsm.println(__VA_ARGS__)
#define gsmWriteATCommand(...)    gsm.write(__VA_ARGS__)


// --------------------------------------
// read a line from gsm, ignore '\r' and returns true if '\n' is found
// --------------------------------------

boolean getGSMLine()
{
  static byte indexMessage = 0;
  boolean incomingMessage = true;

  while (gsm.available() && incomingMessage) {
    int c = gsm.read();
    if (c != -1) {
      switch (c) {
        case '\n':
          GSM_MessageLine[indexMessage] = '\0'; // trailing NULL char for a correct c-string
          indexMessage = 0; // get ready for next time
          incomingMessage = false;
          break;
        case '\r': // don't care about this one
          break;
        default:
          if (indexMessage <= maxMessageSize - 1) GSM_MessageLine[indexMessage++] = (char) c; // else ignore it..
          break;
      }
    }
  }
  return !incomingMessage;
}

// --------------------------------------
// waitForString wait max for duration ms whilst checking if endMarker string is received
// on the GSM Serial port returns a boolean stating if the marker was found
// --------------------------------------

boolean waitForString(const char * endMarker, unsigned long duration, boolean verbose)
{
  int localBufferSize = strlen(endMarker);
  char localBuffer[localBufferSize];
  int index = 0;
  boolean endMarkerFound = false;
  unsigned long currentTime;

  memset(localBuffer, '\0', localBufferSize); // clear buffer

  currentTime = millis();
  while (millis() - currentTime <= duration) {
    if (gsm.available() > 0) {
      if (index == localBufferSize) index = 0;
      localBuffer[index] = (uint8_t) gsm.read();
      if (verbose) Serial.print((char) localBuffer[index]);
      endMarkerFound = true;
      for (int i = 0; i < localBufferSize; i++) {
        if (localBuffer[(index + 1 + i) % localBufferSize] != endMarker[i]) {
          endMarkerFound = false;
          break;
        }
      }
      index++;
    }
    if (endMarkerFound) break;
  }
  return endMarkerFound;
}

void dieHere()
{
  while (true);
}


void setup() {
  Serial.begin(115200);
  gsm.begin(9600); // suivant votre config, essayez 9600 19200 38400 57600 74880 115200

  // prévoir éventuellement AT+CPIN="1234" pour rentrer le PIN

  if (gsmPrintlnAndWaitATCommand(ATString, OKLongString, 5 * oneSecond, false)) {
    Serial.println(F("GPRS Modem OK"));
  } else {
    Serial.println(F("Erreur GPRS Modem"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("AT+GSV", OKLongString, oneSecond, true)) {
    Serial.print(F("Erreur Version"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("ATE0", OKLongString, oneSecond, false)) {
    Serial.print(F("Erreur Echo off"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("ATV1", OKLongString, oneSecond, false)) {
    Serial.print(F("Erreur Message en Verbal"));
    dieHere();
  }

  // on passe en les SMS en mode texte
  if (!gsmPrintlnAndWaitATCommand("AT+CMGF=1", OKLongString, oneSecond, true)) {
    Serial.print(F("Error AT+CMGF"));
    // dieHere(); // on ne meurt pas ici mais AT+CNMI non configurgé
  }


  // on passe en mode routage des SMS vers le terminal
  if (!gsmPrintlnAndWaitATCommand("AT+CNMI=1,2,0,0,0", OKLongString, oneSecond, true)) {
    Serial.print(F("Error AT+CNMI"));
    // dieHere(); // on ne meurt pas ici mais AT+CNMI non configurgé
  }

  Serial.println("Initialisation terminé");
}

boolean sendSMS(const char * noDeTel, const char * messageAEnvoyer)
{
  boolean SMSenvoye = false;
  gsmPrintATCommand("AT+CMGS=\"");
  gsmPrintATCommand(noDeTel);

  if (gsmPrintlnAndWaitATCommand("\"", ">", oneSecond, false)) {
    gsmPrintlnATCommand(messageAEnvoyer);
    SMSenvoye = gsmPrintlnAndWaitATCommand(ctrlZString, OKShortString, 5 * oneSecond, false);
  } else {
    gsmPrintlnATCommand(escapeString);
  }
  return SMSenvoye;
}

void loop()
{
  if (getGSMLine()) {
    // ********************************************
    // TEST RECEPTION D'UN SMS
    // +CMT: "+33620000000",,"01/03/22,16:33:31+00"<CRLF>
    // texte bla bla bla<CRLF>
    // ********************************************
    if (!strncmp(GSM_MessageLine, "+CMT:", 5)) {// 5 parce que "+CMT:" c'est 5 caractères, on compare le début de la chaîne
      const byte maxDigitsPhoneNb = 30;
      char phoneNb[maxDigitsPhoneNb + 1];
      char *ptr = strtok(GSM_MessageLine, "\"");
      if (ptr) {
        ptr =  strtok(NULL, "\"");
        strncpy(phoneNb, ptr, maxDigitsPhoneNb);
        phoneNb[maxDigitsPhoneNb] = '\0';

        // *** DEBUG *** POUR VOIR CE QU'IL SE PASSE
        Serial.print(F("SMS de = ")); Serial.println(phoneNb);
        // ***

        while (!getGSMLine()); // on attend le texte du SMS

        // *** DEBUG *** POUR VOIR CE QU'IL SE PASSE
        Serial.print(F("Message = [")); Serial.print(GSM_MessageLine); Serial.println(F("]"));
        // ***

        if (!strncmp(GSM_MessageLine, "CONFIG", 6)) { // 6 parce que 6 caractères dans le mot "CONFIG"
          // on a rerçu un SMS nous demandant la config, on construit la réponse
          strcpy(GSM_MessageLine, "La config est la suivante:\r\nSSID = ");
          strcat(GSM_MessageLine, _SSID);
          strcat(GSM_MessageLine, "\r\nMot de Passe = ");
          strcat(GSM_MessageLine, _MDP);
          sendSMS(phoneNb, GSM_MessageLine);
        } 
        else if (!strncmp(GSM_MessageLine, "Ssid", 4)) { // 6 parce que 6 caractères dans le mot "CONFIG"
          _SSID = GSM_MessageLine + 5; // Notez que c'est aussi simple d'écrire _SSID = GSM_MessageLine+6;... 
          strncpy(copie_SSID, _SSID,max_SSID);
          copie_SSID[max_SSID] = '\0';
          _SSID = copie_SSID;
          strcpy(GSM_MessageLine, "nouveau SSID recu = ");
          strcat(GSM_MessageLine, _SSID);
          sendSMS(phoneNb, GSM_MessageLine);
        }
        else if (!strncmp(GSM_MessageLine, "Mdp", 3)) { // 6 parce que 6 caractères dans le mot "CONFIG"
          _MDP = GSM_MessageLine + 4; // Notez que c'est aussi simple d'écrire _SSID = GSM_MessageLine+6;... 
          strncpy(copie_MDP, _MDP,max_MDP);
          copie_MDP[max_MDP] = '\0';
          _MDP = copie_MDP;
          strcpy(GSM_MessageLine, "nouveau MDP recu = ");
          strcat(GSM_MessageLine, _MDP);
          sendSMS(phoneNb, GSM_MessageLine);
        }         
        else {
          sendSMS(phoneNb, "Pas compris");
        }
      }
    }
  }
}

* A mon avis ici c'est pas _SSID qu'il faut mais copie_SSID et idem pour _MDP il faut prendre copie_MDP à condition bien sûr de les avoir extraits auparavant

 strcat(GSM_MessageLine, _SSID);
...
strcat(GSM_MessageLine, _MDP);

* Le code suppose que votre SMS ne contienne pas plusieurs lignes - mais ça peut être une convention.

* C'est mieux quand les commentaires correspondent au code :slight_smile:

else if (!strncmp(GSM_MessageLine, "Ssid", 4)) { // 6 parce que 6 caractères dans le mot "CONFIG".
..
else if (!strncmp(GSM_MessageLine, "Mdp", 3)) { // 6 parce que 6 caractères dans le mot "CONFIG"

passez aussi éventuellement tous les commentaires en français, ce sera utile pour les non anglophones

J-M-L:
* A mon avis ici c'est pas _SSID qu'il faut mais copie_SSID et idem pour _MDP il faut prendre copie_MDP à condition bien sûr de les avoir extraits auparavant

strcat(GSM_MessageLine, _SSID);

...
strcat(GSM_MessageLine, _MDP);

Au début le code était comme vous dite mais du coup le contenu n’était pas enregistré dans _SSID
C'est pour cela qua j'ai fait

_SSID = copie_SSID;

J-M-L:
* Le code suppose que votre SMS ne contienne pas plusieurs lignes - mais ça peut être une convention.

Les MDP reseau peuvent être assez long.
j'ai testé des sms avec "MDP 20caracterre espace 5 caractères espace 20 caractères" soit 51 caractères et tout ces bien passé. Quand j'ai ensuite envoyer CONFIG, j'ai bien reçu tout le MDP soit 47 caractères.
Donc pour moi c'est OK (a voir dans le code principal + wifi)

J-M-L:
* C'est mieux quand les commentaires correspondent au code :slight_smile:

else if (!strncmp(GSM_MessageLine, "Ssid", 4)) { // 6 parce que 6 caractères dans le mot "CONFIG".

..
else if (!strncmp(GSM_MessageLine, "Mdp", 3)) { // 6 parce que 6 caractères dans le mot "CONFIG"



passez aussi éventuellement tous les commentaires en français, ce sera utile pour les non anglophones

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

#define gsm Serial1

char * _SSID ;
char * _MDP ;

const byte ctrlZ = 0x1A;
const char * ctrlZString = "\x1A";
const char * escapeString = "\x1B";

const char * ATString = "AT";
const char * OKShortString = "OK";
const char * OKLongString = "\r\nOK\r\n";

const byte max_SSID = 50;// prévoir la bonne longueur
char copie_SSID[max_SSID+1]; 
const byte max_MDP = 50;// prévoir la bonne longueur
char copie_MDP[max_MDP+1]; 

          
const uint32_t oneSecond = 1000ul;

const byte maxMessageSize = 200;
char GSM_MessageLine[maxMessageSize + 1]; // +1 pour le '\0' à la fin de la c-string

// --------------------------------------
//GsmPrintlnAndWaitATCommand exécute une commmand AT en ajoutant à la fin CR LF
//alors, il vérifie si endMarker est recu sur le Port série GSM
//pour la durée Max , boolean si le marqueur a été trouvé
//avec l'option verbeuse, les info du GSM sont imprimées dans le serial

// --------------------------------------

boolean gsmPrintlnAndWaitATCommand(const char * command, const char * endMarker, unsigned long duration, boolean verbose)
{
  gsm.println(command);
  return waitForString(endMarker, duration, verbose);
}

boolean gsmPrintAndWaitATCommand(const char * command, const char * endMarker, unsigned long duration, boolean verbose)
{
  gsm.print(command);
  return waitForString(endMarker, duration, verbose);
}

// --------------------------------------
//GsmPrintATCommand ou gsmpWriteATCommand est utilisé quand vous ne voulez pas envoyer à CR LF
//à la fin de la ligne de commmand; utilisez il développer une partie multi commande
//la même syntaxe est imprimé comme ils sont des Macros Variadic utilisant imprimé ou écrivent
// --------------------------------------

#define gsmPrintATCommand(...)    gsm.print(__VA_ARGS__)
#define gsmPrintlnATCommand(...)  gsm.println(__VA_ARGS__)
#define gsmWriteATCommand(...)    gsm.write(__VA_ARGS__)


// --------------------------------------
// Lise une ligne de gsm, ignorez '\r ' et des retours vrais si '\n ' est trouvé
// --------------------------------------

boolean getGSMLine()
{
  static byte indexMessage = 0;
  boolean incomingMessage = true;

  while (gsm.available() && incomingMessage) {
    int c = gsm.read();
    if (c != -1) {
      switch (c) {
        case '\n':
          GSM_MessageLine[indexMessage] = '\0'; // a la fin character NULL pour c-string correct
          indexMessage = 0; // pret pour la suite
          incomingMessage = false;
          break;
        case '\r': // n'est pas pris en compte
          break;
        default:
          if (indexMessage <= maxMessageSize - 1) GSM_MessageLine[indexMessage++] = (char) c; // sinon ignoré
          break;
      }
    }
  }
  return !incomingMessage;
}

// --------------------------------------
// WaitForString attend la duree Max ms en vérifiant si endMarker est reçue
// Sur le Port série GSM rend une déclaration boolean si le marqueur a été trouvé
// --------------------------------------

boolean waitForString(const char * endMarker, unsigned long duration, boolean verbose)
{
  int localBufferSize = strlen(endMarker);
  char localBuffer[localBufferSize];
  int index = 0;
  boolean endMarkerFound = false;
  unsigned long currentTime;

  memset(localBuffer, '\0', localBufferSize); // effacer buffer

  currentTime = millis();
  while (millis() - currentTime <= duration) {
    if (gsm.available() > 0) {
      if (index == localBufferSize) index = 0;
      localBuffer[index] = (uint8_t) gsm.read();
      if (verbose) Serial.print((char) localBuffer[index]);
      endMarkerFound = true;
      for (int i = 0; i < localBufferSize; i++) {
        if (localBuffer[(index + 1 + i) % localBufferSize] != endMarker[i]) {
          endMarkerFound = false;
          break;
        }
      }
      index++;
    }
    if (endMarkerFound) break;
  }
  return endMarkerFound;
}

void dieHere()
{
  while (true);
}


void setup() {
  Serial.begin(115200);
  gsm.begin(9600); // suivant votre config, essayez 9600 19200 38400 57600 74880 115200

  // prévoir éventuellement AT+CPIN="1234" pour rentrer le PIN

  if (gsmPrintlnAndWaitATCommand(ATString, OKLongString, 5 * oneSecond, false)) {
    Serial.println(F("GPRS Modem OK"));
  } else {
    Serial.println(F("Erreur GPRS Modem"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("AT+GSV", OKLongString, oneSecond, true)) {
    Serial.print(F("Erreur Version"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("ATE0", OKLongString, oneSecond, false)) {
    Serial.print(F("Erreur Echo off"));
    dieHere();
  }

  if (!gsmPrintlnAndWaitATCommand("ATV1", OKLongString, oneSecond, false)) {
    Serial.print(F("Erreur Message en Verbal"));
    dieHere();
  }

  // on passe en les SMS en mode texte
  if (!gsmPrintlnAndWaitATCommand("AT+CMGF=1", OKLongString, oneSecond, true)) {
    Serial.print(F("Error AT+CMGF"));
    // dieHere(); // on ne meurt pas ici mais AT+CNMI non configurgé
  }


  // on passe en mode routage des SMS vers le terminal
  if (!gsmPrintlnAndWaitATCommand("AT+CNMI=1,2,0,0,0", OKLongString, oneSecond, true)) {
    Serial.print(F("Error AT+CNMI"));
    // dieHere(); // on ne meurt pas ici mais AT+CNMI non configurgé
  }

  Serial.println("Initialisation terminé");
}

boolean sendSMS(const char * noDeTel, const char * messageAEnvoyer)
{
  boolean SMSenvoye = false;
  gsmPrintATCommand("AT+CMGS=\"");
  gsmPrintATCommand(noDeTel);

  if (gsmPrintlnAndWaitATCommand("\"", ">", oneSecond, false)) {
    gsmPrintlnATCommand(messageAEnvoyer);
    SMSenvoye = gsmPrintlnAndWaitATCommand(ctrlZString, OKShortString, 5 * oneSecond, false);
  } else {
    gsmPrintlnATCommand(escapeString);
  }
  return SMSenvoye;
}

void loop()
{
  if (getGSMLine()) {
    // ********************************************
    // TEST RECEPTION D'UN SMS
    // +CMT: "+33620000000",,"01/03/22,16:33:31+00"<CRLF>
    // texte bla bla bla<CRLF>
    // ********************************************
    if (!strncmp(GSM_MessageLine, "+CMT:", 5)) {// 5 parce que "+CMT:" c'est 5 caractères, on compare le début de la chaîne
      const byte maxDigitsPhoneNb = 30;
      char phoneNb[maxDigitsPhoneNb + 1];
      char *ptr = strtok(GSM_MessageLine, "\"");
      if (ptr) {
        ptr =  strtok(NULL, "\"");
        strncpy(phoneNb, ptr, maxDigitsPhoneNb);
        phoneNb[maxDigitsPhoneNb] = '\0';

        // *** DEBUG *** POUR VOIR CE QU'IL SE PASSE
        Serial.print(F("SMS de = ")); Serial.println(phoneNb);
        // ***

        while (!getGSMLine()); // on attend le texte du SMS

        // *** DEBUG *** POUR VOIR CE QU'IL SE PASSE
        Serial.print(F("Message = [")); Serial.print(GSM_MessageLine); Serial.println(F("]"));
        // ***

        if (!strncmp(GSM_MessageLine, "CONFIG", 6)) { // 6 parce que 6 caractères dans le mot "CONFIG"
          // on a reçu un SMS nous demandant la config, on construit la réponse
          strcpy(GSM_MessageLine, "La config est la suivante:\r\nSSID = ");
          strcat(GSM_MessageLine, _SSID);
          strcat(GSM_MessageLine, "\r\nMot de Passe = ");
          strcat(GSM_MessageLine, _MDP);
          sendSMS(phoneNb, GSM_MessageLine);
        } 
        else if (!strncmp(GSM_MessageLine, "Ssid", 4)) { // 4 parce que 4 caractères dans le mot "Ssid"
          // on a reçu un SMS nous indiquant un nouveau Ssid, on construit la réponse
          _SSID = GSM_MessageLine + 5; // on extrait le Ssid du message
          strncpy(copie_SSID, _SSID,max_SSID);
          copie_SSID[max_SSID] = '\0';
          _SSID = copie_SSID;
          strcpy(GSM_MessageLine, "nouveau SSID recu = ");
          strcat(GSM_MessageLine, _SSID);
          sendSMS(phoneNb, GSM_MessageLine);
        }
        else if (!strncmp(GSM_MessageLine, "Mdp", 3)) { // 3 parce que 3 caractères dans le mot "Mdp"
           // on a reçu un SMS nous indiquant un nouveau Mdp, on construit la réponse
          _MDP = GSM_MessageLine + 4; // on extrait le Mdp du message
          strncpy(copie_MDP, _MDP,max_MDP);
          copie_MDP[max_MDP] = '\0';
          _MDP = copie_MDP;
          strcpy(GSM_MessageLine, "nouveau MDP recu = ");
          strcat(GSM_MessageLine, _MDP);
          sendSMS(phoneNb, GSM_MessageLine);
        }         
        else {
          sendSMS(phoneNb, "Instruction non comprise");
        }
      }
    }
  }
}

:slight_smile:

J'ai fait au mieux pour la traduction

Ah oui j'avais raté le _SSID = copie_SSID; donc ça va (vous auriez pu directement utiliser copie_SSID)

J-M-L:
Ah oui j'avais raté le _SSID = copie_SSID; donc ça va (vous auriez pu directement utiliser copie_SSID)

Dans la partir wifi le ssid et mdp sont déclare en char *
J'ai donc fait comme ca pour que la "fusion" des code ne pause pas de problème.