Ma loop de sort jamais

Bonjour
je m’excuse mais j’aurais besoin d’un petit coup de pouce a comrendre une fonction, une partie de code.
Je ne l’ai pas écris, je me souviens plus ou jel’ai trouvé mais j’aimerais le faire marcher

En gros,
J’excute ces commande

AT+HTTPPARA="URL","http://www.google.ch"
AT+HTTPACTION=0
AT+HTTPREAD=0,100

Ces trois commande me retourne OK

AT+HTTPREAD me retourne en plus ceci exactement:

AT+HTTPREAD=0,100
+HTTPREAD:100
<!doctype html><html itemscope= itemtype=http://schema.org/WebPage lang=de-CH><head><meta cont
OK

Juste après j’ai ce code (où e bloque) qui va “calculer” la répomse, soit ce qui se trouve en dessous de +HTTPREAD:100

Le probleme c’est qu’il ne sort jamais du premiere do:

answer = sendATcommand2(str_aux1,OK_RESPONSE,"+HTTPREAD:", 30000,true,true);

                  if(answer == 2)
                  {
                    data_size = 0;
                    while(_cell.available()==0);
                    aux = _cell.read();
                      
// IL NE SORT JAMAIS DE CETTE BOUCLE DO
                    do{
                        data_size *= 10;
                        data_size += (aux-0x30);
                        while(_cell.available()==0);
                        aux = _cell.read();        
                    }while(aux != 0x0D);
                    //}while(aux != '\r');

                    #ifdef DEBUG_SEND
                        sprint(F("Received:"));
                        Serial.println(data_size);
                    #endif

                    if (data_size > 0)
                    {
                        while(_cell.available() < data_size);
                        _cell.read();

                        for (int y = 0; y < data_size; y++)
                        {
                          buffer[x] = _cell.read();
                          x++;
                        }
                        buffer[x] = '\0';
                    }
                    else
                    {
                        #ifdef DEBUG_SEND
                          sprintln(F("End"));    
                        #endif

                        #ifdef DEBUG
                          sprint(F("Received:"));
                          sprintln(buffer);
                        #endif
                    }
                  }
                  else if (answer == 1)
                  {
                    #ifdef DEBUG_SEND
                      Serial.println(F("No data"));
                    #endif
                    data_size = 0;
                  }
                  else
                  {
                    #ifdef DEBUG
                      Serial.println(F("ERR HTTP"));
                    #endif  
      
                    data_size = -1;
                  }

Malheureusement, je n’arrive a comprende cette toute petite partie (*= et +=)
Je suppose que 0x30 c’est 0 et 0x0D c’est egal à \r ou 13

data_size *= 10;
                        
data_size += (aux-0x30);

Merci

+=	additionne deux valeurs et stocke le résultat dans la variable (à gauche)
-=	soustrait deux valeurs et stocke le résultat dans la variable
*=	multiplie deux valeurs et stocke le résultat dans la variable

Donc je suppose que si data_size est egal à 0 et aux est egal à < (premier caractere)

 do{
                        data_size *= 10; // data_size = 0*10 = 0
                        data_size += (aux-0x30); // data_size = 0+ <-0 = ??? Là, je bug
                        while(_cell.available()==0);
                        aux = _cell.read();       
                    }while(aux != 0x0D);

Peut etre que aux je dois le remplacer par 0x3c (0x3c = <)

donc selon le tableau ASCII

data_size += (0x3c-0x30); 
// data_size = 0+ 60-0) = 60 ou
// data_size = 0 +(0x3c-0x30) = 0x3c (mais je bug toujours)

en fait je crois que j’ai compris. En gros tant qu’il ne rencontre pas cr, il ne sortira jamais de la boucle et c’est mon cas. Donc c’est pas top!

Comment feriez-vous mieux? comment m’éclairecir?

Ce qui me trouble c'est que les while n'ot pas de {}.
Là je me sens super nul car je ne vois pas comment modifier mes while pour qu'il ait des {} :confused: :slightly_smiling_face:

Ce code me semble bizard mais c'est important que je puisse faire

