Q:

Parsing HTTP get response to extract values

Basically I created a web page to control 4 channel relay, then I made an HTTP get request from that page and got the following response:
Linked

T+CIPSEND=4,50

> GET /ard/sensor.html HTTP/1.1
Host: localho
SEND OK

+IPD,4,351:HTTP/1.1 200 OK
Date: Sat, 07 Apr 2018 01:22:58 GMT
Server: Apache/2.4.9 (Win32) PHP/5.5.12
Last-Modified: Sat, 07 Apr 2018 01:17:13 GMT
ETag: "72-56937eec1c277"
Accept-Ranges: bytes
Content-Length: 114
Content-Type: text/html

<p> Relay1 = 1#  </p> </br>
<p> Relay2 = 0#  </p> </br>
<p> Relay3 = 0#  </p> </br>
<p> Relay4 = 1#  </p> </br>
OK

OK
Unlink

Now I want to store Relay1 status (which is 1 here) in a variable, also all other Relays in order to control them high or low
Note : # is supposed to be the separator
and here is my code:
    #include <SoftwareSerial.h>

const int LED_PIN = 13;

String ssid = "ABC";
String password = "a14102016a";
const byte rxPin = 6;
const byte txPin = 7;

SoftwareSerial ESP8266 (rxPin, txPin);

unsigned long lastTimeMillis = 0;

void setup() {

  Serial.begin(9600);
  ESP8266.begin(9600);
  reset();
  connectWifi();
  delay(2000);
}

//reset the esp8266 module

void reset() {

  ESP8266.println("AT+RST");
  ESP8266.println("AT+CIOBAUD=9600");
  delay(1000);

  if (ESP8266.find("OK") ) Serial.println("Module Reset");

}

//connect to your wifi network
void connectWifi() {

  String cmd = "AT+CWJAP=\"" + ssid + "\",\"" + password + "\"";
  ESP8266.println(cmd);

  delay(4000);

  if (ESP8266.find("OK")) {

    Serial.println("Connected!"); 

  }

  else {

    connectWifi();

    Serial.println("connect to wifi");
  }

}

void printResponse() {
  while (ESP8266.available()) {
    Serial.println(ESP8266.readStringUntil('\n'));
  }
}

void loop() {

  if (millis() - lastTimeMillis > 30000) {
    lastTimeMillis = millis();

    ESP8266.println("AT+CIPMUX=1");
    delay(1000);
    printResponse();

    ESP8266.println("AT+CIPSTART=4,\"TCP\",\"192.168.1.161\",80");
    delay(1000);
    printResponse();

    String cmd = "GET /ard/sensor.html HTTP/1.1\r\nHost: localhost";
    ESP8266.println("AT+CIPSEND=4," + String(cmd.length() + 4));
    delay(1000);

    ESP8266.println(cmd);
    delay(1000);
    ESP8266.println("");    
  }
  if (ESP8266.available()) {
    Serial.write(ESP8266.read());

Byte R[ ] = ESP8266.read () ;
Serial write (R[ ]);

//    if (readString.indexOf("Relay1=1">0)) 
{
    Serial.write("found");
}
  }

}

Any suggestions ? 

A:

First of all, I would avoid using the String class, because of the
memory fragmentation issues that come with it.  The most obvious solution
is probably to store the result in a character array, then parse the
array, with strstr() or sscanf(), to extract the values you want. 
However, this requires storing the whole response in RAM, which is
expensive.  A better option is to parse the string as it comes, character
by character, using a kind of finite state machine. 
Here is how I would do it.  First, I assume you know what you want to do
with these values.  Since I don't, I will instead use this dummy function
to just print the values out to the serial port:
static void parse_relay_callback(uint8_t index, uint8_t value)
{
    Serial.print("parsed: relay ");
    Serial.print(index);
    Serial.print(": ");
    Serial.println(value);
}

You will have to replace this with whatever is appropriate for your
application. 
Then here is the parser:
static void parse_relay(char c)
{
    static const char templ[] = "RelayI = V#"; // I: index, V: value
    static uint8_t pos, index, value;
    char expected = templ[pos++];
    if (expected == 'I' && c >= '0' && c <= '4')
        index = c - '0';
    else if (expected == 'V' && (c == '0' || c == '1'))
        value = c - '0';
    else if (expected == '#' && c == '#')
        parse_relay_callback(index, value);
    else if (c ! = expected)
        pos = 0;
}

You just feed it one character at a time, with something like:
while (ESP8266.available())
    parse_relay(ESP8266.read());

Feeding the parser with your response example gives the following on the
serial port:
parsed: relay 1: 1
parsed: relay 2: 0
parsed: relay 3: 0
parsed: relay 4: 1

