AT+HTTPREAD request parser

I’m streaming data to my mysql with SIM900. Everything is fine.
I want to parse answer from webserver and split it to variables.

After GET request i send -

Serial2.println(“AT+HTTPREAD”);

and in serial monitor it gives me some numbers stored in mysql.

For examle
x,y,z.

I found this data parser and it works as i need but then i insert it in my code magic disappears.

const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.
 
#include <SoftwareSerial.h>
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.
 
SoftwareSerial SoftSer(11, 10); // RX, TX
 
void setup(){
  Serial.begin(9600);
  SoftSer.begin(9600);
}
 
void loop() {
    if (SoftSer.available() > 0) { //makes sure something is ready to be read
      static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
      char inchar = SoftSer.read(); //assigns one byte (as serial.read()'s only input one byte at a time
      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
      }
      else { //once the end of package marker has been read
        serialbuf[bufpos] = 0; //restart the buff
        bufpos = 0; //restart the position of the buff
 
        int x = atoi(subStr(serialbuf, ",", 1));
        int y = atoi(subStr(serialbuf, ",", 2));
        int z = atoi(subStr(serialbuf, ",", 3));
 
        Serial.print("The first number, x is: ");
        Serial.print(x);
        Serial.print(" - The second number, y is: ");
        Serial.print(y);
        Serial.print(" - The third number, z is: ");
        Serial.print(z);
        Serial.println();
 
      }
    }
}
 
char* subStr (char* input_string, char *separator, int segment_number) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;
  strcpy(copy, input_string);
  for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
    sub = strtok_r(act, separator, &ptr);
    if (sub == NULL) break;
  }
 return sub;
}

My sending and receiving function.

void GPRS()
{
        power_on();
 int k = 0;
 static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
 k = sprintf(commandbuffer, "&a=%d&b=%d&c=%d&d=%d&e=%d&f=%d&g=%d&h=%d&i=%d&j=%d&k=%d", t1, h1, w_t1, distance, w_t2, distance2, int_ph, ppm, light, fan, ram);

 sendATcommand("AT+HTTPINIT", "OK", 2000);

 sendATcommand("AT+HTTPPARA=\"CID\",\"1\"", "OK", 2000);

 
 Serial2.print("AT+HTTPPARA=\"URL\",\"gsmserver.esy.es/get.php?i=");
        Serial2.print(commandbuffer);
        Serial2.println("\"");
 delay(2000);

 sendATcommand("AT+HTTPACTION=0", "OK", 9000);
 

        // read server response
 Serial2.println("AT+HTTPREAD");
 delay(3000);
    if(Serial2.available() > 0)
        { //makes sure something is ready to be read
      char inchar = Serial2.read(); //assigns one byte (as serial.read()'s only input one byte at a time
      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
        Serial.print("DATA: ");
        Serial.print(serialbuf);
          
      }
      else { //once the end of package marker has been read
        serialbuf[bufpos] = 0; //restart the buff
        bufpos = 0; //restart the position of the buff
 
        tmax = atoi(subStr(serialbuf, ",", 1));
        thigh = atoi(subStr(serialbuf, ",", 2));
        tnorm = atoi(subStr(serialbuf, ",", 3));
        tmin = atoi(subStr(serialbuf, ",", 4));

 
        Serial.print("Tmax: ");
        Serial.print(tmax);
        Serial.print(" Thigh: ");
        Serial.print(thigh);
        Serial.print("Tnorm: ");
        Serial.print(tnorm);
        Serial.print("Tmin: ");
        Serial.print(tmin);
        Serial.println();
 
      }
    }

 Serial2.println("");

 sendATcommand("AT+HTTPTERM", "OK", 2000);

 Serial2.println("");
}

Which Arduino are you using Serial2 and SoftwareSerial on? Why?

      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
        Serial.print("DATA: ");
        Serial.print(serialbuf);
          
      }

serialBuf is NOT a string. Do NOT pass it to a function that expects a string.

Learn what make a char array a string.

PaulS: Which Arduino are you using Serial2 and SoftwareSerial on? Why?

      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
        Serial.print("DATA: ");
        Serial.print(serialbuf);
          
      }

serialBuf is NOT a string. Do NOT pass it to a function that expects a string.

Learn what make a char array a string.

Hi Paul, thanks for attention. I just copied example of data parser, I'm using Serial2 in my sketch.

This is AT command sequence and SIM900 answers.

AT+HTTPINIT
OK

AT+HTTPPARA="CID","1"
OK

AT+HTTPPARA="URL","gsmserver.esy.es/get.php?i=&a=20&b=60&c=20

AT+HTTPACTION=0
+HTTPACTION:0,200,13
OK

AT+HTTPREAD
+HTTPREAD:13
50,40,35,30. 
OK

AT+HTTPTERM
OK

I want to use this numbers 50,40,35,30. to change value of variables, that are using to control relays. As I understanded in Arduino using Strings is not a good idea, because they are heavy for RAM but they have good built in functions to work with them... Sorry for my bad English(

This is AT command sequence and SIM900 answers.

How am I supposed to make sense of that? Anonymous printing sucks.

but they have good built in functions to work with them...

ALL of which are based on string functions.

It is my code to send data.

void GPRS()
{
        power_on();
        int k = 0;
        k = sprintf(commandbuffer, "&a=%d&b=%d&c=%d&d=%d&e=%d&f=%d&g=%d&h=%d&i=%d&j=%d&k=%d", t1, h1, w_t1, distance, w_t2, distance2, int_ph, ppm, light, fan, ram);

        sendATcommand("AT+HTTPINIT", "OK", 2000);
        sendATcommand("AT+HTTPPARA=\"CID\",\"1\"", "OK", 2000);

        // set http param value
        Serial2.print("AT+HTTPPARA=\"URL\",\"gsmserver.esy.es/get.php?i=");
        Serial2.print(commandbuffer);
        Serial2.println("\"");
        delay(2000);
        toSerial();


        Serial2.println("AT+HTTPACTION=0");
        delay(8000);
        toSerial();

        // read server response
        Serial2.println("AT+HTTPREAD");
        delay(2000);
      toSerial();
    
        Serial2.println("");
        sendATcommand("AT+HTTPTERM", "OK", 2000);
}

How to divide these answer into parts if it is stored in charArray.

+HTTPREAD:13
50,40,35,30.
OK

How to divide these answer into parts if it is stored in charArray.

The simple answer is "Don't store them all in one char array". The data is (apparently) separated into records. The first record starts with +. The only real useful data that it contains is the number of characters in the next record.

You could just discard the first record. You need to save the next record. Parse it, when the cr/lf arrives, using strtok(), with a comma as the delimiter, to get the 4 tokens ("50", "40", "35", and "30"). Convert each token to an int (atoi()) and store in the appropriate variable.