#ifdef DEBUG_SEND
                        sprint(F("Received:"));
                        Serial.println(data_size);
                    #endif

et

#ifdef DEBUG
                          sprint(F("Received:"));
                          sprintln(buffer);
                        #endif

Y a pas moyen de refaire ce code plus simple?
Il y a tellement de

while(_cell.available()==0);
                    aux = _cell.read();
[code]

deux while possibles
le 1er avec do
exemple
do
{
delay(50); // wait for sensors to stabilize
x = readSensors(); // check the sensors

} while (x < 100); // x<100 est la condition de sortie de “DO”

le 2ème
exemple:
while (1) {}; //attente éternelle

autre exemple:
while (x>2) {x = readSensors();}; //lit le sensor et quitte le while lorsque x=1

pour:
data_size = 0 +(0x3c-0x30) = 0x3c (mais je bug toujours)
data_size = 0 +(0x3c-0x30) = 0xC // si data_size est = à 0 avant

voir également ça
x += y; // equivalent to the expression x = x + y;
x -= y; // equivalent to the expression x = x - y;
x *= y; // equivalent to the expression x = x * y;
x /= y; // equivalent to the expression x = x / y;
x %= y; // equivalent to the expression x = x % y;

tu trouveras les renseignements ici
https://www.arduino.cc/en/Reference/HomePage

Pour ton souci, il est loin d'être improbable que le buffer série soit saturé. 64 bytes ça arrive vite en HTTP

Soit tu vas dans core/hardwareSerial.cpp et tu augmente le buffer, soit tu améliores ta routine de réception

Hello Merci pour vos réponses vous être extra.

J’ai refait le code comme ceci, entre temps, mais je ne suis pas convaincu:

strcpy_P(str_aux1, (char*)pgm_read_word(&(table_AT[28])));  //AT+HTTPREAD
                  snprintf(str_aux1, sizeof(str_aux1), "%s=%d,100", str_aux1,x);
                        
                  #ifdef DEBUG_SEND
                  sprintln(str_aux1);
                  #ifdef AUX1
                   Serial.println(strlen(str_aux1));
                  #endif

                  #endif

                  answer = sendATcommand2(str_aux1,OK_RESPONSE,"+HTTPREAD:100", 30000,true,false);

                  if(answer == 2)
                  {
                    data_size = 0;

                    while(_cell.available() > 0)
                    {

/*
Je en suis pas certain si la maniere de calculer la taille est correcte
*/

                      aux = _cell.read();
                      data_size *= 10;
                      //Serial.println(data_size);
                      data_size += (aux-0x30);
                      //Serial.println(data_size);

                      if(_cell.available() < data_size)
                      {
                        buffer[x] = aux;
                        x++;
                      }
                    }

                    #ifdef DEBUG_SEND
                        sprint(F("Received:"));
                        Serial.println(data_size);
                        buffer[x] = '\0';
                        Serial.println(buffer);

                    #endif


/*

                    while(_cell.available()==0);
                    aux = _cell.read();
                      
                    do{
                        data_size *= 10;
                        data_size += (aux-0x30);
                        while(_cell.available()==0);
                        aux = _cell.read();        
                    }while(aux != 0x0D);
                    //}while(aux != '\r');

                    #ifdef DEBUG_SEND
                        sprint(F("Received:"));
                        Serial.println(data_size);
                    #endif
*/
                    /*
                    if (data_size > 0)
                    {
                        while(_cell.available() < data_size);
                        _cell.read();

                        for (int y = 0; y < data_size; y++)
                        {
                          buffer[x] = _cell.read();
                          x++;
                        }
                        buffer[x] = '\0';
                    }
                    else
                    {
                        #ifdef DEBUG_SEND
                          sprintln(F("End"));    
                        #endif

                        #ifdef DEBUG
                          sprint(F("Received:"));
                          sprintln(buffer);
                        #endif
                    }
                    */
                  }
                  else if (answer == 1)
                  {
                    #ifdef DEBUG_SEND
                      Serial.println(F("No data"));
                    #endif
                    data_size = 0;
                  }
                  else
                  {
                    #ifdef DEBUG
                      Serial.println(F("ERR HTTP"));
                    #endif  
      
                    data_size = 0;
                  }

