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: 2018年4月07日 01:22:58 GMT
Server: Apache/2.4.9 (Win32) PHP/5.5.12
Last-Modified: 2018年4月07日 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 ?
1 Answer 1
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
1001