functions ::IsSMSPresent and ::GetSMS not returning next message's position?

Good day!

I am working on a project that has GSM to LED Matrix display
and looping the function checkSMS()
but the 2nd time a message gets read, it doesnt return the position.

It reads and successfully display the first message but the 2nd doesnt

anyone?

here’s the code

// GSM
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
#include <iostream>
#include <array>

#define OUTPUT_SERIAL

SMSGSM sms;

template <typename T, size_t N>
inline
size_t SizeOfArray( T(&)[ N ] )
{
  return N;
}

boolean MSG_RCVD    = false;

char position;
char phone_num[20]; // array for the phone number string
char sms_text[160]; // array for the SMS text string
char sms_text_final[160]; // array for the SMS text string

char *inbox[5];

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];

// LED MATRIX
#include "cmap.h"
#define INTEN 6000

int d;
unsigned char char_pointer;
char Display_Ram[38];
unsigned char mask;

int array_ctr;

int message_no;                         // message counter
int message_no_txt;

char count;	
unsigned char shift_counter;

const char regnum[] = "639175086850";   // admin number

const char CLK = 5; 
const char DAT = 6; 
const char STR = 7; 
const char K0 = A0; 
const char K1 = A1; 
const char K2 = A2; 
const char K3 = A3; 
const char K4 = 8; 
const char K5 = 9; 
const char K6 = 10; 
const char K7 = 11; 

const char RX = RX;
const char TX = TX;

char *TXT[] = {"Announcement No.1 NEW           ~",
		     "Announcement No.2 NEW      ~",
                     "Announcement No.3 NEW      ~", 
                     "Announcement No.4 NEW      ~",
                     "Announcement No.5 NEW      ~"};
void setup() {  
  
  Serial.begin(9600);
  if(gsm.begin(9600)) { 
      started=true;
      #ifdef OUTPUT_SERIAL
        Serial.println("\nGSM INIT");
      #endif
  }
  
  #ifdef OUTPUT_SERIAL
      Serial.println("\nSETUP INITIALIZED");
  #endif
  
  if(started){   
   
    //Enable this two lines if you want to send an SMS.
    //if (sms.SendSMS("09175086850", "Started"))
      //Serial.println("\nSMS sent OK");
            
      // NOTE: IF SIM INBOX IS FULL uncomment below
      // http://www.developershome.com/sms/cmgdCommand.asp
      
     
      if(gsm.SendATCmdWaitResp("AT+CMGD=1,1", 1000, 50, "OK", 2)) {
        #ifdef OUTPUT_SERIAL
            Serial.println("\nSMS DELETED ALL");
        #endif
      }
      
  }
 
  
  pinMode(CLK, OUTPUT);     
  pinMode(DAT, OUTPUT);     
  pinMode(STR, OUTPUT);     
  pinMode(K0, OUTPUT);     
  pinMode(K1, OUTPUT);     
  pinMode(K2, OUTPUT);     
  pinMode(K3, OUTPUT);     
  pinMode(K4, OUTPUT);     
  pinMode(K5, OUTPUT);     
  pinMode(K6, OUTPUT);     
  pinMode(K7, OUTPUT);  

  digitalWrite(K0,HIGH);  
  digitalWrite(K1,HIGH);  
  digitalWrite(K2,HIGH);  
  digitalWrite(K3,HIGH);  
  digitalWrite(K4,HIGH);  
  digitalWrite(K5,HIGH);  
  digitalWrite(K6,HIGH);  
  digitalWrite(K7,HIGH);  

  for(d=0;d<32;d++)
  {
    clock();
  }
  strobe();
  d = 0;
}

int inboxCtr = 0;

