Comment analyser mon buffer

Bonjour bonjour!!

J'arrive à récolter les localisation du GPS. Je stok ceci dans un buufer

AT+CGPSINF=2

2,182822,4613.161213,N,608.474865,E,1,9,1.179917,433.212921,M,48.200256,M,,0000 OK

La dedans, il y a que ceci qui m'intéresse

2,182822,4613.161213,N,608.474865,E,1,9,1.179917,433.212921,M,48.200256,M,,0000

J'ai pas beucoup d'expérience avec C++. Avec php il y a qui me permet de remplacer un string que je ne veux plus par un espace. J'ai aussi vu qu'il y readBytesUntil, mais apparement c'est une class de Serial.

Bref, ce que j'aimerais surtout c'est d'avoir au final un truc du genre:

val[0]=2 val[1]=182822 val[2]=4613.161213 val[3]=N val[4]=608.474865 val[5]=E val[6]=1 val[7]=9 val[8]=1.179917 val[9]=433.212921 val[10]=M val[11]=48.200256 val[12]=M val[13]= val[14]=0000

Pourriez-vous me mettre sur la piste?

Milles mercis

Je pensais à un truc du genre (meme si ne supprime pas encore le OK et la commande et le CR)

void gps_explode(void)          //get ','
{  
  char fix;
 
  int z = 0;
  int y = 0;
  
  for(y=0; y < strlen(buffer); y++)
  {
    if(buffer[y]==',')
    {
      z++;
    }
    else
    {
      fix[z][y]=buffer[y];
    }
    
    if(y==num)//if the command is right, run return
      y=strlen(buffer)+1;
  }
}

Mais ca ne semble pas fonctionner en C++.
Il a pas l’air d’aimer :stuck_out_tongue:

fix[z][y]=buffer[y];

Hello,

Jette un oeil sur strtok(), qui te permettra de récupérer d'abord la nième ligne (en utilisant '\n' comme séparateur), puis un autre appel à strtok() pour lire les champs séparés par une virgule.

Ok super, merci, je vais voir ca

MERCI pepe pour ce code intéressant.

Je l’essaye sur mon code. Mais je dois pouvoir utiliser val. C’est une valeur que je vais envoyer dans une base de donnée.
Donc il faut que my fonction gps_read()

static char* gps_read (void) {
  
  if(strstr(read_AT_string("AT+CGPSINF=2",3000),"OK") != NULL)
  {
    
    Serial.println(F("------- Show buffer------"));
    Serial.println(buffer);
    Serial.println(F("-------------------------\n"));
    
    litParametres(buffer,val);
    
    return val
  }
  else
  {
     return "Error : no fix";
  }
  
}

void litParametres(char *buffer, char **val)
{
  char *p = buffer;
  int i = 0;
  val[i++] = p;
  while (*p) {
    if (*p==',') {
      *p++ = '\0';
      if (i<NBVALS)
         val[i++] = p;
    } else
      p++;
  }
  while(i<NBVALS)
    val[i++] = p;
}

Ce que je peine à comprendre, c’est comment faire pour que gps_read() retourn la valeur val qui se trouve dans litParametres…

Milles mercis

Ok, je te remercie. Je vais regardé tout ca demain. Milles mercis, ca semble super bien!!!!

Hello,

J’ai pas trop compris la deuxième partie de ton code. Peut-être l’heure :slight_smile:

// read data to gps_buf[] from GPS
static char* gps_read (void) {
  
  if(strstr(read_AT_string("AT+CGPSINF=2",3000),"OK") != NULL)
  {
    if(debug_buffer)
    {
      Serial.println(F("------- Show buffer------"));
      Serial.println(buffer);
      Serial.println(F("-------------------------\n"));
    }
    GPGGAParams(buffer,fix); // P
    
    // Display $GPGGA fix
    if(debug)
    {
      for(int i =0; i< NBVALS; i++)
      {
        Serial.print(i); Serial.print(F(":")); Serial.println(fix[i]);
      }
    }

  }
  
}

void GPGGAParams(char *buffer, char **fix)
{
  char *p = buffer;
  int i = 0;
  fix[i++] = p;
  
  while (*p) {
    if (*p==',') {
      *p++ = '\0';
      if (i<NBVALS)
         fix[i++] = p;
    } else
      p++;
  }
  while(i<NBVALS)
    fix[i++] = p;
}

Ce code me donne un bon résultat.

0:AT+CGPSINF=2

