Leer contenido SMS..

Hola a todos, una consulta: como se puede filtrar o separar un sms que sale por monitor de la siguiente manera:

+CMTI: "SM",1
+CMGR: "REC UNREAD","+54XXXXXXXXX,,"12/12/08,12:43:41+04"
Mensaje de pruebas

OK

yo quisiera poder recuperar o extraer solo "mensaje de pruebas" que es todo el contenido del sms…

estuve mirando la librería:

String Sim800l::readSms(uint8_t index){
  SIM.print (F("AT+CMGF=1\r")); 
  if (( _readSerial().indexOf("ER")) ==-1) {
    SIM.print (F("AT+CMGR="));
    SIM.print (index);
    SIM.print("\r");
    _buffer=_readSerial();
    if (_buffer.indexOf("CMGR:")!=-1){
      return _buffer;
    }
    else return "";    
    }
  else
    return "";
}

pero no tengo idea como poder recuperar solo el contenido del sms...ojala me puedan orientar..

Hola..alguien que me pueda tirar alguna idea??

la verdad que no lo gro entender como leer todo el mensaje y como quedarme solo con el contenido.. en realidad tengo que eliminar los primeros 56(creo si no conte mal) caracteres y aislar el resto que son siempre 13...

Hola Landom!! te ayudaria de mil amores, tengo la misma libreria, y por ende supongo que el mismo modulo que vos ajaja, y seria super interesante poder aislar el contenido de un sms..ojala alguien te de una respuesta de como hacerlo...a mi tambien me vendria barbaroo...salu2..

Any.

Hola Any, agradezco tu preocupación jajaja si será el mismo modulo yo uso un sim800l con un Arduino uno...
si obvio q seria re interesante porque es muy útil poder aislar el contenido de un sms, incluso poder reconocer dentro del sms y separador, por ejemplo:

"+54xxxxxxxxx+password"

esto seria de una enorme utilidad...ojala alguien nos tire una soga, saludos..

Hola, encontré este código, pongo el link porque no me deja todo el código excede:

es de otro modulo l sim900, pero en la parte de extraer el mensaje:

/* Funsión para la recepción de información de un numero celular remitente
   cualesquiera, e identificación del tipo de numero remitente. */
void Receive_message_and_Phone_Number(){
  char num0,num1,num2,num3,num4,num5,num6,num7,num8,num9,num10,num11,num12;
  char data;
  int trama=0;
  for(int i=0;i<=100;i++){
    data=Serial.read();
    /* Empezar a detectar el segmento contenedora del número telefónico 
       remitente de los datos de entrada. */
    if((trama == 0) && (data == 'C')){ 
      trama = 1;
      destinationNumber="";
      clave="";
    }
    // lectura de caracter espacio "M" seguido del caracter dos punto "C"
    if((trama == 1) && (data == 'M')){
      trama = 2;
    }
    if((trama == 2) && (data == 'T')){  // detecta el caracter "T".
      trama = 3;
    }
    if((trama == 3) && (data == ':')){  // detecta el caracter ":".
      trama = 4;
    }
    if((trama == 4) && (data == ' ')){  // detecta el caracter " ".
      trama = 5;
    }
    if((trama == 5) && (data == '"')){  // detecta el caracter """.
      trama=6;
      /* Empieza a capturar el número telefónico remitente a partir del 
         caracter "+" del tipo +593982832027 para Ecuador. */
      num0 = Serial.read();
      num1 = Serial.read();
      num2 = Serial.read();
      num3 = Serial.read();
      num4 = Serial.read();
      num5 = Serial.read();
      num6 = Serial.read();
      num7 = Serial.read();
      num8 = Serial.read();
      num9 = Serial.read();
      num10 = Serial.read();
      num11 = Serial.read();
      num12 = Serial.read();
      
      destinationNumber += num0;
      destinationNumber += num1;
      destinationNumber += num2;
      destinationNumber += num3;
      destinationNumber += num4;
      destinationNumber += num5;
      destinationNumber += num6;
      destinationNumber += num7;
      destinationNumber += num8;
      destinationNumber += num9;
      destinationNumber += num10;
      destinationNumber += num11;
      destinationNumber += num12;
      if ((num1=='5')&&(num2 =='9')&&(num3=='3'))
      /* Si el número de celular remitente es correcto 
         (código de país para Ecuador 593). */
         destinationNumber = destinationNumber;
      else 
      /* Número incorrecto, mantener número registrado por software.
         Si el remitente no es un número celular o nacional. */
         destinationNumber = log_numeber;
    }
    // Lectura de clave o contraseña enviada por el remitente.
    if((trama==6)&&(data=='#')){
      trama = 0;
      clave1=Serial.read();
      clave2=Serial.read();
      clave3=Serial.read();
      clave4=Serial.read();
      clave += clave1;
      clave += clave2;
      clave += clave3;
      clave += clave4;
      //contraseña correcta = 1234.
      if ((clave1=='1')&&(clave2 =='2')&&(clave3=='3')&&(clave4=='4')) {
        Send_message();      /* envió de información solicitada, es decir estado
                                                de la estación  de monitoreo. */
        digitalWrite(LED_3,HIGH); // Encender LED si es correctas la contraseña.
      }
      else {
        Send_message_Err();// envió de mensajes de solicitud errónea.
        digitalWrite(LED_3,LOW);  // Apagar LED si es incorrectas la contraseña.
      }
    }
    delay(100);  // tiempo necesario para recepción de datos.
  }
}