@B@tto,

Ta remarque est super intéressante et je savais déjà ceci mais j’ai toujours été rétissent à modifier ceci. Je ne peux pas expliqué pourquoi. Mais attention je suis oas en HardwareSerial. Mes deux pins sont connectées au pin 8 et 9 et j’utilise SoftwareSerial. C’est plus tot là que je devrais modifier. J’ai un autre problème quand j’envoi une URL de 140 caracteres avec des parametreet je pense que c’est lié à la limite de 64byte.

La modif est dans ce cas dans softwareSerial.h

Pareil pour l'émission, la c'est plus facile à gérer, il suffit d'utiliser flush() régulièrement après des print()

Après les fonctions type sendATcommand2() sont pas mal mais pas assez robustes. Perso j'en ai réécrit complètement parce qu'elle n'était pas du tout assez fiable. Je dois sortir une lib quand j'aurais bien vérifié que tout fonctionne.

Salut Batto,

Mais -es-ce que je peux donc changer SoftwareSerial.h sans autre?

Par contre pour etre sure bien de te comprendre, car là, tu m’enlève une belle éèine du pied.

On est d’accord que lorsque tu dit "Pareil pour l’énission, c’est dans le cas ou j’envoi des données.
J’aimerais bien rebondir la dessus, car c’est le second problème que je dois résoudre, ce soir ou demain.
J’aimerais rwbondir là dessus car tu parle de flush après un print() et peut etre que ca va résoudre mon problème. Puis demander ton attention là-dessus?

J’envoi des données à un serveur distant en passant des paramètres. Pour cela j’utilise ces commandes

AT+HTTPPARA="URL","AT+HTTPPARA="URL","http://xxxxx.dyndns.org:8080/gprmc/Data?acct=sysadmin&dev=bipme&cid=11631&mnc=03&mcc=228&lac=6001&gprmc=$GPRMC,,V,,,,,,,"
AT+HTTPACTION=0
AT+HTTPREAD=0,100

Attention l’URL peut etre plus longue s’il a des positions valides GPS.

Ca fonctionne bien saud pour le HTTPPARA, si l’urlest longue. Avec www.google.ch, ca marche mais plus avec celle que je viens de mettre. Donc là on parle bien d’émission?

La partie code de l’URL est la suivante

snprintf(str_aux1, sizeof(str_aux1), "%s=\"URL\",\"http://%s:%s/%s%s", str_aux1,_http_srv,_http_port,_http_path,_http_script);

// str_aux => AT+HTTPPARA="URL","http://xxxxx.dyndns.org:8080/gprmc/Data?


    // SEND COMMAND
    _cell.print(str_aux1);
//_cell.flash();
                    
	// Imrpime ceci : acct=sysadmin&dev=bipme&
    _cell.print(F("acct="));
    _cell.print(_acct);
//_cell.flash();
    _cell.print(F("&"));
    _cell.print(F("dev="));
    _cell.print(_dev); // See page 36 of OpenGTS Manuel

    _cell.print(F("&"));
//_cell.flash();

    // Imrpime ceci : cid=11631&mnc=03&mcc=228&lac=6001&gprmc=$GPRMC,,V,,,,,,,
    for(byte i=0; i < strlen(data); i++)
    {
        if(data[i] == '\0')
        {
        	sprintln(F("rmrr0"));
        }
        else
        {
        	_cell.print(data[i]);
            
        }
    }
