One strategy were:
wait for a line beginning with "+IPD"
wait for the next empty line
grab the next line and return it
Code you could insert
// example usage
Serial.print("* parsetest: ");
char* result = (char*)dateContent(buff, buffLen);
Serial.print("result '");
Serial.print(result);
Serial.print("' len ");
Serial.println(strlen(result));
// implementation
const int buffLen = 100;
byte buff[buffLen];
enum {
sStart, // collect line until CR, if "+IPD" next state
sScan, // collect line until CR, if empty next state
sStore, // collect line until CR, then next state
sDeliver // zero terminate result, leave parser
};
byte* dateContent(byte* buf, int bufLen) {
byte sState = sStart;
byte cPos = 0;
byte inByte;
bufLen -= 2; // adjust to maxStorePos
while (sState != sDeliver) {
if (Serial.available()) {
if (10 == (inByte = Serial.read())) {
continue; // ignore LF
}
switch (sState) {
case sStart:
if (inByte == 13) {
if (!strncmp((char*)buf, "+IPD", 4)) { // prelude found
sState = sScan;
}
cPos = 0; // drop line
} else {
if (cPos < bufLen) {
buf[cPos++] = inByte; // store if possible
}
}
break;
case sScan:
if (inByte == 13) {
if (!cPos) { // prelude found
sState = sStore;
}
cPos = 0; // drop line
} else {
if (cPos < bufLen) {
buf[cPos++] = inByte; // store if possible
}
}
break;
case sStore:
if (inByte != 13) {
if (cPos < buffLen) {
buf[cPos++] = inByte; // store if possible
}
} else {
buf[cPos] = 0;
sState = sDeliver; // exit parser
}
break;
}
}
}
return buf;
}
Testprogramm using your original data (maybe without LF but that is ignored anyway)
class dummySerial {
public:
dummySerial() {};
void begin(char* readStart, int len) {
rCurr = readStart;
rEnd = readStart + len;
}
int available() {
return rEnd - rCurr;
};
byte read() {
return (rCurr < rEnd) ? *rCurr++ : 0;
};
char* rCurr;
char* rEnd;
};
dummySerial Cerial;
char testInput[] = "\r+IPD,0,637:HTTP/1.1 200 OK\rContent-Type: text/html; charset=utf-8\rConnection: close\rStatus: 200 OK\rX-Frame-Options: ALLOWALL\rAccess-Control-Allow-Origin: *\rAccess-Control-Allow-Methods: GET, POST, PUT, OPTIONS, DELETE, PATCH\rAccess-Control-Allow-Headers: origin, content-type, X-Requested-With\rAccess-Control-Max-Age: 1800\rETag: \"6618644d86bb40f12eefc8f3f59cd42e\"\rCache-Control: max-age=0, private, must-revalidate\rX-Request-Id: 54474c64-10bc-4dc6-9bc4-4d893915a6eb\rX-Runtime: 0.095279\rX-Powered-By: Phusion Passenger 4.0.57\rDate: Sun, 01 Nov 2015 17:54:56 GMT\rServer: nginx/1.9.3 + Phusion Passenger 4.0.57\r\rSun, 01/11/2015, 17:54\rOK\r\r";
const int buffLen = 100;
byte buff[buffLen];
enum {
sStart, // collect line until CR, if "+IPD" next state
sScan, // collect line until CR, if empty next state
sStore, // collect line until CR, then next state
sDeliver // zero terminate result, leave parser
};
byte* dateContent(byte* buf, int bufLen) {
byte sState = sStart;
byte cPos = 0;
byte inByte;
bufLen -= 2; // adjust to maxStorePos
while (sState != sDeliver) {
if (Cerial.available()) { // CHANGE TO YOUR SERIAL
if (10 == (inByte = Cerial.read())) { // CHANGE TO YOUR SERIAL
continue; // ignore LF
}
switch (sState) {
case sStart:
if (inByte == 13) {
if (!strncmp((char*)buf, "+IPD", 4)) { // prelude found
sState = sScan;
}
cPos = 0; // drop line
} else {
if (cPos < bufLen) {
buf[cPos++] = inByte; // store if possible
}
}
break;
case sScan:
if (inByte == 13) {
if (!cPos) { // prelude found
sState = sStore;
}
cPos = 0; // drop line
} else {
if (cPos < bufLen) {
buf[cPos++] = inByte; // store if possible
}
}
break;
case sStore:
if (inByte != 13) {
if (cPos < buffLen) {
buf[cPos++] = inByte; // store if possible
}
} else {
buf[cPos] = 0;
sState = sDeliver; // exit parser
}
break;
}
}
}
return buf;
}
byte* dateContent(byte* buf, int bufLen);
void setup() {
Cerial.begin(testInput, strlen(testInput));
Serial.begin(115200);
Serial.print("* parsetest: ");
char* result = (char*)dateContent(buff, buffLen);
Serial.print("result '");
Serial.print(result);
Serial.print("' len ");
Serial.println(strlen(result));
}
void loop() {}
Output
* parsetest: result 'Sun, 01/11/2015, 17:54' len 22