estaría la posibilidad de adaptar al modulo sim800l...

igual no veo como puedo hacer para adaptar esa info al modulo, ya que da respuesta de este tipo:

AT+CMGR=1
+CMGR: "REC UNREAD","+xxxxxxxxxxxx","","17/06/28,19:58:04-12"
#loquesea

no se como puedo modificar el código para adapralo y ller el mensaje..

Empecemos por lo básico.
Qué librería usan? Ninguna y como no usan librería se tienen que darse contra la pared intentando reinventar la rueda.

Existe una librería que es la que viene por defecto en el IDE. La buscaron?
Si leen las normas del foro, éstas les dicen.. que antes de preguntar hay que buscar y seguramente buscaron porque este link no salió de la nada. Pero aprender a buscar es importante.

Se busca asi y no se molesten, porque las preguntas de ambos prueban que lo hacen mal.

Google: Arduino GSM esto les dará todo sobre ambos temas
Google: Arduino GSM Library

Dirá que ésta es una librería a tener en cuenta GSM library

Este librería tiene ejemplos de todo tipo como éste

Receive SMS

Acá otra GPRS SIM900 que soporta SIM800L

y aca un ejemplo que lee SMS

Espero les sirva.

Hola que tal Surbyte, agradezco tu aporte, la libreria q uso es la de sim800l-master de Cristian Steib...yo lo modifique asi, para tratar de adaptarlo:

char inicio_clave;
char clave1;
char clave2;
char clave3;
char clave4;
String clave = "";
String destinationNumber = "";