//_cell.flash();
            
    // Imrpime ceci : " et ajour un cr
    _cell.println("\"\r\n");        

	// La commande est envoyé et j'écoute la réponse
	// Dans ce cas unique, je n'utilise pas la function snedATcommande2
	// Intilize the variables
  	int x = 0;
  	answer = 0;
  	unsigned long previous;
	previous = millis();

  	// Clean the buffer
  	memset(buffer, '\0', BUFFERSIZE);     // BUFFERSIZE is 200

	// Clean _cell (SerialSoftware
    while(_cell.available() > 0) _cell.read();    


    // Start do loop until the while condition is met (timeout and expected answers)
    do{
    	// If _cell is available
      	if(_cell.available() > 0)
      	{
        	if(x < BUFFERSIZE-1) 
        	{

          	char r = _cell.read();
          	buffer[x] = r;

			x++;
          	//char r = (_cell.read());

			// Si rencontre OK sors de la boucle
            if (strstr(buffer, "OK") != NULL)    
            { 
            	// Pour sortir
                answer = 1;
                // ferme le buffer
                buffer[x]='\0';
                
            }


        } // end x<BUFFERSITE
        else
        {
          #ifdef DEBUG
            sprintln(F("*Overflow*"));
          #endif
        }
      }
      else{
        //Serial.println(F("N/A"));
        //Serial.println(x);
      }// End cell available

    } // end do
    while((answer == 0) && ((millis() - previous) < 10000)); 
    // Sors si answer est plus a 0 ou si plus de 10sec


    if (answer == 1)
    {
    	// Well done!
        #ifdef DEBUG_SEND
        	//sprintln(OK_RESPONSE);
            sprintln(F("OK"));
            sprint(F("URL:\t\t\t"));
            sprintln(buffer);
        #endif
    }

Le truc qui me casse LES PIEDS, c’est que le dernier " qui sert à fermer la commande. (Et en plus je viens de voir que mon URL est tronquée)

AT+HTTPPARA="URL","AT+HTTPPARA="URL","http://xxxxx.dyndns.org:8080/gprmc/Data?acct=sysadmin&dev=bipme&cid=11631&mnc=03&mcc=228&lac=6001&gprmc=$GPRMC,,V,,,,,,,"

est envoyé une fois sur 2, et évidemment s’il n’est pas envoyé, ca retorune une erreur.
Des fois il est envoyé et ca retourne une erreur. Par contre avec www.google.ch, ca marche bien.

Donc je suis arrivé à me dire qu’il doit avoir un problème avec le buffer (64 byte) lors de l’émission.
Et je suis super embêter car, OpenGTS demande se format d’URL!!!

Tu as écris que je pauvais utiliser
_cell.flush après un print.