2
1:224725
2:4613.168333
3:N
4:608.476599
5:E
6:1
7:9
8:1.174264
9:413.947083
10:M
11:48.200256
12:M
13:
14:0000
OK

Le seul truc qui m’embête, c’est qu’à la position 0, il ne devrait pas avoir
AT+CGPSINF=2
et les deux reour à la ligne. Il faurdait juste le dernier 2.

et à la position 14, il faudait juste avoir

14:0000,

sans le retur à la ligne et le OK

Salut pepe,

Je te remercie encore pour ton aide, Je peine....

J'ai essayé ton deuxieme code qui m'affiche ceci

0:AT+CGPSINF=2 1: 2:2,092525,4613.165174,N,608.471244,E,1,6,1.373523,429.716888,M,48.200226,M,,0000 3:OK 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:

NB: Je dois tenir en compte qu'il peut avoir de retour à la ligne, tout comme il peut ne pas en avoir. Donc la chaine de caracter qui m'intàresse, mais elle peut etre en position 1 ou 3 ou 4....

Dans ce cas, on ne pourrait pas détecter la ligne qui contient 15 parametre séparer par des virgule, placer cette ligne sur la position 14, lire la ligne 14, mettre le premier paramettre sur 0: le deuxièeme sur 1: le troisième sur 2: etc pour trouver 0000 sur 14:

Je te remercie pour ton aide car je suis larger, là!! :)

PS: Je ne peux pas perdre la ligne vie, soit le parametre vide

PS, d'un côté, si je peux aussi avoir comme résultat et remplacer

0:AT+CGPSINF=2
1:
2:2,093749,4613.165174,N,608.471244,E,1,7,1.189542,429.716888,M,48.200226,M,,0000
3:OK
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:

par ca

0:2,093749,4613.165174,N,608.471244,E,1,7,1.189542,429.716888,M,48.200226,M,,0000
1:OK
2:QUIMPORTE
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:

Ca me va aussi. Ainsi je sais que la valeur recherché se trouvera toujours en premiere position 0:, qu'importe ce qu'il y a dans les suivantes. De plus, de mémoire, la fonction qui envoi la valeur sur le serveur, attent un String qui sépare justement les paramètres par des virgules. Excatement comme ceci:

2,093749,4613.165174,N,608.471244,E,1,7,1.189542,429.716888,M,48.200226,M,,0000

Donc pour avoir ma valeur à envoyer, il me suffira juste de fix[0], qu'importe de ce qu'il y a apèrs. C'est le serveur qui spliter les donnée en fonction des ','

Ca me semble plus simple. Simplement, maintenant, comme faire pour détecter la ligne qui à 15 paramètres, séparé par des virgule et le copier en position 0: ? :cold_sweat:

En gros, vous avez réécrit strtok()...

Pépé_ je te remercie mille fois pour tout ce que tu fais. Mais je m’excuse, je n’arrive toujours pas reprendre ton code :cold_sweat: :cold_sweat: :cold_sweat:

#define NBVALS 15
char ligne[NBVALS];
//J'ai dans mon buffer mon cheni dont il faut extraire, la ligne  15 paramettre
GPGGAParams(buffer,ligne); // Le 4 me semble étrange

void GPGGAParams(char *buffer, char *ligne)
{
  char *p = buffer;
  char *ligne; // Ca bug ici

  while (*p) {
    if (*p==',' || *p>='0' && *p<='9') { // début des paramètres
      ligne = p++;
      while (*p) {
        if (*p=='\n' || *p=='\r') { // fin de ligne
          *p = '\0';
          break;
        }
        p++;
      }
      return ligne;
    }
    do { 
      if (*p=='\n' || *p=='\r') { // LF ou CR
        p++;
        break;
      }
      p++;
    } while (*p);
  }
  return NULL;
}

Ce que je ne comprends pas c’est
‘ligne’
J’ai une erreur, d’ailleur dans mon code a ce niveau char *ligne; // Ca bug ici

Et ou est stoqué le résultat, dans lignes?
Je vois

return ligne;

mais pourtant la fonction est void

Ha oui, encore un petit détail, mais c’est pas grave…
Le début de ma chaine commencera toujours pas ‘2,’. Voir peut être un autre chiffre, mais avec un digit et une virgule :o)

Oufs… J’y arriverai :slight_smile:

Salut pepe_ Je te remercie mille fois pour ton engagement. Je ne suis plus a la maison mais je vais essayer ça plus tard. Milles mercis!