void Receive_message_and_Phone_Number(){
  char num0,num1,num2,num3,num4,num5,num6,num7,num8,num9,num10,num11,num12,num13;
  char data;
  int trama=0;
  for(int i=0;i<=100;i++){
    data=ctextSms;
    /* Empezar a detectar el segmento contenedora del número telefónico 
       remitente de los datos de entrada. */
    if((trama == 0) && (data == 'C')){ 
      trama = 1;
      destinationNumber = numberSms;
      clave="";
    }
    // lectura de caracter espacio "M" seguido del caracter dos punto "C"
    if((trama == 1) && (data == 'M')){
      trama = 2;
    }
    if((trama == 2) && (data == 'G')){  // detecta el caracter "G".
      trama = 3;
    }
    if((trama == 3) && (data == 'R')){  // detecta el caracter "R".
      trama = 4;
    }
    if((trama == 4) && (data == ':')){  // detecta el caracter ":".
      trama = 5;
    }
    if((trama == 5) && (data == ' ')){  // detecta el caracter " ".
      trama = 6;
    }
    if((trama == 6) && (data == '"')){  // detecta el caracter """.
      trama=7;
      /* Empieza a capturar el número telefónico remitente a partir del 
         caracter "+" del tipo +593982832027 para Ecuador. */
      num0 = Serial.read();
      num1 = Serial.read();
      num2 = Serial.read();
      num3 = Serial.read();
      num4 = Serial.read();
      num5 = Serial.read();
      num6 = Serial.read();
      num7 = Serial.read();
      num8 = Serial.read();
      num9 = Serial.read();
      num10 = Serial.read();
      num11 = Serial.read();
      num12 = Serial.read();
      num13 = Serial.read();
      
      destinationNumber += num0;
      destinationNumber += num1;
      destinationNumber += num2;
      destinationNumber += num3;
      destinationNumber += num4;
      destinationNumber += num5;
      destinationNumber += num6;
      destinationNumber += num7;
      destinationNumber += num8;
      destinationNumber += num9;
      destinationNumber += num10;
      destinationNumber += num11;
      destinationNumber += num12;
      destinationNumber += num13;
      if ((num1=='5')&&(num2 =='9')&&(num3=='3')){
      /* Si el número de celular remitente es correcto 
         (código de país para Ecuador 593). */
         destinationNumber = destinationNumber;}
      else {
      /* Número incorrecto, mantener número registrado por software.
         Si el remitente no es un número celular o nacional. */
         //destinationNumber = log_numeber;
    }
    
    // Lectura de clave o contraseña enviada por el remitente.
    if((trama==7)&&(data=='#')){
      trama = 0;
      clave1=Serial.read();
      clave2=Serial.read();
      clave3=Serial.read();
      clave4=Serial.read();
      clave += clave1;
      clave += clave2;
      clave += clave3;
      clave += clave4;
      //contraseña correcta = 1234.
      if ((clave1=='1')&&(clave2 =='2')&&(clave3=='3')&&(clave4=='4')) {
      text="\nNumero no autorizado.";
      error=Sim800l.sendSms();
      error = Sim800l.delAllSms(); //Apaga SMS
      }
      else {
      Serial.println(textSms);
      //Serial.println("Su numero no esta autorizado.");
      text="\nNumero no autorizado.";
      error=Sim800l.sendSms();
      error = Sim800l.delAllSms(); //Apaga SMS
 }
    }
    //delay(1000);  // tiempo necesario para recepción de datos.
  }
  }}

pero no logro que funcione...

y hay otro instrucción que no entiendo bien su funcionamiento:

textSms.indexOf("xxxxx")

esa isntruccion lee/compaa el contenido del sms a la perfeccion..no se si se podrá utilizar para leer el sms de alguna otra forma, ya que ("xxxxx") esto es para comparar, no se como se podría utilizar:

textSms.indexOf() esta parte sola..como tratando de que devuelva el contenido

Que son estas cosas que pones?

[/textSms.indexOf("xxxxx")code]