void checkSMS() 
{   
  #ifdef OUTPUT_SERIAL
      Serial.println("called checkSMS");
  #endif

  if(started){
    position = sms.IsSMSPresent(SMS_UNREAD);
    
    if (position > 0) {
      
      // read new SMS
        sms.GetSMS(position, phone_num, sms_text, 100);
        #ifdef OUTPUT_SERIAL
            Serial.print("RECEIVED MSG: ");
            //Serial.print(phone_num);
            Serial.println(sms_text);
        #endif
        
        MSG_RCVD = true;
                
        strcat (sms_text_final,"     ");
        strcat (sms_text_final,sms_text);
        strcat (sms_text_final,"           ~");
        inbox[inboxCtr] = sms_text_final;
        inboxCtr++;
        if (inboxCtr == 5)        {
          inboxCtr = 0;
        }
    }

  }
  else MSG_RCVD = false;
  
  gsm.SetCommLineStatus(CLS_FREE);
};

void loadSMS(void){
  
  String test = inbox[message_no_txt];
  //Serial.print("STR COUNT: "); Serial.print(test.length());
  
  if (message_no_txt >= 4 || test.length()==0)
  {
    message_no_txt = 0;
    checkSMS();   
  }
  
  char counter1;
  
  char *LED_DATA = inbox[message_no_txt];  

  if(LED_DATA[char_pointer+1] == '~' || LED_DATA[char_pointer+1] == '\0'){
    char_pointer = 0;
    message_no_txt++;
  }
  for(counter1 = 0; counter1 < 5; counter1++){
    Display_Ram[32 + counter1] = character_data[(LED_DATA[char_pointer] - 0x20)][counter1];
  }	
  Display_Ram[37] = 00;	
  char_pointer++;
}

void load(void){
  if (message_no >= 4)
  {
    message_no = 0;
    checkSMS();
  }
  
  char counter1;
  
  char *LED_DATA = TXT[message_no];
  //Serial.print(LED_DATA); Serial.print(array_ctr);

  if(LED_DATA[char_pointer+1] == '~' || LED_DATA[char_pointer+1] == '\0'){
    char_pointer = 0;
    message_no++;
  }
  for(counter1 = 0; counter1 < 5; counter1++){
    Display_Ram[32 + counter1] = character_data[(LED_DATA[char_pointer] - 0x20)][counter1];
  }	
  Display_Ram[37] = 00;	
  char_pointer++;
}

void loop(){
  Display();
  shift(); 
 //checkSMS();
}		

void shift(void) 
{
  Display_Ram[0] = Display_Ram[1];
  Display_Ram[1] = Display_Ram[2];
  Display_Ram[2] = Display_Ram[3];
  Display_Ram[3] = Display_Ram[4];
  Display_Ram[4] = Display_Ram[5];
  Display_Ram[5] = Display_Ram[6];
  Display_Ram[6] = Display_Ram[7];
  Display_Ram[7] = Display_Ram[8];
  Display_Ram[8] = Display_Ram[9];
  Display_Ram[9] = Display_Ram[10];
  Display_Ram[10] = Display_Ram[11];
  Display_Ram[11] = Display_Ram[12];
  Display_Ram[12] = Display_Ram[13];
  Display_Ram[13] = Display_Ram[14];
  Display_Ram[14] = Display_Ram[15];
  Display_Ram[15] = Display_Ram[16];
  Display_Ram[16] = Display_Ram[17];
  Display_Ram[17] = Display_Ram[18];
  Display_Ram[18] = Display_Ram[19];
  Display_Ram[19] = Display_Ram[20];
  Display_Ram[20] = Display_Ram[21];
  Display_Ram[21] = Display_Ram[22];
  Display_Ram[22] = Display_Ram[23];
  Display_Ram[23] = Display_Ram[24];
  Display_Ram[24] = Display_Ram[25];
  Display_Ram[25] = Display_Ram[26];
  Display_Ram[26] = Display_Ram[27];
  Display_Ram[27] = Display_Ram[28];
  Display_Ram[28] = Display_Ram[29];
  Display_Ram[29] = Display_Ram[30];
  Display_Ram[30] = Display_Ram[31];
  Display_Ram[31] = Display_Ram[32];
  Display_Ram[32] = Display_Ram[33];
  Display_Ram[33] = Display_Ram[34];
  Display_Ram[34] = Display_Ram[35];
  Display_Ram[35] = Display_Ram[36];
  Display_Ram[36] = Display_Ram[37];
  shift_counter++;
  if(shift_counter == 6){
    shift_counter = 0;
    
    if(MSG_RCVD == true)
    {
      loadSMS();
    }
    else
    {
      load();
    }
    
  }
}

