Comment bien comprendre cette fonction qui traite les réponses AT+xxx

Bonjours à tous,

J'ai passé beaucoup de temps à travailler sur un fonction qui

  • Envoie une commande AT+
  • Qui lit la répomse
  • Qui filtre la réponse
  • et traite la réponse

Ca fait beaucoup et il me semble que finalement elle bug quelques fois.

Dans le doute, je souhaite retraivailler ce sujet en m'inspirant d'une autre librairie qui envoie simplement la commande comme ceci, par exemple

cell.println("AT+CENG");

et juste après, il y a une autre fonction, celle que je ne maitrise pas, qui va lire la réponse, attendre un paramettre, pour après, pouvoir traiter les données qui m'intérsse.

Le principe me plait et me semble plus simple et plus légé.

Ceci dit avec mes compétences d'autodidact, j'ai du mal à maitriser cette fonction et il me semble important que je la maitrise bien

Voici la fonction la fonction en question

cell.println("AT+CENG");
WaitResp(100, 500,"+CENG:");
// Traitement de la suite de la réponse, après le +CENG:

et les fonctions qui y sont liées.

La première chose que j'aimerais bien comprendre, c'est les deux premiers paramètre de cette fonction, soit

uint16_t start_comm_tmout
et
uint16_t max_interchar_tmout

Je ne comprends pas exactement ce que fait le premier et le second.
Es-ce que le prmier est egal à 100, es-ce qu'il va considéré les caractère reçu depuis le 101ème?
Le deuxième, es-ce que le timeout n'est pas en seconde, mais en nombre de caractere reçu?
Je suis un peu dans le flou

L'autre grand questionnement, c'est la fonction RxInit(), j'ai aussi du mal "à la traduire"

byte WI968C::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, 
                   char const *expected_resp_string)
{
  byte status;
  byte ret_val;

  RxInit(start_comm_tmout, max_interchar_tmout); 
  // wait until response is not finished
  do {
    status = IsRxFinished(expected_resp_string);
  } while (status == RX_NOT_FINISHED);

  if (status == RX_FINISHED) {
    // something was received but what was received?
    // ---------------------------------------------
  
    if(IsStringReceived(expected_resp_string)) {
      // expected string was received
      // ----------------------------
      ret_val = RX_FINISHED_STR_RECV;      
    }
    else {
  ret_val = RX_FINISHED_STR_NOT_RECV;
  }
  }
  else {
    // nothing was received
    // --------------------
    ret_val = RX_TMOUT_ERR;
  }
  return (ret_val);
}


byte WI968C::IsRxFinished(char const *expected_resp_string)
{
  byte num_of_bytes;
  byte ret_val = RX_NOT_FINISHED;  // default not finished

  // Rx state machine
  // ----------------

  if (rx_state == RX_NOT_STARTED) {
    // Reception is not started yet - check tmout
    if (!_cell.available()) {
      // still no character received => check timeout
  /*  
  #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: reception timeout", 0);      
      Serial.print((unsigned long)(millis() - prev_time));  
      DebugPrint("\r\nDEBUG: start_reception_tmout\r\n", 0);      
      Serial.print(start_reception_tmout);  
      
    
  #endif
  */
      if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) {
        // timeout elapsed => GSM module didn't start with response
        // so communication is takes as finished
    /*
      #ifdef DEBUG_GSMRX    
        DebugPrint("\r\nDEBUG: RECEPTION TIMEOUT", 0);  
      #endif
    */
        comm_buf[comm_buf_len] = 0x00;
        ret_val = RX_TMOUT_ERR;
      }
    }
    else {
      // at least one character received => so init inter-character 
      // counting process again and go to the next state
      prev_time = millis(); // init tmout for inter-character space
      rx_state = RX_ALREADY_STARTED;
    }
  }

  if (rx_state == RX_ALREADY_STARTED) {
    // Reception already started
    // check new received bytes
    // only in case we have place in the buffer
    num_of_bytes = _cell.available();
    // if there are some received bytes postpone the timeout
    if (num_of_bytes) prev_time = millis();
      
    // read all received bytes      
    while (num_of_bytes) {
      num_of_bytes--;
      if (comm_buf_len < COMM_BUF_LEN) {
        // we have still place in the GSM internal comm. buffer =>
        // move available bytes from circular buffer 
        // to the rx buffer
        *p_comm_buf = _cell.read();

        p_comm_buf++;
        comm_buf_len++;
        comm_buf[comm_buf_len] = 0x00;  // and finish currently received characters
                                        // so after each character we have
                                        // valid string finished by the 0x00
      if (IsStringReceived(expected_resp_string) == 1){
        //Serial.println("not ready");
        return (RX_FINISHED);
      }
    
      }
      else {
        // comm buffer is full, other incoming characters
        // will be discarded 
        // but despite of we have no place for other characters 
        // we still must to wait until  
        // inter-character tmout is reached
        
        // so just readout character from circular RS232 buffer 
        // to find out when communication id finished(no more characters
        // are received in inter-char timeout)
        _cell.read();

    
    
      }
    }

    // finally check the inter-character timeout 
  /*
  #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: intercharacter", 0);     
<     Serial.print((unsigned long)(millis() - prev_time));  
      DebugPrint("\r\nDEBUG: interchar_tmout\r\n", 0);      
      Serial.print(interchar_tmout);  
      
    
  #endif
  */
    if ((unsigned long)(millis() - prev_time) >= interchar_tmout) {
      // timeout between received character was reached
      // reception is finished
      // ---------------------------------------------
    
    /*
      #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: OVER INTER TIMEOUT", 0);         
    #endif
    */
      comm_buf[comm_buf_len] = 0x00;  // for sure finish string again
                                      // but it is not necessary
      ret_val = RX_FINISHED;
    }
  }
    


  return (ret_val);
}

