Retrieving data from SIM900 module

Hi..i have been working on SIM900 module for the past three days.Everything seems to be working fine. I am able to retrieve a data from the server using AT+HTTPREAD command. It returns something like this

+HTTPACTION:0,200,15
AT+HTTPREAD

+HTTPREAD :15
[{"abc" : "150"}]
OK

I need to get [{"abc" : "150"}] alone and use it for some other purpose. can you please just help me out with this.?

It returns something like this

Something like that? Or exactly that?

That is, does the value after the : define the number of characters in the response? Does the response include the [ and ], or did you add those?

It returns exactly like this [{"abc" : "150"}].

The value after : is not the response length. The total response length is 15.

It is just a value i am fetching from the database which is in JSON...Also i am getting the response in an array so the [] comes along with the response.

Also i am getting the response in an array so the [] comes along with the response.

So, you know that the interesting data starts with the '[' and ends with the ']'.

Given that, I really can't think of a single way of storing only the interesting data or of using the ArduinoJSON library to parse it. Sorry.

Say for instance, if am getting the server response as 10. It will be displayed in the terminal as

+HTTPREAD:2
10
OK

What needs to be done is, I have to store the value in a separate variable(a=10) like this. Is it possible?..How to get the value(10) alone from the response.?

Is it possible?

Yes. The response starts with +HTTPREAD, followed by a : and a number of characters, followed by a carriage return and/or line feed, followed by the n characters.

You can tell when to start storing the data (possibly in a different place) when the carriage return or line feed arrives. It would be smart to have saved the characters before the CR or LF, so you can determine how many characters to expect.

Since you haven't posted any code, I'm operating on the assumption that you don't need help with the coding.

As per paulS suggestion, I have modified the code, Below is the code

#include <SoftwareSerial.h>
SoftwareSerial GSM(7, 8); // RX, TX

enum _parseState {
  PS_DETECT_MSG_TYPE,

  PS_IGNORING_COMMAND_ECHO,

  PS_HTTPACTION_TYPE,
  PS_HTTPACTION_RESULT,
  PS_HTTPACTION_LENGTH,

  PS_HTTPREAD_LENGTH,
  PS_HTTPREAD_CONTENT
};

byte parseState = PS_DETECT_MSG_TYPE;
char buffer[80];
byte pos = 0;

int i;
char ans[50];
char ans1;
String data;
int contentLength = 0;

void resetBuffer() {
  memset(buffer, 0, sizeof(buffer));
  pos = 0;
}

void sendGSM(const char* msg, int waitMs = 500) {
  GSM.println(msg);
  delay(waitMs);
  while(GSM.available()) {
    parseATText(GSM.read());
    
  }
}

void setup()
{
  GSM.begin(9600);
  Serial.begin(9600);
  
  sendGSM("AT+SAPBR=3,1,\"APN\",\"airtelgprs.com\"");  
  sendGSM("AT+SAPBR=1,1",3000);
  sendGSM("AT+HTTPINIT");  
  sendGSM("AT+HTTPPARA=\"CID\",1");
  sendGSM("AT+HTTPPARA=\"URL\",\"http://219.90.67.70:9000/rrt/rest/Billing_info?id=2\"");
  sendGSM("AT+HTTPACTION=0");
  
}

void loop()
{  
  while(GSM.available()) {
    parseATText(GSM.read());
    
  }
}