Bonjour à tous,

En lisant la 1ère fois le titre du sujet je me suis dit : “avec le plus grand soin”,
et même en lisant le texte du 1er post je ne voyais pas le rapport.

Dans mon esprit, nettoyer voulait sans doute dire purger le buffer ?
et non analyser le contenu d’une chaîne de caractères.

Conclusion :
Pour les débutants et nuls, (comme moi) ne sachant pas lire entre les lignes, je demande un tout petit
peu plus d’attention dans vos rédactions.
Ainsi les sujets sont partagés et profitables à tous, sans avoir en plus, à “décoder” le texte.

Il est quand même bien ce forum !
Merci et Bien à vous

Géryko

Salut pepe
Je me permets de revenir sur ce post car tu m’avais porposé une fonction qui m’aide beaucoup.

void SIM908::bufferByLine(char *buffers, char **buffer_by_line)
{
  //Serial.println(F("--"));
  //Serial.println(buffers);
  //Serial.println(F("--"));

  char *p = buffers;
  byte i = 0;

  buffer_by_line[i++] = p;

  while (*p) {
    if (*p=='\n') {
      *p++ = '\0';
      if (*p=='\r')
        *p++ = '\0';
      if (i<NBLINES)
      {
         buffer_by_line[i++] = p;
      }
    } else
    if (*p=='\r') {
      *p++ = '\0';
      if (*p=='\n')
        *p++ = '\0';
      if (i<NBLINES)
      {
         buffer_by_line[i++] = p;
       }
    } else
      p++;
  }
  while(i<NBLINES)
    buffer_by_line[i++] = p;
}

J’ai du mal à la comprendre et je dois la modifier pour qu’elle fasse la meme chose mais sans les ligne vide:
Avant

0:
1:AT+CMGR=1,1
2:
3:+CMGR: "REC UNREAD","+417611111111","","14/10/17,19:46:33+08"
4:dir,r
5:
6:OK
7:
8:
9:
10:
11:

Après

0:AT+CMGR=1,1
1:+CMGR: "REC UNREAD","+41763435206","","14/10/17,19:46:33+08"
2:dir,r
3:OK

Ceci parce que des fois, il commance à la position 1. alors qu’il ne doit pas.

Je n’arrive pas a trouver la solution. On m’a proposé d’ajouté

if(p!=NULL || *p!='\n' || *p!='\r'  || strcmp(p, "\r\n")!=0)

après le while, mais ca ne marche pas
(attention j’ai rendu ta fonction “plus lisible” pour moi, en fernant le if. J’espère avoir bien fait)

void SIM908::bufferByLine(char *buffers, char **buffer_by_line)
{
  //Serial.println(buffers);

  char *p = buffers;
  byte i = 0;

  buffer_by_line[i++] = p;

  while (*p) {
    if (*p=='\n') {
      *p++ = '\0';

      if (*p=='\r'){
        *p++ = '\0';
      }
      if (i<NBLINES){
        //if(*p!='\0'){
          buffer_by_line[i++] = p;
        //}
      }
    } 
    else if (*p=='\r') 
    {
      *p++ = '\0';
      if (*p=='\n'){
        *p++ = '\0';
      }

      if (i<NBLINES){
       // if(*p!='\0'){
         buffer_by_line[i++] = p;
       // }
      }
    } 
    else
    {
      p++;
    }
  }
  while(i<NBLINES)
  {
    if(p!=NULL || *p!='\n' || *p!='\r'  || strcmp(p, "\r\n")!=0)
    {
      buffer_by_line[i++] = p;
    }
  }
}

Vu que tu m’avais proposé cette fonction pourrais-tu me dire comment la corrigée pour que dans buffer_by_line, il n’y ait pas d’index vide?

Milles mercis

J'ai du mal à la comprendre

Je pense que c'est par là qu'il faudrait commencer. Cela te permettrait de faire progresser tes connaissances et de résoudre ton problème.

La fonction est relativement simple. Quelques pistes:

  • p pointe dans une chaîne
  • *p donne accès au caractère pointé par p
  • p++ avance le pointeur d'un caractère.

Salut fdufnew. Oui tu as raison. Je prends un cours C++ de 5 jous, le 1 décembre qui traite justement les pointeurs. C'est ma grosse lacune, je le reconnais :drooling_face: Mais voilà, je veux comme meme avancer d'ici là :cold_sweat: