SIM800L V2. Extraer un numero de telef del cuerpo del sms para utilizarlo

Hola buenas tardes....
Podrían darme una mano que no logro ver el error.

  • Tengo un modulo sim800l V2 y un arduino uno.Antes que nada aclaro que no tengo inconveniente alguno para poder enviar y recibir sms. Comento esto por el tema conexiones.

  • Le envío un sms al SIM800 y dentro del cuerpo del mensaje hay un numero telefónico que quiero utilizar.

  • Ese numero lo guardo en un String (celulares).

  • Luego a dicho string le aplico el comando tocharArray (Aclaro que este char està definido
    char cprimercelu [20]; y lo guardo en una posición de la EEPROM

  • El contenido de (cprimercelu) lo paso a un nuevo string (celular1) y utilizo ese numero como destinatario para enviarle un mensaje.

Todo esto lo voy viendo paso a paso por el puerto serie. El problema es que ese numero que guardè finalmente en el nuevo string al momento de "pegarlo" dentro del comando AT+CMGS no logro que el modulo pueda interpretar ese numero y por ende no manda el sms, aún leyendo por puerto serie que el numero està correctamente guardado.

 // EN ESTE PROGRAMA RECIBO MENDAJES DE LA SIM Y LEO LA PALABRA CEL1,LUEGO GUARDO SOLAMENTE EL NUMERO DE CELULAR 

#include <Sim800l.h>
#include <SoftwareSerial.h>
SoftwareSerial sim800l(6,7); // RT  TX
#include <EEPROM.h>

String celulares;
char cprimercelu[25];
String celular1;



void setup() {
  Serial.begin(9600);
  sim800l.begin(9600);
 sim800l.print("AT\r");
  delay(1000);
 sim800l.print("AT+CMGF=1\r"); // comando para enviar y recibir mensaje
  delay(1000);
 sim800l.print("AT+CNMI=2,2,0,0,0\r");
  delay(1000);
sim800l.print(char(26));
  pinMode(3, INPUT);
  delay(200);
}

void PrimerCelular (){

       delay(1000);
       celulares.remove(1, 50);         //Elimino la primera linea
       Serial.println("Borre linea");
       delay(500);
       celulares.remove(1, 6);  // elimino la palabra (cel1 del cuerpo del mensaje
       Serial.println("Borre 6 caracteres");
       delay(500);
       celulares.toCharArray(cprimercelu,celulares.length());    // paso el contenido a char                     
       delay(500);
       Serial.println(cprimercelu);  // corroboro que se guadó el numero del cuerpo del mensaje
       EEPROM.put(0,cprimercelu);    // guardo el contenido en eeprom
       Serial.println(EEPROM.get(0, cprimercelu)); // verifico lo que se guardo en eeprom
       delay(500);
       celular1 = EEPROM.get(0,cprimercelu);  // psso el contenido de eeprom a un nuevo String (celular1)
       delay(3000);
       Serial.println(celular1); // veo que en este nuvo String tenga guardado el numero                                                 
       Serial.println("Enviando Mensaje");
       sim800l.print("AT\r");
       delay(500);
       sim800l.print("AT+CMGF=1\r");
       delay(500);
       sim800l.print("AT+CMGS=\"" + celular1 + "\"\r"); // ESTA LINEA NO SE EJECUTA. SOLO ENVIÓ EL SMS 1 VEZ                             
       Serial.println("AT+CMGS=\"" + celular1 + "\"\r");
       delay(250);
       sim800l.print(" LOGRADO ");// Mensaje que no logro enviar.....
       delay(500);                                                                           
       sim800l.print(char(26));
       delay(500);
       sim800l.println();
       Serial.println("Mensaje Enviado");
                                                                                               
}

void loop(){
                                             
 if(sim800l.available()>0){
   (celulares = sim800l.readString()); // EN EL CUERPO DEL MENSAJE ENVÍO "cel1 +549xxxxxxxxxx"
   if((celulares.indexOf("cel1") > 0)){
   Serial.println("Se reconocio la palabra CEL1");
   delay(500);
   PrimerCelular();
   }  
  } 
 }

Hola @cjvc2020, tal como te pedí, te respondo ahora que has creado el hilo. Gracias por hacerlo.

En lo personal tengo algo con los comandos AT, no me gustan aunque cuando no hay nada los uso, claro esta, pero si hay librerías las uso.

Este ejemplo corresponde a la librería GSM que encuentras en el Gestor del IDE.

Recibir SMS

Observa que fácil es

@surbyte gracias por tu respuesta.

He leìdo esa librería y de hecho voy a intentar hacerlo. Pero te lo reitero porque por ahí no me expliqué bien.
El numero que yo quiero recuperar no es el del remitente, sino es uno que està escrito en el cuerpo del mensaje y puede que coincida o no con el del remitente.

En su momento lo que vi de esa librería era que el numero que rescataba con "facilidad" era el del remitente y en el caso del cuerpo del mensaje lo guardaba en un char, algo parecido como lo que estaba haciendo.
Reitero las gracias por la respuesta y voy a probar con esa librería.
En cuanto a mi programa no me queda claro porque en algún momento respondió. Veremos..
Gracias

Si tienes el mensaje lo que quieres recuperar se hace usando comparación con cadenas sea String o cadenas de arrays.
Ahora me fijo y te digo.

MIra el mensaje se muestra aqui

 // Read message bytes and print them
    while (c = sms.read()) {
      Serial.print(c);
    }

quiere decir que c va mostrando letra por letra.
Una opcion para manejarlo de modo cómodo es crear un String e ir concatenando los valores de este modo.
Define un String como global.

// define variables globales.
String msg = "";
int index = 0;

// en el loop en el mismo lugar ahora haces
     msg = "";
    // Read message bytes and print them
    while (c = sms.read()) {
      msg += c;
    }
    
 // luego de tener todo en msg ahora puedes buscar tu número por ejemplo con Substring()
 // busca lo que necesitas con 
  byte  ubico = msg.indexOf("+54"); // busco telefonos de Argentina p.ejemplo  
  if (ubico > -1 ) { 
           Serial.println("command:" + msg.Substring(ubico-3,13)); // imprimo 13 caracteres desde la posición encontrada. Puede haber errores

  }

a ver si esto te ubica mas en lo que persigues para encontrar un número telefónico X en el cuerpo del msg recibido.

a= Serial.readString();// read the incoming data as string

@surbyte nuevamente gracias.

Reitero porque me parece que no me entendiste. En cuanto a recuperar en numero dentro del cuerpo del mensaje, yo no tengo ningún inconveniente. De hecho lo recupero y por el puerto serie veo exactamente que el numero que yo "pegue" dentro del comando AT, es el numero que yo quiero.

Y de hecho, como te mencionè cuando cree el hilo, que en dos oportunidades , el mensaje fue enviado.

Estoy viendo si la cosa viene por otro lado, ya que el numero con la función "remove" logro recuperarlo.
Gracias...

He repasado tu código por encima y veo que no has puesto el ; después del número a enviar.
Si no es eso.... avisa y lo repaso con mas tiempo.
este es tu codigo

sim800l.print("AT+CMGS=\"" + celular1 + "\"\r"); // ESTA LINEA NO SE EJECUTA. SOLO ENVIÓ EL SMS 1 VEZ

este sería el correcto

sim800l.print("AT+CMGS=\"" + celular1 + ";\"\r"); // ESTA LINEA NO SE EJECUTA. SOLO ENVIÓ EL SMS 1 VEZ

Saludos

Hola @bosoft gracias por tu ayuda.
Agregué ese ; pero no pasa nada. Todo igual....

Jajaja, ahora entiendo lo que me dices! Hice cualquier cosa. Para un juego de teléfono descompuesto y el descompuesto soy yo claramente.

Prueba así

sim800l.print("AT+CMGS= \"" + number +"\"");

Hola @surbyte......No,no. Puse somo me dijiste, en el monitor serie me muestra de igual forma como lo tenia configurado yo (AT+CMGS= +549xxxxxxxxxx " ) pero no lo envía.
No se.....

Según esto

AT+CMGS=

se debe enviar el CR que yo no hice.

Mira este tutorial a ver si sirve

void mensaje_sms(String Numero, String Texto)
{
  wdt_reset();
  if (Numero != NULL && Texto != NULL) {

    if (enviarAT(“AT + CREG ? ”, “ +CREG : 0, 1”, 1000) == 1) //comprueba la conexion a la red
    {

      Serial.print(“Enviando SMS…a “);
      Serial.println(Numero);

      enviarAT(“AT + CMGF = 1\r”, “OK”, 2000); //Comando AT para mandar un SMS
      //sprintf(aux_str, comando, strlen(Texto)); //Numero al que vamos a enviar el mensaje no lo uso

      // printf(“AT+CMGS=\”%s\””,AT, Numero); //Numero al que vamos a enviar el mensaje no lo uso

      //Serial.print(“Numero: “);
      // Serial.println(numero);

      String comando = “AT + CMGS = \””;

      Numero.concat(‘\”‘);

      comando.concat(Numero);

      wdt_reset();
      delay(2000);
      wdt_reset();

      Texto.concat((char)26);

      Serial.print(“comando: “);
      Serial.println(comando);

      //Serial.print(“Numero: “);
      // Serial.println(Numero);

      Serial.print(“Texto: “);
      Serial.println(Texto);

      //Texto del mensaje
      if (enviarAT(comando, ‘ > ’, 10000) == 1)
      {

        if ( enviarAT(Texto, “OK”, 10000) == 1) {
          Serial.println(“SMS enviado”);
        }

      } else {
        Serial.println(“SMS NO enviado”);
      }

    } else {
      reiniciar();
      iniciar();

    }

  } else {
    Serial.println(“Error: No hay numero o no hay texto para el mensaje”);
  }

}

comenta wdt_reset(); por ahora

@surbyte ese link que me pasaste lo estuve mirando de una pagina de España. Sinceramente no se como adaptarlo a mi programa, pero lo que si había visto que es 0x0D =13 y se me ocurrió agregar una linea mas, debajo del comando en cuestión tipo .... sim800l.print(char(13)); pero tampoco diò resultado.

Aprovecho y te pregunto porque me quedò la duda.......si yo hago un Serial.print(celular1); que es el contenido que yo guardè en la posición 0 de la eeprom y eso me muestra que tengo guardado el numero que yo deseo,...puede que vea un numero en el puerto serie y en realidad haya otro guardado en ese String?? Porque lo que me marea es eso. Que yo veo el numero tal cual lo necesito

Es mas, si ese numero lo guardo en el soft previamente en un char, lo paso a la eeprom, y luego lo paso a un string, lo lee perfectamente dentro del comando AT porque ya probé con otro programa.
El problema viene cuando lo tiene que levantar del cuerpo de un mensaje

No entiendo que me queres decir con "comenta wdt_reset(); por ahora" ?????

@surbyte te cuento otra prueba que hice... Hice otro programa en el que defino el mismo numero el cual envío en el cuerpo del mensaje llamado "teléfono"(Ej ·define teléfono "+549xxxxxxxxxx"

Luego de la linea en la que convierto el numero a char, agregué un if strstr..... en la que comparo ambos telefonos, es decir, el que tengo definido en el programa y el que guardè y son exactamente IGUALES y dada esta condición salto a otro void del programa.

De esta manera me auto conteste la pregunta que te hice con respecto a lo que veo por el puerto serie jajajaja

No se. Volveré al ruedo cuando se me acomoden las ideas.... Gracias como siempre...

Ya empiezo a mosquearme. Si esto no te funciona le dedicaré un rato a investigar

sim800l.print(" LOGRADO ");// Mensaje que no logro enviar.....
sim800l.print("\r"); <------ creo que te falta esto después del mensaje

si todavía falla, haré pruebas con un SIM900, pero viendo como tengo los SMSs en varios SIMs no me queda claro porque no envía a no ser que el numero no esté "correctamente" escrito

Saludos

Hola bosoft como estas. No. Tampoco funciona.
Por otro lado te comento que el teléfono està perfectamente grabado, por lo menos es lo que verifico por el puerto serie.
Y si has estado mirando un poco las pruebas que hice, en el post anterior mencionè que había hecho otro programa en el que verifico el numero "rescatado" del mensaje, con otro igual definido en el programa y son iguales. Eso es lo que mas me marea. En todas las pruebas que hice, siempre por el puerto serie veo el numero que quiero.
Seguiré probando y analizando.
Como siempre les digo, gracias por la ayuda....

No entiendo que me queres decir con "comenta wdt_reset(); por ahora" ?????

COmentar es poner // antes de wdt_reset asi

//wdt_reset();

Hola @surbyte, hola @bosoft......Bueno estoy mas que seguro que encontré el error pero no se como solucionarlo.

Cuando rescato el numero y lo pego en el comando at, al momento de enviar el mensaje, el comando se muestra de la siguiente manera por el puerto serie:

AT+CMGS="+549xxxxxxxxx1 "--------------Si observan queda un espacio entre en ultimo numero que es un 1 y las comillas.

Si yo en lugar de "pegar" el numero que rescato, lo hago escribiendo el numero en el programa para probar ejemplo: sim800l.print(AT+CMGS="+549xxxxxxxxx1"\r");----------al momento de enviar el mensaje el comando se muestra de la siguiente manera por el puerto serie:

AT+CMGS="+549xxxxxxxxx1" -------------es decir, sin espacios al final

Ante esta duda configurè la segunda opción generándole espacios al final y el comando no se envía.

Estoy casi seguro que si logro limpiar ese espacio, el comando se enviarà.

Ustedes que son expertos dirán....Gracias como siempre

Bueno amigos lo he solucionado no se si de la mejor manera, pero vamos trabajando. Les comento

En el cuerpo del mensaje yo mandaba el comando ejemplo: cel1 +549xxxxxxxxx1.

Ahora mando cel1 +549xxxxxxxxx1/ (le agrego una barra)

Y en el programa original, antes de grabar el String llamado celulares en la eeprom, agrego una linea:

celulares.trim(); y con esto borro cualquier caracter del 1 para atrás. Luego lo grabo en la eeprom, y lo paso a un nuevo String y de esas forma puedo "pegarlo" dentro del comando AT sin problema.
En cuanto emprolije el programa lo subo.
Escucho si hay otra posibilidad mejor sin necesidad de agregar un caracter mas como "/" al final.

Nada que decirte, en estas cosas se debe observar el detalle.
Si asi te funciona, adelante!!

@surbyte aprovecho y te consulto. Se puede pegar el contenido de una posición de la eeprom en el cuerpo del mensaje??

La idea es que ese mismo numero que uso para responder lo pueda "pegar" en el cuerpo del mensaje

Gracias como siempre....

No entiendo bien qué preguntas? Pegar el contenido de una posición de la EEPROM.
Puedes armar un mensaje con lo que gustes, incluido contenido de donde quieras, la EEPROM por ejemplo.