porque mezclas code con [/code

No leiste las normas del foro? digo porque solo tienes que usar </> para que un texto quede como código. Esta debidamente explicado.

Respecto de la librería no tienes un include de modo que supongo has incluido las funciones/rutinas en tu código.

Bueno toda librería tiene ejemplos para lectura de SMS. Supongo que la tuya tmb.

Yo ya te di dos sugerencias.

Lo que te preguntas que son??? esas cosas que pongo, es un error de tipeo, que creo q no esta penado con la expatriación todavía...espero poder seguir iendo argentino...
no viste q en el primer post puse la parte de la librería que lee el sms? la repito por las dudas:

String Sim800l::readSms(uint8_t index){
  SIM.print (F("AT+CMGF=1\r")); 
  if (( _readSerial().indexOf("ER")) ==-1) {
    SIM.print (F("AT+CMGR="));
    SIM.print (index);
    SIM.print("\r");
    _buffer=_readSerial();
    if (_buffer.indexOf("CMGR:")!=-1){
      return _buffer;
    }
    else return "";    
    }
  else
    return "";
}

la consulta es concreta, como se puede hacer para leer solo el contenido del sms…y después agregue otro fragmento de código que aparentemente ayuda a desglosar el mensaje completo que se recibe y quedarse con lo que uno quiere que es el contenido...
pero no logro adaptarlo... es eso...
a veces contestar por contestar, solo hace mas grande el post...

Bueno veo que lo has corregido y te agredezco, podes seguir siendo argentino al igual que yo.

Vi el primer post pero como no vi un #include a una librería intuí que era algo tuyo.

Ahora te devuelvo la pelota, te puse dos links con ejemplos para leer los SMS. Los viste? Porque ambos devuelven el SMS limpio.

Otra opcion es que lo que recibis en TU rutina lo tenes en un String asi que podes manipular el String.

Sabes como?

Sino una de las dos opciones tiene la forma de hacerlo

bool GPRS::readSMS(int messageIndex, char *message, int length, char *phone, char *datetime)  
{
  /* Response is like:
  AT+CMGR=2
  
  +CMGR: "REC READ","XXXXXXXXXXX","","14/10/09,17:30:17+08"
  SMS text here
  
  So we need (more or lees), 80 chars plus expected message length in buffer. CAUTION FREE MEMORY
  */

    int i = 0;
    char gprsBuffer[80 + length];
    //char cmd[16];
 char num[4];
    char *p,*p2,*s;
    
 //180822 In the init function
 //if(!sim900_check_with_cmd(F("AT+CMGF=1\r\n"), "OK\r\n", CMD)) { // Set message mode to ASCII
    //    return false;
    //}
    //delay(1000); 

 //sprintf(cmd,"AT+CMGR=%d\r\n",messageIndex);
    //sim900_send_cmd(cmd);
 sim900_send_cmd(F("AT+CMGR="));
 itoa(messageIndex, num, 10);
 sim900_send_cmd(num);
 sim900_send_cmd(F("\r\n"));
    sim900_clean_buffer(gprsBuffer,sizeof(gprsBuffer));
    sim900_read_buffer(gprsBuffer,sizeof(gprsBuffer));
      
// **********************************************
// ESTO ES LO QUE ESTAS BUSCANDO
// No es mas facil usar la librería que ya lo hace?
// **********************************************


    if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){
        // Extract phone number string
        p = strstr(s,",");
        p2 = p + 2; //We are in the first phone number character
        p = strstr((char *)(p2), "\"");
        if (NULL != p) {
            i = 0;
            while (p2 < p) {
                phone[i++] = *(p2++);
            }
            phone[i] = '\0';            
        }
        // Extract date time string
        p = strstr((char *)(p2),",");
        p2 = p + 1; 
        p = strstr((char *)(p2), ","); 
        p2 = p + 2; //We are in the first date time character
        p = strstr((char *)(p2), "\"");
        if (NULL != p) {
            i = 0;
            while (p2 < p) {
                datetime[i++] = *(p2++);
            }
            datetime[i] = '\0';
        }        
        if(NULL != ( s = strstr(s,"\r\n"))){
            i = 0;
            p = s + 2;
            while((*p != '\r')&&(i < length-1)) {
                message[i++] = *(p++);
            }
            message[i] = '\0';
        }
        return true;
    }
    return false;    
}

Lee porque en la rutina indico desde donde está la parte que te separa las cosas.
Para mi conviene usar la librería.

Gracias por tu respuesta, si lo corregí porque tenes razón lo q pasa q a veces (por lo menos a mi me pasa, no se seguido pero..) le damos ok para enviar y seguimos viaje...claro se q es un error no chequear, pero bue en la vorágine de la búsqueda de la solución jajajaja pasa de todo..

a ver si te sigo, me pones el código y en una parte dice:

// **********************************************
// ESTO ES LO QUE ESTAS BUSCANDO
// No es mas facil usar la librería que ya lo hace?
// **********************************************


    if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){
        // Extract phone number string
        p = strstr(s,",");
        p2 = p + 2; //We are in the first phone number character
        p = strstr((char *)(p2), "\"");
        if (NULL != p) {
            i = 0;
            while (p2 < p) {
                phone[i++] = *(p2++);
            }
            phone[i] = '\0';            
        }
        // Extract date time string
        p = strstr((char *)(p2),",");
        p2 = p + 1; 
        p = strstr((char *)(p2), ","); 
        p2 = p + 2; //We are in the first date time character
        p = strstr((char *)(p2), "\"");
        if (NULL != p) {
            i = 0;
            while (p2 < p) {
                datetime[i++] = *(p2++);
            }
            datetime[i] = '\0';
        }        
        if(NULL != ( s = strstr(s,"\r\n"))){
            i = 0;
            p = s + 2;
            while((*p != '\r')&&(i < length-1)) {
                message[i++] = *(p++);
            }
            message[i] = '\0';
        }
        return true;
    }
    return false;    
}