void Display(void)
{
  mask = 0x01;
  scan();
  digitalWrite(K7,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K7,HIGH);

  mask = 0x02;
  scan();
  digitalWrite(K6,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K6,HIGH);

  mask = 0x04;
  scan();
  digitalWrite(K5,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K5,HIGH);

  mask = 0x08;
  scan();
  digitalWrite(K4,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K4,HIGH);

  mask = 0x10;
  scan();
  digitalWrite(K3,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K3,HIGH);

  mask = 0x20;
  scan();
  digitalWrite(K2,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K2,HIGH);

  mask = 0x40;
  scan();
  digitalWrite(K1,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K1,HIGH);

  mask = 0x80;
  scan();
  digitalWrite(K0,LOW);
  for(d=0;d<INTEN;d++){}
  digitalWrite(K0,HIGH);
  
}


void Clear_Display_Ram(void){
  unsigned char rcount;
  for(rcount = 0; rcount < 37; rcount++)
    Display_Ram[rcount] = 0xff;
}

void scan(void){
  char countj;
  for (countj=32;countj>(-1);countj--){
    if ((Display_Ram[countj] & mask) == mask)
      digitalWrite(DAT,LOW);
    else
      digitalWrite(DAT,HIGH);
    clock();
  }
  strobe();
}

void clock(void){
  digitalWrite(CLK,HIGH);			// clock hi
  digitalWrite(CLK,LOW);		        // clock low
}

void strobe(void){
  digitalWrite(STR,HIGH);			// strobe hi
  digitalWrite(STR,LOW);			// strobe low
}

I'm a little troubled by this:

      strcat (sms_text_final,"     ");
      strcat (sms_text_final,sms_text);
      strcat (sms_text_final,"           ~");
      inbox[inboxCtr] = sms_text_final;

You keep concatenating to sms_text_final. Won't it eventually run out of space?

sorry forgot to add a reset for var sms_text_final, the purpose is to add spaces before and an ending " ~ " to terminate as the LED matrix sample code requires

should be:

would putting var declaration inside checkSMS() fix the problem as shown below