/**********************************************************
Method checks received bytes
compare_string - pointer to the string which should be find
return: 0 - string was NOT received
        1 - string was received
**********************************************************/
byte WI968C::IsStringReceived(char const *compare_string)
{
  char *ch;
  byte ret_val = 0;

  if(comm_buf_len) {
  /*
    #ifdef DEBUG_GSMRX
      DebugPrint("DEBUG: Compare the string: \r\n", 0);
      for (int i=0; i<comm_buf_len; i++){
        Serial.print(byte(comm_buf[i]));  
      }
      
      DebugPrint("\r\nDEBUG: with the string: \r\n", 0);
      Serial.print(compare_string); 
      DebugPrint("\r\n", 0);
    #endif
  */
  #ifdef DEBUG
    Serial.println("ATT: ");
    Serial.print(compare_string);
    Serial.print("RIC: ");
    Serial.println((char *)comm_buf);
  #endif
    ch = strstr((char *)comm_buf, compare_string);
    if (ch != NULL) {
      ret_val = 1;
    /*#ifdef DEBUG_PRINT
    DebugPrint("\r\nDEBUG: expected string was received\r\n", 0);
    #endif
    */
    }
  else
  {
    /*#ifdef DEBUG_PRINT
    DebugPrint("\r\nDEBUG: expected string was NOT received\r\n", 0);
    #endif
    */
  }
  }

  return (ret_val);
}


void WI968C::RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout)
{
  rx_state = RX_NOT_STARTED;
  start_reception_tmout = start_comm_tmout;
  interchar_tmout = max_interchar_tmout;
  prev_time = millis();
  comm_buf[0] = 0x00; // end of string
  p_comm_buf = &comm_buf[0];
  comm_buf_len = 0;
  _cell.flush(); // erase rx circular buffer
}

Si vous pouviez me consacrer un peu de temps à éclairer ma lanterne, vous me donner un gros coup de pousse pour reprendre mon truc au propre.

Milles mercis
(J'espère ne pas avoir manquer de donner des infos) :slight_smile:

En je pense avoir compris mais sans certitude.

uint16_t start_comm_tmout

Ceci permets de définir le temps qu'on va rester à l'écoute de la réponse

uint16_t max_interchar_tmout

Ceci va définir le temps entre deux caractère recu. Si le temps est trop long, on sort.

La question, c'est comment on fait poue définir ce temps.
J'ai vu que des fois c'est à 50 ou 100. A partit de quel temps on estime qu'il est long?

Je peine toujours sur cette fonction et ca serait super si vous pouviez m'aider

Je n'arrive pas a comprendre ce que fait exactement le deuxième paramètre max_interchar_tmout et j'ai vraimenr besoin de le comprendre.

Si je ne me trompe pas, le premier paramètre va définir le temps maximal pour avoir en retour la réponse, soit expected_resp_string

Mais le deuxième parametre, je n'arrive vraiment pas à le cerner!!

byte WI968C::WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout,
                   char const *expected_resp_string)
{
  byte status;
  byte ret_val;

  RxInit(start_comm_tmout, max_interchar_tmout);
  // wait until response is not finished
  do {
    status = IsRxFinished(expected_resp_string);
  } while (status == RX_NOT_FINISHED);

  if (status == RX_FINISHED) {
    // something was received but what was received?
    // ---------------------------------------------
  
    if(IsStringReceived(expected_resp_string)) {
      // expected string was received
      // ----------------------------
      ret_val = RX_FINISHED_STR_RECV;      
    }
    else {
  ret_val = RX_FINISHED_STR_NOT_RECV;
  }
  }
  else {
    // nothing was received
    // --------------------
    ret_val = RX_TMOUT_ERR;
  }
  return (ret_val);
}