.

eso pareciera que es para recuperar el numero de teléfono, y eso si lo hago con una de las funciones de la librería:

Sim800l.getNumberSms(1);

que pasa el numero de cel que envio el mensaje a una variable que uso mucho..ahora,

yo puse este código:

char inicio_clave;
char clave1;
char clave2;
char clave3;
char clave4;
String clave = "";
String destinationNumber = "";

void Receive_message_and_Phone_Number(){
  char num0,num1,num2,num3,num4,num5,num6,num7,num8,num9,num10,num11,num12,num13;
  char data;
  int trama=0;
  for(int i=0;i<=100;i++){
    data=ctextSms;
    /* Empezar a detectar el segmento contenedora del número telefónico 
       remitente de los datos de entrada. */
    if((trama == 0) && (data == 'C')){ 
      trama = 1;
      destinationNumber = numberSms;
      clave="";
    }
    // lectura de caracter espacio "M" seguido del caracter dos punto "C"
    if((trama == 1) && (data == 'M')){
      trama = 2;
    }
    if((trama == 2) && (data == 'G')){  // detecta el caracter "G".
      trama = 3;
    }
    if((trama == 3) && (data == 'R')){  // detecta el caracter "R".
      trama = 4;
    }
    if((trama == 4) && (data == ':')){  // detecta el caracter ":".
      trama = 5;
    }
    if((trama == 5) && (data == ' ')){  // detecta el caracter " ".
      trama = 6;
    }
    if((trama == 6) && (data == '"')){  // detecta el caracter """.
      trama=7;
      /* Empieza a capturar el número telefónico remitente a partir del 
         caracter "+" del tipo +593982832027 para Ecuador. */
      num0 = Serial.read();
      num1 = Serial.read();
      num2 = Serial.read();
      num3 = Serial.read();
      num4 = Serial.read();
      num5 = Serial.read();
      num6 = Serial.read();
      num7 = Serial.read();
      num8 = Serial.read();
      num9 = Serial.read();
      num10 = Serial.read();
      num11 = Serial.read();
      num12 = Serial.read();
      num13 = Serial.read();
      
      destinationNumber += num0;
      destinationNumber += num1;
      destinationNumber += num2;
      destinationNumber += num3;
      destinationNumber += num4;
      destinationNumber += num5;
      destinationNumber += num6;
      destinationNumber += num7;
      destinationNumber += num8;
      destinationNumber += num9;
      destinationNumber += num10;
      destinationNumber += num11;
      destinationNumber += num12;
      destinationNumber += num13;
      if ((num1=='5')&&(num2 =='9')&&(num3=='3')){
      /* Si el número de celular remitente es correcto 
         (código de país para Ecuador 593). */
         destinationNumber = destinationNumber;}
      else {
      /* Número incorrecto, mantener número registrado por software.
         Si el remitente no es un número celular o nacional. */
         //destinationNumber = log_numeber;
    }
    
    // Lectura de clave o contraseña enviada por el remitente.
    if((trama==6)&&(data=='#')){
      trama = 0;
      clave1=Serial.read();
      clave2=Serial.read();
      clave3=Serial.read();
      clave4=Serial.read();
      clave += clave1;
      clave += clave2;
      clave += clave3;
      clave += clave4;
      //contraseña correcta = 1234.
      if ((clave1=='1')&&(clave2 =='2')&&(clave3=='3')&&(clave4=='4')) {
      text="\nNumero no autorizado.";
      error=Sim800l.sendSms(numberSms.c_str(),text);
      error = Sim800l.delAllSms(); //Apaga SMS
      EEPROM.put(0,numberSms.c_str());  
      EEPROM.get(0, Buffer_admin);
      text="\nActualizando Admin Tel...";  
      error=Sim800l.sendSms(buffer_Admin,text);
      //Serial.println("Actualizando Admin Tel...");
      //Serial.println("Nuevo numero de admin:");
      //Serial.println(buffer_EEPROM);
      strcat( text1, "El nuevo numero aceptado es: ");
      strcat( text1, buffer_Admin);
      error=Sim800l.sendSms(buffer_Admin,text1);          
      error = Sim800l.delAllSms(); //Apaga SMS
      }
      else {
      Serial.println(textSms);
      //Serial.println("Su numero no esta autorizado.");
      text="\nNumero no autorizado.";
      error=Sim800l.sendSms(numberSms.c_str(),text);
      error = Sim800l.delAllSms(); //Apaga SMS
 }
    }
    //delay(1000);  // tiempo necesario para recepción de datos.
  }
  }}