Ca veut dire que d’ajouter après chaque print, à environ tous les 50 caracteres, ca résoudrait mon problème (Voir partie commenté dans le code ci-dessus.

Ou suis à c’oté de la plaque :slight_smile:

C'est bien ce que je voulais dire. Tu peux très bien tronquer ton URL, du moment que le module ne reçoit pas CRLF il ne considère pas la commande terminée. Mais il ne faut pas passer par des fonction type sendATcommand(), il faut toi même écrire au module (rien de méchant). Grosso modo ça doit ressembler à :

SIMCOM.print("\"http://xxxxx.dyndns.org:8080/gprmc/Data?");
SIMCOM.flush();
SIMCOM.print("acct=sysadmin&dev=bipme&cid=11631&mnc");
SIMCOM.flush();
SIMCOM.print("=03&mcc=228&lac=6001");
SIMCOM.flush();
SIMCOM.println(&gprmc=$GPRMC,,V,,,,,,,\"");

J'ai pas mon code entre les mains la mais ce soir si j'oublie pas je te le poste, c'est exactement pour la même commande.

T’es GÉNIAL!
J’ai un contre temps ce soit, je dois faire un autre truc mais je serai au PC plus tard en soit ou demain, mais je suis impatient de régler ceci!!!

Merci!!!

Ouais bin c’est ce que j’avais en fait :

SIM808.print("AT+HTTPPARA=\"URL\",\"http");  
  SIM808.flush();
  SIM808.print("://");
  SIM808.print(server);

// tle reste de ton URL avec régulièrement des flush()

SIM808.println("\"");
  SIM808.flush();

et avant et après évidemment des sendATcommand() avec ce qui va bien pour ouvrir et fermer la connexion

Je te remercie B@tto,
J'ai pas pris le temps de regarder mais je le ferai au plus vite dans la journée

Hello B@tto

J’arrive toujours pas faire fonctionner mon truc :o|
J’ai pourtant mis des flush un peu partout mais je crois savoir ou est le problème
Voici mon code (attention, y a des Serial.print(), c’est pour le debugage)

/*
Sets url 
*/

strcpy_P(str_aux1, (char*)pgm_read_word(&(table_AT[24])));  //AT+HTTPPARA
#ifdef DEBUG_SEND
	sprint(str_aux1); // Affiche : AT+HTTPPARA
    sprint(F("\t\t"));
#endif


// The correct URL
// http://xxxx.dyndns.org:8080/gprmc/Data?acct=sysadmin&dev=bipme&cid=2d6f&mnc=03&mcc=228&lac=1771&gprmc=$GPRMC,174520.00,A,4613.16427,N,00608.47563,E,0.207,,030915,,,

snprintf(str_aux1, sizeof(str_aux1), "%s=\"URL\",\"http://%s:%s/%s%s", str_aux1,_http_srv,_http_port,_http_path,_http_script);

// SEND COMMAND
_cell.print(str_aux1);	// Send : http://xxxx.dyndns.org:8080/gprmc/Data?
_cell.flush();

_cell.print(F("acct="));
_cell.print(_acct);

_cell.print(F("&dev="));
_cell.print(_dev); // See page 36 of OpenGTS Manuel

_cell.print(F("&"));
// send : acct=sysadmin&dev=bipme&
_cell.flush();

// Les 3 serial.print, c'est du degug. C'est juste pour afficher afin de voir si fix est correct
Serial.println(F(""));
Serial.println(fix);			// Affiche : cid=2d6f&mnc=03&mcc=228&lac=1771&gprmc=$GPRMC,174520.00,A,4613.16427,N,00608.47563,E,0.207,,030915,,,
Serial.println(strlen(fix));	// Affiche : 95

// JE PENSE QUE LE PROBLEME EST LA CAR IL Y A 95 CARACETERE ALORS QUE LA LIMITE EST 64. SI NON LE FORMAT DE FIX EST JUSTE

// SEND FIX
byte i;
for(i=0; i < strlen(fix); i++)
{
	// NE PAS ENVOYER \0 . CECI EST SURTOUT SI FIX A un \0 A LA FIN DE LA CHAINE
    if(fix[i] != '\0')
    {
    	_cell.print(fix[i]);
    }
    
    // DONC VU QUE FIX A 95 CARACTERE, JE FAIS UN FLUSH TOUS LES 30. JE POURRAIS LE FAIRE TOUS LES 60, MAIS CA RIEN CHANGER 
	if(i == 30 || i == 60 || i == 90 || i == 120)
    {
    	_cell.flush();        
    }

}
_cell.flush();
            
// FERME LE LIEN. J?AI AUSSI ESSAYER AVEC UN _cell.print("\"\r\n")
_cell.println("\"");
            
// SI DESSOUS EST POUR LIRE LA REPONSE, MAIS JE PENSE QUE LE PROBLEME EST PLUS HAUT
// Je n'ai pas commenté le code.

delay(100);

            /*
             READ THE RESPONSE
            */
            // Intilize the variables
            int x = 0;
            answer = 0;
            unsigned long previous;
            previous = millis();

            // Clean the buffer
            memset(buffer, '\0', BUFFERSIZE);     // BUFFERSIZE is 200

            // Clean _cell
            while(_cell.available() > 0) _cell.read();    

            // Start do loop until the while condition is met (timeout and expected answers)
            do{
            // If _cell is available
            if(_cell.available() > 0)
            {
              if(x < BUFFERSIZE-1) 
              {
                char r = _cell.read();
                buffer[x] = r;
                x++;


                //char r = (_cell.read());

                if (strstr(buffer, OK_RESPONSE) != NULL)    
                { 
                  answer = 1;
                  buffer[x]='\0';
                }

              } // end x<BUFFERSITE
              else
              {
                #ifdef DEBUG
                  sprintln(F("*OF! 3*"));
                #endif
              }
            }
            else
            {
              //Serial.println(F("N/A"));
              //Serial.println(x);
            }// End cell available

          } // end do
          while((answer == 0) && ((millis() - previous) < 10000)); 


          // if(sendATcommand2("\r","OK",NULL,10000,false,false))
          if (answer == 1)
          {
            #ifdef DEBUG_SEND
              //sprintln(OK_RESPONSE);
              sprintln(F("OK"));
              sprint(F("URL:\t\t\t"));
              sprintln(buffer);
            #endif

Es-ce que ca cause un probleme que j’ai _cell. au lieu de cell. (le underscore)?
J’espère que tu va pouvoir m’aider. Merci

non le underscore n'a aucun effet.

Après il y a tellement de paramètres et d'index qu'il faut remettre les choses à plat : tu utilises plein de sprintf() de F() ... quand on rencontre un problème qu'on arrivent pas résoudre comme ça, il faut simplifier puis réajouter les fonctions au fur et à mesure.

Donc la, vire les F(), les sprintf() etc ... Il faut simplifier. Il y a des index et des limite de capacité partout, y'en a une qui doit être dépassée. Comme ça j'ai tellement de pistes qui me viennent que je peux pas t'aider facilement : est-ce que c'est une limite de F() ? et oui l'accès à la flash est très lent comparé à de la RAM, est-ce que c'est pas ça qui crée un problème ? Exemple : tu fait une boucle for avec un byte, ta chaine fait 95 caractères, tu joue avec le feu ... Y'a un débug au milieu : est-ce que c'est pas lui qui bug ? Est-ce qu'il n'entre passe conflit avec la liaison série du simcom ? Et j'en passe d'autre ...

Est-ce tu as essayé d'ajuster les deux buffers (Série debug + série simcom) ?

Merci B@tto pour ta réponse, je bais éliminer un maximum de (F

Par contre, je en comprend pas ce que tu veux dire

tu fait une boucle for avec un byte, ta chaine fait 95 caractères, tu joue avec le feu

Parles-tu bien de ceci:

 // SEND FIX
            byte i;
            for(i=0; i < strlen(fix); i++)
            {
              if(fix[i] != '\0')
              {
                // Envoi un caracters à la fois de cette chaine:
                // cid=2d6f&mnc=03&mcc=228&lac=1771&gprmc=$GPRMC,174520.00,A,4613.16427,N,00608.47563,E,0.207,,030915,,,
                _cell.print(fix[i]);
              }
              
 
              if(i == 30 || i == 60 || i == 90 || i == 120)
              {
                #ifdef ALTSOFT
                #else
                  _cell.flush();
                #endif
              }
            }

Bin ouais, un byte c'est 128 max, si ta chaine fait simplement 34 caractères de plus tout plante. Déclare le en int et t'auras jamais ce problème.

Ne pas perdre de vue que Serial.write() et Serial.print() sont bloquantes.

Si le nombre de caractères à envoyer dépasse la capacité du buffer la méhode write() attend qu'il y ait de la place dans celui-ci pour continuer. Le flush() n'apporte rien, bien au contraire. Flush() bloque l'exécution en attendant que le buffer soit complètement vide.
Prenons un exemple, le buffer est plein et tu veux envoyer 2 caractères supplémentaires:

  • la méthode write() place un caractère dans le buffer dès qu'une place se libère, donc elle attendra l'émission de 2 caractères et retournera dans le programme.
  • la méthode flush() attend que le buffer soit vide avant de retourner donc elle va bloquer l'exécution pendant l'émission de 64 caractères.

L'usage de flush() est limité à des cas particuliers comme la gestion d'une liaison RS485 où il faut s'assurer que tous les caractères sont émis avant de basculer le sens du bus ou pour la gestion de certains protocoles.

Il faut aussi être conscient que l'utilisation de Serial.print() pour le debug peut être très impactant. Si tu envoies trop de messages (ou des messages trop longs) alors tu bloques ton programme et ta fonction de debug pénalise le déroulement de ton programme en cours de test.