void parseATText(byte b) {

  buffer[pos++] = b;
     
  if ( pos >= sizeof(buffer) )
    resetBuffer(); // just to be safe

  /*
   // Detailed debugging
   Serial.println();
   Serial.print("state = ");
   Serial.println(state);
   Serial.print("b = ");
   Serial.println(b);
   Serial.print("pos = ");
   Serial.println(pos);
   Serial.print("buffer = ");
   Serial.println(buffer);*/

  switch (parseState) {
  case PS_DETECT_MSG_TYPE: 
    {
      if ( b == '\n' )
        resetBuffer();
      else 
      {        
        if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) 
        {
          parseState = PS_IGNORING_COMMAND_ECHO;
        }
        else if ( b == ':' ) 
        {
          //Serial.print("Checking message type: ");
          //Serial.println(buffer);

          if ( strcmp(buffer, "+HTTPACTION:") == 0 ) 
          {
            Serial.println("Received HTTPACTION");
            parseState = PS_HTTPACTION_TYPE;
          }
          else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) 
          {
            Serial.println("Received HTTPREAD");            
            parseState = PS_HTTPREAD_LENGTH;
          }
          resetBuffer();
        }
      }
    }
    break;

  case PS_IGNORING_COMMAND_ECHO:
    {
      if ( b == '\n' ) {
        Serial.print("Ignoring echo: ");
        Serial.println(buffer);
        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_TYPE:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION type is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_RESULT;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_RESULT:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION result is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_LENGTH;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_LENGTH:
    {
      if ( b == '\n' ) {
        Serial.print("HTTPACTION length is ");
        Serial.println(buffer);
        
        // now request content
        GSM.print("AT+HTTPREAD=0,");
        GSM.println(buffer);
        
        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_LENGTH:
    {
      if ( b == '\n' ) {
        contentLength = atoi(buffer);
        Serial.print("HTTPREAD length is ");
        Serial.println(contentLength);
        
        Serial.print("HTTPREAD content: ");
        
        parseState = PS_HTTPREAD_CONTENT;
        
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_CONTENT:
    {
      // for this demo I'm just showing the content bytes in the serial monitor
      //Serial.println(contentLength);
     //Serial.write(b);
    
     
     ans[i]=b;
     i++;
     
     
     contentLength--;
     
      if ( contentLength <= 0 ) {
        
        // all content bytes have now been read
       
        parseState = PS_DETECT_MSG_TYPE;
         
        resetBuffer();
      }
      
    }
    
    break;
   
  }
 
}

The switch case PS_HTTPREAD_CONTENT prints the response via Serial.print(b) whereas i need to store the response in a variable. So what i did is, i have stored the 'b' in an array called ans*. Can you please tell me, where to print this array?*

Can you please tell me, where to print this array?

Only you have any idea where or when you want to print it. ans is a char array, but it is NOT a string, because you do not NULL terminate the array.

     ans[i]=b;
     i++;
     ans[i] = '\0';

Now, ans IS a string.

How to take this String value outside the function? I need to print the ans in PS_HTTPREAD_LENGTH next to the Serial.print("HTTPREAD content: ");

How to get the response of

myGsm.println("AT+HTTPREAD=0,20");// read the data from the website you access
delay(3000);

printSerialData();

in a variable ? As i need to take this value for further processing, i have to store the value in a variable.

Code for reference,

#include <SoftwareSerial.h>

SoftwareSerial myGsm(7,8);
void setup()
{
myGsm.begin(9600);
Serial.begin(9600);
delay(500);

myGsm.println("AT+CGATT=1");
delay(200);
printSerialData();

myGsm.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");//setting the SAPBR,connection type is GPRS
delay(1000);
printSerialData();

myGsm.println("AT+SAPBR=3,1,\"www.airtelgprs.com\",\"\"");//setting the APN,2nd parameter empty works for all networks
delay(5000);
printSerialData();

myGsm.println();
myGsm.println("AT+SAPBR=1,1");
delay(10000);
printSerialData();

myGsm.println("AT+HTTPINIT"); //init the HTTP request
delay(2000);
printSerialData();

//myGsm.println("AT+HTTPPARA=\"URL\",\"http://api.thingspeak.com/apps/thinghttp/send_request?api_key=VV7WQ9DS19E2BNNI\"");// setting the httppara,
myGsm.println("AT+HTTPPARA=\"URL\",\"http://api.thingspeak.com/apps/thinghttp/send_request?api_key=AP6AK0Z3APH3RDNY\"");// setting the httppara,
//the second parameter is the website from where you want to access data
delay(1000);
printSerialData();

myGsm.println();
myGsm.println("AT+HTTPACTION=0");//submit the GET request
delay(8000);//the delay is important if the return datas are very large, the time required longer.
printSerialData();


myGsm.println("AT+HTTPREAD=0,20");// read the data from the website you access
delay(3000);

printSerialData();
//val=printSerialData();


//myGsm.println("");
delay(1000);

myGsm.println("AT+HTTPTERM");// terminate HTTP service
printSerialData();
}
void loop()
{
}
void printSerialData()
{
while(myGsm.available()!=0)
Serial.write(myGsm.read());
}

Following are the response of my code,

AT+HTTPPARA="URL","http://api.thingspeak.com/apps/thinghttp/sen
AT+HTTPACTION=0

OK

+HTTPACTION:0,200,14
AT+HTTPREAD=0,20

+HTTPREAD:14
1,208,047 hits
OK

How can i save the value (1,208,047 hits) in a variable i.e., the response of myGsm.println("AT+HTTPREAD=0,20"). Can you please help me out?

Can you please help me out?

No. You seem to not understand that sending AT commands and getting responses are NOT synchronous activities.

printSerialData() does exactly that. It prints whatever data has arrived since the last time it was called. That might be a partial response, a complete response, or several responses.

It does NOT store the response anywhere.

If you are going to expect that received data is received in response to some command, you will need to tell the function to wait until the complete response has been received, you will need to make the function store the response somewhere, AND you will need to make the function understand what command the data is in response to, so that it can use that information to decide where to store the data.