byte WI968C::IsRxFinished(char const *expected_resp_string)
{
  byte num_of_bytes;
  byte ret_val = RX_NOT_FINISHED;  // default not finished

  // Rx state machine
  // ----------------

  if (rx_state == RX_NOT_STARTED) {
    // Reception is not started yet - check tmout
    if (!_cell.available()) {
      // still no character received => check timeout
  /*  
  #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: reception timeout", 0);      
      Serial.print((unsigned long)(millis() - prev_time));  
      DebugPrint("\r\nDEBUG: start_reception_tmout\r\n", 0);      
      Serial.print(start_reception_tmout);  
      
    
  #endif
  */
      if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) {
        // timeout elapsed => GSM module didn't start with response
        // so communication is takes as finished
    /*
      #ifdef DEBUG_GSMRX    
        DebugPrint("\r\nDEBUG: RECEPTION TIMEOUT", 0);  
      #endif
    */
        comm_buf[comm_buf_len] = 0x00;
        ret_val = RX_TMOUT_ERR;
      }
    }
    else {
      // at least one character received => so init inter-character
      // counting process again and go to the next state
      prev_time = millis(); // init tmout for inter-character space
      rx_state = RX_ALREADY_STARTED;
    }
  }

  if (rx_state == RX_ALREADY_STARTED) {
    // Reception already started
    // check new received bytes
    // only in case we have place in the buffer
    num_of_bytes = _cell.available();
    // if there are some received bytes postpone the timeout
    if (num_of_bytes) prev_time = millis();
      
    // read all received bytes      
    while (num_of_bytes) {
      num_of_bytes--;
      if (comm_buf_len < COMM_BUF_LEN) {
        // we have still place in the GSM internal comm. buffer =>
        // move available bytes from circular buffer
        // to the rx buffer
        *p_comm_buf = _cell.read();

        p_comm_buf++;
        comm_buf_len++;
        comm_buf[comm_buf_len] = 0x00;  // and finish currently received characters
                                        // so after each character we have
                                        // valid string finished by the 0x00
      if (IsStringReceived(expected_resp_string) == 1){
        //Serial.println("not ready");
        return (RX_FINISHED);
      }
    
      }
      else {
        // comm buffer is full, other incoming characters
        // will be discarded
        // but despite of we have no place for other characters
        // we still must to wait until  
        // inter-character tmout is reached
        
        // so just readout character from circular RS232 buffer
        // to find out when communication id finished(no more characters
        // are received in inter-char timeout)
        _cell.read();

    
    
      }
    }

    // finally check the inter-character timeout
  /*
  #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: intercharacter", 0);    
     Serial.print((unsigned long)(millis() - prev_time));  
      DebugPrint("\r\nDEBUG: interchar_tmout\r\n", 0);      
      Serial.print(interchar_tmout);  
      
    
  #endif
  */
    if ((unsigned long)(millis() - prev_time) >= interchar_tmout) {
      // timeout between received character was reached
      // reception is finished
      // ---------------------------------------------
    
    /*
      #ifdef DEBUG_GSMRX
    
      DebugPrint("\r\nDEBUG: OVER INTER TIMEOUT", 0);        
    #endif
    */
      comm_buf[comm_buf_len] = 0x00;  // for sure finish string again
                                      // but it is not necessary
      ret_val = RX_FINISHED;
    }
  }
    


  return (ret_val);
}

/**********************************************************
Method checks received bytes
compare_string - pointer to the string which should be find
return: 0 - string was NOT received
        1 - string was received
**********************************************************/
byte WI968C::IsStringReceived(char const *compare_string)
{
  char *ch;
  byte ret_val = 0;

  if(comm_buf_len) {
  /*
    #ifdef DEBUG_GSMRX
      DebugPrint("DEBUG: Compare the string: \r\n", 0);
      for (int i=0; i<comm_buf_len; i++){
        Serial.print(byte(comm_buf[i]));  
      }
      
      DebugPrint("\r\nDEBUG: with the string: \r\n", 0);
      Serial.print(compare_string);
      DebugPrint("\r\n", 0);
    #endif
  */
  #ifdef DEBUG
    Serial.println("ATT: ");
    Serial.print(compare_string);
    Serial.print("RIC: ");
    Serial.println((char *)comm_buf);
  #endif
    ch = strstr((char *)comm_buf, compare_string);
    if (ch != NULL) {
      ret_val = 1;
    /*#ifdef DEBUG_PRINT
    DebugPrint("\r\nDEBUG: expected string was received\r\n", 0);
    #endif
    */
    }
  else
  {
    /*#ifdef DEBUG_PRINT
    DebugPrint("\r\nDEBUG: expected string was NOT received\r\n", 0);
    #endif
    */
  }
  }

  return (ret_val);
}


void WI968C::RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout)
{
  rx_state = RX_NOT_STARTED;
  start_reception_tmout = start_comm_tmout;
  interchar_tmout = max_interchar_tmout;
  prev_time = millis();
  comm_buf[0] = 0x00; // end of string
  p_comm_buf = &comm_buf[0];
  comm_buf_len = 0;
  _cell.flush(); // erase rx circular buffer
}

En fait, je crois que j'ai compris, mais je ne suis pas sûre, du moins je ne comprens pas le sens (il y a en a un j'en suis sûre :slight_smile: )

En fait, le premier paramère (start_comm_tmout) : est le temps qu'on lui donne pour avoir une réponse.
Le deuxième paramère (max_interchar_tmout) : est le temps qu'on lui donne pour lire la réponse attendue, soit expected_resp_string

Si c'est bien ca, qu'elle est le but de donner un temps start_comm_tmout pour recevoir le premier caractère :o , alors qu'on peut commence à lire la réponse tout de suite, non?