pero no logro adaptarlo...

No entiendo lo que estas buscando entonces.

busco obtener solo el contenido del mensaje, no esto:

AT+CMGR=1
+CMGR: "REC UNREAD","+xxxxxxxxxxxx","","17/06/28,19:58:04-12"
#loquesea //esto es lo que mande en el sms

solo quiero recuperar:
#loquesea

q es lo q esta dentro del mensaje...

esta esta función:

Sim800l.readSms(1);

usada de esta forma:

//Lee el SMS en la posicion 1
  textSms = Sim800l.readSms(1);

pero al mostrarla en monitor es el mensaje completo:

AT+CMGR=1
+CMGR: "REC UNREAD","+xxxxxxxxxxxx","","17/06/28,19:58:04-12"
#loquesea

y veo la manera de obtener solo en contenido del sms si no es desglosando...

Como te dije antes, usa las funciones inherentes a la clase String como esta

if (textSms.substring(8) == "REC UNREAD") {
    Serial.println("Ahi comienza REC UNREAD");
    Serial.println(textSms.substring(21,10)); // debería imprimir el número que envio el SMS
  }

Hola Surbyte, gracias por tu respuesta..

He probado como pusiste pero no hay Serial.println...se queda congelado aunque sigue funcionando el programa

No lo toma, se queda colgado en esta línea:

if (textSms.substring(8) == "REC UNREAD") {

...consulta, habrá algún error desde donde se toma como inicio del mensaje completo?

digo esto porque en pantalla muestra asi:

AT+CMGR=1
+CMGR: "REC UNREAD","+xxxxxxxxxxxx","","17/06/28,19:58:04-12"
#loquesea

arranca por AT+CMGR=1...
no se como se calcula ese salto de renglon..pero tal vez no lo toma por eso..

Una consulta: la línea de código:

textSms.indexOf()

devuelve exactamente el contenido del sms...no hay alguna forma de manipular eso??

Lo que veo también es q son 3 líneas que devuelve textSms:

AT+CMGR=1
+CMGR: "REC UNREAD","+xxxxxxxxxxxx","","17/06/28,19:58:04-12"
#loquesea

no se puede hacer que solo se lea la ultima línea que es siempre la del mensaje?

Hola Suubyte, hice esto:

       Serial.println(textSms);
         if (textSms.substring(0, 9) == "AT+CMGR=1") {
         Serial.println("AT+CMGR=1");
      }

y aparece asi en el monitor:

AT+CMGR=1
+CMGR: "REC UNREAD","+541126569397","","19/01/29,00:51:24-12"
Z790M41LX211U#1234

OK

AT+CMGR=1 /// aca lo hace escribe el texto del sms de la primera línea..

el tema es como puedo hacer para que haga el substring de la 3er línea..

Hola Surbyte, ya lo resolvi…
el tema es contar los caracteres desde el inicio hasta el final del sms completo y agregarle 2, que supongo serán los saltos de liea, pareciera que los toma como un carácter mas, en mi caso:

AT+CMGR=1  9 caratcteres
+CMGR: "REC UNREAD","+541126569397","","19/01/29,00:51:24-12" 61 caracteres
Z790M41LX211U 13 caracteres

9 + 61 = 70 hasta aca; a eso le sumo mi texto que son siempre 13 da 83 y los 2 del salto de línea = 85

el tema es ver igual como aislar la 3 línea ahí esta el chiste...

para que me funcione uso:

Serial.println(textSms.substring(-85,73));

pero repito, lo ideal seria poder aislar la 3 línea que no se como se programaria eso para que siempre lo que este ahí sea el contenido del sms...