...
void checkSMS() 
{
  char sms_text_final[160];
  ...

the problem is, the next time i send a message, the program does not enter the condition " if (position > 0) { ", im really thinking the ::IsSMSPresent is not returning any value on the 2nd time he's called.

JethroXV: would putting var declaration inside checkSMS() fix the problem as shown below

No.

applying what said in this link http://stackoverflow.com/questions/632846/clearing-a-char-array-c

...
void checkSMS() 
{
  memset(&sms_text_final[0], 0, sizeof(sms_text_final));
  ...

Hi, I really need to read the 2nd message =(

Hi, just try to read the position following the one returned by IsSMSPresent.

Reason: I don't know the library, but I guess it sends a command that list all the unread sms messages and marks them as read. But it only returns the position of the first unread message. So the next time you call IsSMSPresent you get no results, but if there was more than one message the other messages will still be there. So, if the position is, say, 3, try to read position 4, 5, ... until you get an error.

spatula:
Hi, just try to read the position following the one returned by IsSMSPresent.

Reason: I don’t know the library, but I guess it sends a command that list all the unread sms messages and marks them as read. But it only returns the position of the first unread message. So the next time you call IsSMSPresent you get no results, but if there was more than one message the other messages will still be there. So, if the position is, say, 3, try to read position 4, 5, … until you get an error.

Hi!

i have added a code to know where the gsm.comm_buf start and end

p_char = strchr((char *)gsm.comm_buf,':');
if (p_char != NULL) {
          ret_val = atoi(p_char+1);
		  Serial.print("PCHAR IS NOT NULL : ");
		  Serial.println((char *)gsm.comm_buf);
		  Serial.println("END ");
        }

this is the first message in serial monitor

PCHAR IS NOT NULL :
+CMGL: 5,“REC UNREAD”,"+639175086850","",“13/03/20,16:34:30+32”
Cccccc

OK

END

and here is the 2nd

PCHAR IS NOT NULL :
+CMT: “+639175086850”,"",“13/03/20,16:41:14+32”
Hello World

+CMGL: 7,“REC UNREAD”,"+639175086850","",“13/03/20,16:41:14+32”
Hello World

OK

END

notice that in the 2nd buff, there is a +CMT:
since the function ::IsSMSPresent is getting the first occurrence of “:”

p_char = strchr((char *)gsm.comm_buf,':');

it will get the position of that of CMT not the CMGL with position beside it

how do i code the ::IsSMSPresent to look all of the gsm.comm_buf with CMGL as key not just “:”?

Post all your code, not just a couple of lines.

in sms.cpp

char SMSGSM::IsSMSPresent(byte required_status) 
{
  char ret_val = -1;
  char *p_char;
  byte status;

  if (CLS_FREE != gsm.GetCommLineStatus()) return (ret_val);
  gsm.SetCommLineStatus(CLS_ATCMD);
  ret_val = 0; // still not present

  switch (required_status) {
    case SMS_UNREAD:
      gsm.SimpleWriteln(F("AT+CMGL=\"REC UNREAD\""));
      break;
    case SMS_READ:
      gsm.SimpleWriteln(F("AT+CMGL=\"REC READ\""));
      break;
    case SMS_ALL:
      gsm.SimpleWriteln(F("AT+CMGL=\"ALL\""));
      break;
  }

  // 5 sec. for initial comm tmout
  // and max. 1500 msec. for inter character timeout
  gsm.RxInit(5000, 1500); 
  // wait response is finished
  do {
    if (gsm.IsStringReceived("OK")) { 
      // perfect - we have some response, but what:

      // there is either NO SMS:
      // <CR><LF>OK<CR><LF>

      // or there is at least 1 SMS
      // +CMGL: <index>,<stat>,<oa/da>,,[,<tooa/toda>,<length>]
      // <CR><LF> <data> <CR><LF>OK<CR><LF>
      status = RX_FINISHED;
      break; // so finish receiving immediately and let's go to 
             // to check response 
    }
    status = gsm.IsRxFinished();
  } while (status == RX_NOT_FINISHED);

  


  switch (status) {
    case RX_TMOUT_ERR:
      // response was not received in specific time
      ret_val = -2;
      break;

    case RX_FINISHED:
      // something was received but what was received?
      // ---------------------------------------------
      if(gsm.IsStringReceived("+CMGL:")) { 
        // there is some SMS with status => get its position
        // response is:
        // +CMGL: <index>,<stat>,<oa/da>,,[,<tooa/toda>,<length>]
        // <CR><LF> <data> <CR><LF>OK<CR><LF>
        p_char = strchr((char *)gsm.comm_buf,':');
        if (p_char != NULL) {
          ret_val = atoi(p_char+1);
        }
      }
      else {
        // other response like OK or ERROR
        ret_val = 0;
      }

      // here we have gsm.WaitResp() just for generation tmout 20msec. in case OK was detected
      // not due to receiving
      gsm.WaitResp(20, 20); 
      break;
  }

  gsm.SetCommLineStatus(CLS_FREE);
  return (ret_val);
}

JethroXV: how do i code the ::IsSMSPresent to look all of the gsm.comm_buf with CMGL as key not just ":"?

I wouldn't change IsSMSPresent, I would use sms.GetSMS() with the next position. I understand however that this is not very efficient once you have the output from CMGL. In order to use that output, search for the "+" that starts a new record in the response, or for the "OK" or "ERROR" that end the response, then examine the response code (if CMGL read the rest of the message until the next "+", "OK" or "ERROR", otherwise discard). For accuracy you should check that the terminating strings are at the beginning of a new line.

Issue update https://code.google.com/p/gsm-shield-arduino/issues/detail?id=69